Lambdas, statements, typechecking lambdas
This commit is contained in:
106
new_resolve.cpp
106
new_resolve.cpp
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user