From: Brendan Hansen Date: Wed, 2 Jun 2021 14:24:33 +0000 (-0500) Subject: bugfixes with polymorphic function calls with unresolved symbols X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=d0a60667514ade477b1d00fd8f7f6aa6922fa9e7;p=onyx.git bugfixes with polymorphic function calls with unresolved symbols --- diff --git a/bin/onyx b/bin/onyx index 407ea599..e9b6fe51 100755 Binary files a/bin/onyx and b/bin/onyx differ diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index a75694f1..01680a4f 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -232,7 +232,9 @@ typedef enum AstFlags { Ast_Flag_Has_Been_Symres = BH_BIT(26), - Ast_Flag_Static_If_Resolved = BH_BIT(27), + Ast_Flag_Has_Been_Checked = BH_BIT(27), + + Ast_Flag_Static_If_Resolved = BH_BIT(28), } AstFlags; typedef enum UnaryOp { @@ -796,6 +798,9 @@ struct AstFunction { OnyxToken* foreign_name; }; }; + + struct Entity* entity_header; + struct Entity* entity_body; }; struct AstOverloadedFunction { @@ -1017,7 +1022,7 @@ typedef struct EntityHeap { void entity_heap_init(EntityHeap* entities); void entity_heap_insert_existing(EntityHeap* entities, Entity* e); -void entity_heap_insert(EntityHeap* entities, Entity e); +Entity* entity_heap_insert(EntityHeap* entities, Entity e); Entity* entity_heap_top(EntityHeap* entities); void entity_heap_change_top(EntityHeap* entities, Entity* new_top); void entity_heap_remove_top(EntityHeap* entities); diff --git a/src/onyx.c b/src/onyx.c index dd22f2d9..dee800b2 100644 --- a/src/onyx.c +++ b/src/onyx.c @@ -333,8 +333,8 @@ static void output_dummy_progress_bar() { if (bh_arr_length(eh->entities) == 0) return; static const char* state_colors[] = { - "\e[91m", "\e[93m", "\e[94m", "\e[93m", "\e[97m", - "\e[95m", "\e[97m", "\e[95m", "\e[96m", "\e[92m", + "\e[91m", "\e[93m", "\e[94m", "\e[93m", + "\e[97m", "\e[95m", "\e[96m", "\e[92m", }; printf("\e[2;1H"); diff --git a/src/onyxchecker.c b/src/onyxchecker.c index 1725f282..76c3bd8a 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -146,7 +146,7 @@ CheckStatus check_if(AstIfWhile* ifnode) { CHECK(expression, &ifnode->cond); if (!type_is_bool(ifnode->cond->type)) { - onyx_report_error(ifnode->cond->token->pos, "expected boolean type for condition"); + onyx_report_error(ifnode->cond->token->pos, "Expected expression of type 'bool' for condition, got '%s'", type_get_name(ifnode->cond->type)); return Check_Error; } @@ -163,7 +163,7 @@ CheckStatus check_while(AstIfWhile* whilenode) { CHECK(expression, &whilenode->cond); if (!type_is_bool(whilenode->cond->type)) { - onyx_report_error(whilenode->cond->token->pos, "expected boolean type for condition"); + onyx_report_error(whilenode->cond->token->pos, "Expected expression of type 'bool' for condition, got '%s'", type_get_name(whilenode->cond->type)); return Check_Error; } @@ -405,6 +405,8 @@ CheckStatus check_call(AstCall* call) { // SPEED CLEANUP: Keeping an original copy for basically no reason except that sometimes you // need to know the baked argument values in code generation. + // This should only be done once, but right now it is being done everytime this is checked, + // which can be multiple if we have to yield on a callee's type. arguments_clone(&call->original_args, &call->args); if (call->callee->kind == Ast_Kind_Overloaded_Function) { @@ -426,10 +428,7 @@ CheckStatus check_call(AstCall* call) { // NOTE: Build callee's type fill_in_type((AstTyped *) callee); - if (callee->type == NULL) { - onyx_report_error(call->token->pos, "There was an error with looking up the type of this function."); - return Check_Error; - } + if (callee->type == NULL) return Check_Yield_Macro; if (callee->type->kind != Type_Kind_Function) { onyx_report_error(call->token->pos, @@ -1582,6 +1581,7 @@ CheckStatus check_block(AstBlock* block) { CheckStatus check_function(AstFunction* func) { if (func->flags & Ast_Flag_Already_Checked) return Check_Success; + if (func->entity_header && func->entity_header->state < Entity_State_Code_Gen) return Check_Yield_Macro; expected_return_type = func->type->Function.return_type; if (func->body) { @@ -1809,6 +1809,7 @@ CheckStatus check_type(AstType* type) { CheckStatus check_static_if(AstIf* static_if) { expression_types_must_be_known = 1; CheckStatus result = check_expression(&static_if->cond); + if (result == Check_Yield_Macro) return Check_Yield_Macro; expression_types_must_be_known = 0; if (result > Check_Errors_Start || !(static_if->cond->flags & Ast_Flag_Comptime)) { @@ -1866,21 +1867,14 @@ void check_entity(Entity* ent) { switch (ent->type) { case Entity_Type_Foreign_Function_Header: - case Entity_Type_Function_Header: - cs = check_function_header(ent->function); - break; - - case Entity_Type_Function: - cs = check_function(ent->function); - break; - - case Entity_Type_Overloaded_Function: - cs = check_overloaded_function(ent->overloaded_function); - break; - - case Entity_Type_Global: - cs = check_global(ent->global); - break; + case Entity_Type_Function_Header: cs = check_function_header(ent->function); break; + case Entity_Type_Function: cs = check_function(ent->function); break; + case Entity_Type_Overloaded_Function: cs = check_overloaded_function(ent->overloaded_function); break; + case Entity_Type_Global: cs = check_global(ent->global); break; + case Entity_Type_Struct_Member_Default: cs = check_struct_defaults((AstStructType *) ent->type_alias); break; + case Entity_Type_Memory_Reservation_Type: cs = check_memres_type(ent->mem_res); break; + case Entity_Type_Memory_Reservation: cs = check_memres(ent->mem_res); break; + case Entity_Type_Static_If: cs = check_static_if(ent->static_if); break; case Entity_Type_Expression: cs = check_expression(&ent->expr); @@ -1894,28 +1888,10 @@ void check_entity(Entity* ent) { cs = check_type(ent->type_alias); break; - case Entity_Type_Struct_Member_Default: - cs = check_struct_defaults((AstStructType *) ent->type_alias); - break; - - case Entity_Type_Memory_Reservation_Type: - cs = check_memres_type(ent->mem_res); - break; - - case Entity_Type_Memory_Reservation: - cs = check_memres(ent->mem_res); - break; - - case Entity_Type_Static_If: - cs = check_static_if(ent->static_if); - break; - default: break; } - if (cs == Check_Success) ent->state = Entity_State_Code_Gen; - if (cs == Check_Complete) ent->state = Entity_State_Finalized; - else if (cs == Check_Yield_Macro) { - ent->macro_attempts++; - } + if (cs == Check_Success) ent->state = Entity_State_Code_Gen; + if (cs == Check_Complete) ent->state = Entity_State_Finalized; + if (cs == Check_Yield_Macro) ent->macro_attempts++; } diff --git a/src/onyxentities.c b/src/onyxentities.c index 8020dfe5..630ae73f 100644 --- a/src/onyxentities.c +++ b/src/onyxentities.c @@ -4,8 +4,8 @@ static inline i32 entity_phase(Entity* e1) { if (e1->state <= Entity_State_Parse) return 1; - if (e1->state < Entity_State_Code_Gen) return 2; - return 3; + if (e1->state < Entity_State_Code_Gen) return 3; + return 4; } // NOTE: Returns >0 if e1 should be processed after e2. @@ -96,11 +96,10 @@ void entity_heap_insert_existing(EntityHeap* entities, Entity* e) { entities->all_count[e->state][e->type]++; } -// nocheckin -// Temporary wrapper -void entity_heap_insert(EntityHeap* entities, Entity e) { +Entity* entity_heap_insert(EntityHeap* entities, Entity e) { Entity* entity = entity_heap_register(entities, e); entity_heap_insert_existing(entities, entity); + return entity; } Entity* entity_heap_top(EntityHeap* entities) { @@ -134,8 +133,8 @@ void entity_heap_remove_top(EntityHeap* entities) { // NOTE(Brendan Hansen): Uses the entity heap in the context structure void add_entities_for_node(bh_arr(Entity *) *target_arr, AstNode* node, Scope* scope, Package* package) { -#define ENTITY_INSERT(_ent) { \ - Entity* entity = entity_heap_register(entities, _ent); \ +#define ENTITY_INSERT(_ent) \ + entity = entity_heap_register(entities, _ent); \ if (target_arr) { \ bh_arr(Entity *) __tmp_arr = *target_arr; \ bh_arr_push(__tmp_arr, entity); \ @@ -143,9 +142,10 @@ void add_entities_for_node(bh_arr(Entity *) *target_arr, AstNode* node, Scope* s } else { \ entity_heap_insert_existing(entities, entity); \ } \ - } + EntityHeap* entities = &context.entities; + Entity* entity; Entity ent; ent.state = Entity_State_Resolve_Symbols; @@ -187,10 +187,12 @@ void add_entities_for_node(bh_arr(Entity *) *target_arr, AstNode* node, Scope* s ent.type = Entity_Type_Function_Header; ent.function = (AstFunction *) node; ENTITY_INSERT(ent); + ((AstFunction *) node)->entity_header = entity; ent.type = Entity_Type_Function; ent.function = (AstFunction *) node; ENTITY_INSERT(ent); + ((AstFunction *) node)->entity_body = entity; } break; } diff --git a/src/onyxsymres.c b/src/onyxsymres.c index eaed4488..b053f77e 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -819,6 +819,7 @@ SymresStatus symres_function_header(AstFunction* func) { SymresStatus symres_function(AstFunction* func) { if (func->scope == NULL) func->scope = scope_create(context.ast_alloc, curr_scope, func->token->pos); + if (func->entity_header && func->entity_header->state < Entity_State_Check_Types) return Symres_Yield_Macro; scope_enter(func->scope); diff --git a/src/onyxutils.c b/src/onyxutils.c index 321f4a4d..f0c1b9c0 100644 --- a/src/onyxutils.c +++ b/src/onyxutils.c @@ -324,8 +324,11 @@ static b32 add_solidified_function_entities(AstSolidifiedFunction solidified_fun .scope = solidified_func.poly_scope, }; - entity_heap_insert(&context.entities, func_header_entity); - entity_heap_insert(&context.entities, func_entity); + Entity* entity_header = entity_heap_insert(&context.entities, func_header_entity); + Entity* entity_body = entity_heap_insert(&context.entities, func_entity); + + solidified_func.func->entity_header = entity_header; + solidified_func.func->entity_body = entity_body; return 1; } @@ -1268,6 +1271,8 @@ AstStructType* polymorphic_struct_lookup(AstPolyStructType* ps_type, bh_arr(AstP } void entity_bring_to_state(Entity* ent, EntityState state) { + EntityState last_state = ent->state; + while (ent->state != state) { switch (ent->state) { case Entity_State_Resolve_Symbols: symres_entity(ent); break; @@ -1277,6 +1282,9 @@ void entity_bring_to_state(Entity* ent, EntityState state) { default: return; } + if (ent->state == last_state) break; + last_state = ent->state; + if (onyx_has_errors()) return; } }