bugfixes with polymorphic function calls with unresolved symbols
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 2 Jun 2021 14:24:33 +0000 (09:24 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 2 Jun 2021 14:24:33 +0000 (09:24 -0500)
bin/onyx
include/onyxastnodes.h
src/onyx.c
src/onyxchecker.c
src/onyxentities.c
src/onyxsymres.c
src/onyxutils.c

index 407ea599341575beec977b3bb52657ee4ab94e11..e9b6fe51867680d8a7e1827e297e9256ca2dd6f7 100755 (executable)
Binary files a/bin/onyx and b/bin/onyx differ
index a75694f1309fb5f8e02c30cc9b92c3a1dcec09e1..01680a4f43c321cc96e741808f2973522730e4a7 100644 (file)
@@ -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);
index dd22f2d9be362c51c04b5f6bf5ad3f2d116092ef..dee800b25c36c989adbb4a5bf7e890fc28505f03 100644 (file)
@@ -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");
index 1725f282eeb180777bb4f65009b963ce66ce1c9f..76c3bd8ad812d33c3fbf597d69ecb52ee8abf520 100644 (file)
@@ -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++;
 }
index 8020dfe5f74cb1056082adcb1130836f81e8b0e0..630ae73f394b36df891fcc992d6bd2cd66addb38 100644 (file)
@@ -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;
         }
index eaed4488e95b59f7d67d54c75351f6e7a3cb710c..b053f77e4a1627dbcfe35e7da3557126abdfa89d 100644 (file)
@@ -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);
 
index 321f4a4d4fb37dca648e500690446456e86c6b94..f0c1b9c02e44dcf4768550af3dcfc4c1fc1a443d 100644 (file)
@@ -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;
     }
 }