Lambdas, statements, typechecking lambdas

This commit is contained in:
Krzosa Karol
2022-05-25 14:44:30 +02:00
parent 9dc2e1588d
commit b945f3affd
8 changed files with 229 additions and 118 deletions

View File

@@ -11,7 +11,7 @@ enum Sym_Kind{
struct Sym{
Intern_String name;
Sym_Kind kind;
Ast_Decl *decl;
Ast *ast;
Ast_Resolved_Type *type;
union{
S64 int_val;
@@ -33,27 +33,57 @@ global Ast_Decl empty_decl = {};
function void
sym_insert(Sym *sym){
U64 hash = hash_string(sym->name.s);
Sym *is_sym = (Sym *)map_get_u64(&pctx->global_syms, hash);
Sym *is_sym = (Sym *)map_get(&pctx->syms, hash);
if(is_sym){
parsing_error(sym->decl->pos, "Symbol with name: [%s] defined multiple times", sym->name.s.str);
parsing_error(sym->ast->pos, "Symbol with name: [%s] defined multiple times", sym->name.s.str);
}
if(pctx->scope > 0){
pctx->local_syms.add(sym);
}
map_insert_u64(&pctx->global_syms, hash, sym);
map_insert(&pctx->syms, hash, sym);
}
function Sym *
sym_get(Intern_String name){
Sym *result = (Sym *)map_get_u64(&pctx->global_syms, hash_string(name.s));
Sym *result = (Sym *)map_get(&pctx->syms, hash_string(name.s));
return result;
}
function S64
scope_push(){
S64 local_sym_count = pctx->local_syms.len;
pctx->scope++;
return local_sym_count;
}
function void
scope_pop(S64 local_sym_count){
pctx->scope--;
assert(pctx->scope >= 0);
for(S64 i = local_sym_count; i < pctx->local_syms.len; i++){
void *removed = map_remove(&pctx->syms, hash_string(pctx->local_syms.data[i]->name.s));
assert(removed);
}
pctx->local_syms.len = local_sym_count;
}
function Sym *
sym_new(Sym_Kind kind, Intern_String name, Ast_Resolved_Type *type, Ast_Decl *decl){
sym_new(Sym_Kind kind, Intern_String name, Ast_Resolved_Type *type, Ast *ast){
Sym *result = exp_alloc_type(pctx->perm, Sym);
result->name = name;
result->kind = kind;
result->type = type;
result->decl = decl;
result->ast = ast;
assert(ast);
map_insert(&pctx->resolved, ast, result);
return result;
}
function Sym *
resolved_get(Ast *ast){
Sym *result = (Sym *)map_get(&pctx->resolved, ast);
assert(result);
return result;
}
@@ -159,6 +189,40 @@ resolve_type_pair(Token *pos, Ast_Resolved_Type *a, Ast_Resolved_Type *b){
return result;
}
function void
eval_var(Ast_Decl *node){
Ast_Resolved_Type *type = eval_typespec(node->var.typespec);
Operand expr = node->var.expr ? eval_expr(node->var.expr, type) : Operand{};
Ast_Resolved_Type *resolved_type = resolve_type_pair(node->pos, type, expr.type);
Sym *sym = sym_new(SYM_Var, node->name, resolved_type, node);
sym_insert(sym);
}
function void
eval_stmt(Ast *ast, Ast_Resolved_Type *ret){
// @todo: need to check if all paths return a value
switch(ast->kind){
Ast_Begin(AST_RETURN, Ast_Return){
Operand op = {};
if(node->expr) op = eval_expr(node->expr);
if(!op.type && ret != type_void) parsing_error(node->pos, "Function expects a void return value but the returned value is [x]");
if(op.type && op.type != ret) parsing_error(node->pos, "Return statement has different type then returned value");
Ast_End();
}
Ast_Begin(AST_VAR, Ast_Decl){
eval_var(node);
Ast_End();
}
invalid_default_case;
}
}
function Operand
eval_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type){
switch(ast->kind){
@@ -226,13 +290,18 @@ eval_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type){
Ast_Begin(AST_LAMBDA, Ast_Lambda){
Ast_Resolved_Type *type = eval_typespec(ast_typespec_lambda(0, node));
// @todo: typecheck the function
// enter scope -
// push local syms etc.
// Make sure return type is matching function return type
// quit scope
For(node->block->stmts){
// @todo: We also need to make sure there is a return value when ret type is not void
if(node->block){
S64 scope_index = scope_push();
For(node->args){
Ast_Resolved_Type *type = eval_typespec(it[0]->typespec);
Sym *arg_sym = sym_new(SYM_Var, it[0]->name, type, it[0]);
sym_insert(arg_sym);
}
For(node->block->stmts){
eval_stmt(it[0], node->ret->resolved_type);
}
scope_pop(scope_index);
}
return {type, true};
@@ -366,12 +435,7 @@ eval_decl(Ast *ast){
}
Ast_Begin(AST_VAR, Ast_Decl){
Ast_Resolved_Type *type = eval_typespec(node->var.typespec);
Operand expr = node->var.expr ? eval_expr(node->var.expr, type) : Operand{};
Ast_Resolved_Type *resolved_type = resolve_type_pair(node->pos, type, expr.type);
Sym *sym = sym_new(SYM_Var, node->name, resolved_type, node);
sym_insert(sym);
eval_var(node);
Ast_End();
}
@@ -397,7 +461,7 @@ eval_decl(Ast *ast){
function void
test_resolve(){
TEST_PARSER();
String filename = "test3.kl"_s;
String filename = "globals.kl"_s;
String file_content = os_read_file(scratch, filename);
lex_restream(&ctx, file_content, filename);
Ast_Package *result = parse_file();