From 7c4b01cd922d9ce5e2dfb8b0e881a110c016d74a Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Thu, 26 May 2022 23:40:23 +0200 Subject: [PATCH] Local symbols use linear array searches now, there was a bug, when removing from map we are leaving holes it makes some entries unreachable --- new_resolve.cpp | 65 ++++++++++++++++++++++++------------ order_independent_globals.kl | 9 +++-- 2 files changed, 49 insertions(+), 25 deletions(-) diff --git a/new_resolve.cpp b/new_resolve.cpp index 3a901fa..b11c7ed 100644 --- a/new_resolve.cpp +++ b/new_resolve.cpp @@ -44,35 +44,42 @@ sym_insert(Sym *sym){ Sym *is_sym = (Sym *)map_get(&pctx->syms, hash); if(is_sym){ parsing_error(sym->ast->pos, "Symbol with name: [%s] defined multiple times", sym->name.s.str); + return; } if(pctx->scope > 0){ + For(pctx->local_syms){ + if(it[0]->name.str == sym->name.str) parsing_error(sym->ast->pos, "Symbol with name: [%s] defined multiple times", sym->name.s.str); + return; + } pctx->local_syms.add(sym); } - - map_insert(&pctx->syms, hash, sym); + else{ + map_insert(&pctx->syms, hash, sym); + } } function Sym * sym_get(Intern_String name){ Sym *result = (Sym *)map_get(&pctx->syms, hash_string(name.s)); + if(!result){ + For(pctx->local_syms){ + if(it[0]->name.str == name.str) return it[0]; + } + } return result; } function S64 -scope_push(){ +scope_open(){ S64 local_sym_count = pctx->local_syms.len; pctx->scope++; return local_sym_count; } function void -scope_pop(S64 local_sym_count){ +scope_close(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; } @@ -248,11 +255,11 @@ eval_stmt(Ast *ast, Ast_Resolved_Type *ret){ For(node->ifs){ if(it[0]->init) eval_stmt(it[0]->init, ret); if(it[0]->expr) eval_expr(it[0]->expr); - S64 scope_index = scope_push(); + S64 scope_index = scope_open(); For_It(it[0]->block->stmts, jt){ eval_stmt(jt[0], ret); } - scope_pop(scope_index); + scope_close(scope_index); } Ast_End(); } @@ -261,14 +268,6 @@ eval_stmt(Ast *ast, Ast_Resolved_Type *ret){ } } -function void -try_completing_lambda(Sym *sym, Ast_Resolved_Type *type){ - if(sym && sym->state == SYM_RESOLVING){ - sym->state = SYM_RESOLVED; - sym->type = type; - } -} - function Operand eval_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_complete){ switch(ast->kind){ @@ -333,12 +332,11 @@ eval_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_comple } Ast_Begin(AST_LAMBDA, Ast_Lambda){ - Ast_Resolved_Type *type = eval_typespec(ast_typespec_lambda(0, node)); - try_completing_lambda(lambda_to_complete, type); + Ast_Resolved_Type *type = eval_typespec(ast_typespec_lambda(node->pos, node)); // @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(); + S64 scope_index = scope_open(); For(node->args){ Ast_Resolved_Type *type = eval_typespec(it[0]->typespec); Sym *arg_sym = sym_new_resolved(SYM_VAR, it[0]->name, type, it[0]); @@ -347,7 +345,7 @@ eval_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_comple For(node->block->stmts){ eval_stmt(it[0], node->ret->resolved_type); } - scope_pop(scope_index); + scope_close(scope_index); } return {type, true}; @@ -495,6 +493,20 @@ eval_decl(Ast *ast, Sym *sym){ } } +function Ast_Lambda * +ast_get_lambda(Ast *ast){ + if(ast->kind == AST_CONST){ + auto ast_const = (Ast_Const *)ast; + if(ast_const->expr){ + auto ast_expr = ast_const->expr; + if(ast_expr->kind == AST_LAMBDA){ + return (Ast_Lambda *)ast_expr; + } + } + } + return 0; +} + function void resolve_sym(Sym *sym){ if(sym->state == SYM_RESOLVED) return; @@ -503,6 +515,15 @@ resolve_sym(Sym *sym){ assert(sym->ast->kind == AST_VAR || sym->ast->kind == AST_CONST); sym->state = SYM_RESOLVING; + + // @note: lambda doesn't need body for it to be usable + // quickly resolve the type so we can have recursive functions + Ast_Lambda *lambda = ast_get_lambda(sym->ast); + if(lambda){ + sym->type = eval_typespec(ast_typespec_lambda(lambda->pos, lambda)); + sym->state = SYM_RESOLVED; + } + Operand op = eval_decl(sym->ast, sym); sym->type = op.type; if(sym->kind == SYM_CONST){ diff --git a/order_independent_globals.kl b/order_independent_globals.kl index 0094336..ba9ca77 100644 --- a/order_independent_globals.kl +++ b/order_independent_globals.kl @@ -1,9 +1,12 @@ -lambda :: (thing: int) - in_val := lambda +other_func :: () + a_val := recursive_lambda + +recursive_lambda :: (thing: int) + in_val := recursive_lambda some_value := thing + const_in_lambda - + const_in_lambda :: 10 not_const := val + 10