Local symbols use linear array searches now, there was a bug, when removing from map we are leaving holes it makes some entries unreachable
This commit is contained in:
@@ -44,35 +44,42 @@ sym_insert(Sym *sym){
|
|||||||
Sym *is_sym = (Sym *)map_get(&pctx->syms, hash);
|
Sym *is_sym = (Sym *)map_get(&pctx->syms, hash);
|
||||||
if(is_sym){
|
if(is_sym){
|
||||||
parsing_error(sym->ast->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);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if(pctx->scope > 0){
|
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);
|
pctx->local_syms.add(sym);
|
||||||
}
|
}
|
||||||
|
else{
|
||||||
map_insert(&pctx->syms, hash, sym);
|
map_insert(&pctx->syms, hash, sym);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function Sym *
|
function Sym *
|
||||||
sym_get(Intern_String name){
|
sym_get(Intern_String name){
|
||||||
Sym *result = (Sym *)map_get(&pctx->syms, hash_string(name.s));
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function S64
|
function S64
|
||||||
scope_push(){
|
scope_open(){
|
||||||
S64 local_sym_count = pctx->local_syms.len;
|
S64 local_sym_count = pctx->local_syms.len;
|
||||||
pctx->scope++;
|
pctx->scope++;
|
||||||
return local_sym_count;
|
return local_sym_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
function void
|
function void
|
||||||
scope_pop(S64 local_sym_count){
|
scope_close(S64 local_sym_count){
|
||||||
pctx->scope--;
|
pctx->scope--;
|
||||||
assert(pctx->scope >= 0);
|
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;
|
pctx->local_syms.len = local_sym_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,11 +255,11 @@ eval_stmt(Ast *ast, Ast_Resolved_Type *ret){
|
|||||||
For(node->ifs){
|
For(node->ifs){
|
||||||
if(it[0]->init) eval_stmt(it[0]->init, ret);
|
if(it[0]->init) eval_stmt(it[0]->init, ret);
|
||||||
if(it[0]->expr) eval_expr(it[0]->expr);
|
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){
|
For_It(it[0]->block->stmts, jt){
|
||||||
eval_stmt(jt[0], ret);
|
eval_stmt(jt[0], ret);
|
||||||
}
|
}
|
||||||
scope_pop(scope_index);
|
scope_close(scope_index);
|
||||||
}
|
}
|
||||||
Ast_End();
|
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
|
function Operand
|
||||||
eval_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_complete){
|
eval_expr(Ast_Expr *ast, Ast_Resolved_Type *expected_type, Sym *lambda_to_complete){
|
||||||
switch(ast->kind){
|
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_Begin(AST_LAMBDA, Ast_Lambda){
|
||||||
Ast_Resolved_Type *type = eval_typespec(ast_typespec_lambda(0, node));
|
Ast_Resolved_Type *type = eval_typespec(ast_typespec_lambda(node->pos, node));
|
||||||
try_completing_lambda(lambda_to_complete, type);
|
|
||||||
|
|
||||||
// @todo: We also need to make sure there is a return value when ret type is not void
|
// @todo: We also need to make sure there is a return value when ret type is not void
|
||||||
if(node->block){
|
if(node->block){
|
||||||
S64 scope_index = scope_push();
|
S64 scope_index = scope_open();
|
||||||
For(node->args){
|
For(node->args){
|
||||||
Ast_Resolved_Type *type = eval_typespec(it[0]->typespec);
|
Ast_Resolved_Type *type = eval_typespec(it[0]->typespec);
|
||||||
Sym *arg_sym = sym_new_resolved(SYM_VAR, it[0]->name, type, it[0]);
|
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){
|
For(node->block->stmts){
|
||||||
eval_stmt(it[0], node->ret->resolved_type);
|
eval_stmt(it[0], node->ret->resolved_type);
|
||||||
}
|
}
|
||||||
scope_pop(scope_index);
|
scope_close(scope_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {type, true};
|
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
|
function void
|
||||||
resolve_sym(Sym *sym){
|
resolve_sym(Sym *sym){
|
||||||
if(sym->state == SYM_RESOLVED) return;
|
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);
|
assert(sym->ast->kind == AST_VAR || sym->ast->kind == AST_CONST);
|
||||||
sym->state = SYM_RESOLVING;
|
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);
|
Operand op = eval_decl(sym->ast, sym);
|
||||||
sym->type = op.type;
|
sym->type = op.type;
|
||||||
if(sym->kind == SYM_CONST){
|
if(sym->kind == SYM_CONST){
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
|
|
||||||
|
|
||||||
lambda :: (thing: int)
|
other_func :: ()
|
||||||
in_val := lambda
|
a_val := recursive_lambda
|
||||||
|
|
||||||
|
recursive_lambda :: (thing: int)
|
||||||
|
in_val := recursive_lambda
|
||||||
some_value := thing + const_in_lambda
|
some_value := thing + const_in_lambda
|
||||||
|
|
||||||
const_in_lambda :: 10
|
const_in_lambda :: 10
|
||||||
|
|||||||
Reference in New Issue
Block a user