MAYBE BREAKING CHANGE; everything can defer right now so order doesn't matter
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 2 Jun 2021 04:44:27 +0000 (23:44 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 2 Jun 2021 04:44:27 +0000 (23:44 -0500)
bin/onyx
include/onyxastnodes.h
src/onyx.c
src/onyxastnodes.c
src/onyxchecker.c
src/onyxentities.c
src/onyxsymres.c
src/onyxutils.c

index 15f113436b2d3c3ae7239277b2fc1ee2fae1a033..407ea599341575beec977b3bb52657ee4ab94e11 100755 (executable)
Binary files a/bin/onyx and b/bin/onyx differ
index 87c20fa2738a3f756ac504381771955086a77d7b..a75694f1309fb5f8e02c30cc9b92c3a1dcec09e1 100644 (file)
@@ -229,6 +229,10 @@ typedef enum AstFlags {
     Ast_Flag_Incomplete_Body       = BH_BIT(24),
 
     Ast_Flag_Array_Literal_Typed   = BH_BIT(25),
+
+    Ast_Flag_Has_Been_Symres       = BH_BIT(26),
+
+    Ast_Flag_Static_If_Resolved    = BH_BIT(27),
 } AstFlags;
 
 typedef enum UnaryOp {
@@ -924,8 +928,6 @@ typedef enum EntityState {
     Entity_State_Parse_Builtin,
     Entity_State_Introduce_Symbols,
     Entity_State_Parse,
-    Entity_State_Comptime_Resolve_Symbols,
-    Entity_State_Comptime_Check_Types,
     Entity_State_Resolve_Symbols,
     Entity_State_Check_Types,
     Entity_State_Code_Gen,
index ea6a5e58c24316b1de49bee8ec199c194320cf6c..dd22f2d9be362c51c04b5f6bf5ad3f2d116092ef 100644 (file)
@@ -318,12 +318,8 @@ static b32 process_entity(Entity* ent) {
             ent->state = Entity_State_Finalized;
             break;
 
-        case Entity_State_Comptime_Resolve_Symbols:
         case Entity_State_Resolve_Symbols: symres_entity(ent); break;
-
-        case Entity_State_Comptime_Check_Types:
         case Entity_State_Check_Types:     check_entity(ent);  break;
-        
         case Entity_State_Code_Gen:        emit_entity(ent);   break;
     }
 
index 4db5c8f50861aa4d263800664880ab6f833a444a..d185a243cd04a3e07b68138c790e52e885362b20 100644 (file)
@@ -111,8 +111,6 @@ const char* entity_state_strings[Entity_State_Count] = {
     "Parse Builtin",
     "Introduce Symbols",
     "Parse",
-    "Resolve Static Symbols",
-    "Check Static Types",
     "Resolve Symbols",
     "Check Types",
     "Code Gen",
index deafb06270a41e4da4d36483852c31b37f4f6ba8..1725f282eeb180777bb4f65009b963ce66ce1c9f 100644 (file)
@@ -16,6 +16,7 @@ typedef enum CheckStatus {
     Check_Complete, // The node is done processing
 
     Check_Errors_Start,
+    Check_Yield_Macro,
     Check_Error,    // There was an error when checking the node
 } CheckStatus;
 
@@ -130,6 +131,10 @@ CheckStatus check_if(AstIfWhile* ifnode) {
     if (ifnode->assignment != NULL) CHECK(statement, (AstNode **) &ifnode->assignment);
 
     if (ifnode->kind == Ast_Kind_Static_If) {
+        if ((ifnode->flags & Ast_Flag_Static_If_Resolved) == 0) {
+            return Check_Yield_Macro;
+        }
+
         if (static_if_resolution(ifnode)) {
             if (ifnode->true_stmt != NULL) CHECK(statement, (AstNode **) &ifnode->true_stmt);
             
@@ -1816,6 +1821,8 @@ CheckStatus check_static_if(AstIf* static_if) {
         return Check_Error;
     }
 
+    static_if->flags |= Ast_Flag_Static_If_Resolved;
+
     b32 resolution = static_if_resolution(static_if);
 
     if (context.options->print_static_if_results)
@@ -1908,7 +1915,7 @@ void check_entity(Entity* ent) {
 
     if (cs == Check_Success)  ent->state = Entity_State_Code_Gen;
     if (cs == Check_Complete) ent->state = Entity_State_Finalized;
-    // else if (cs == Check_Yield) {
-    //     ent->attempts++;
-    // }
+    else if (cs == Check_Yield_Macro) {
+         ent->macro_attempts++;
+    }
 }
index 410d13ae3ef8f4d1024f70ccdd6acef4d53d51d2..8020dfe5f74cb1056082adcb1130836f81e8b0e0 100644 (file)
@@ -4,7 +4,7 @@
 
 static inline i32 entity_phase(Entity* e1) {
     if (e1->state <= Entity_State_Parse) return 1;
-    if (e1->state <= Entity_State_Comptime_Check_Types) return 2;
+    if (e1->state <  Entity_State_Code_Gen) return 2;
     return 3;
 }
 
@@ -13,17 +13,17 @@ static i32 entity_compare(Entity* e1, Entity* e2) {
     i32 phase1 = entity_phase(e1);
     i32 phase2 = entity_phase(e2);
 
-    if (phase1 != phase2 || phase1 != 2) {
-        if (e1->state != e2->state)
-            return (i32) e1->state - (i32) e2->state;
-        else if (e1->type != e2->type)
-            return (i32) e1->type - (i32) e2->type;
-        else
-            return (i32) (e1->micro_attempts - e2->micro_attempts);
-
-    } else {
+    if (phase1 != phase2)
+        return phase1 - phase2;
+    else if (e1->macro_attempts != e2->macro_attempts)
         return (i32) e1->macro_attempts - (i32) e2->macro_attempts;
-    }
+    else if (e1->state != e2->state)
+        return (i32) e1->state - (i32) e2->state;
+    else if (e1->type != e2->type)
+        return (i32) e1->type - (i32) e2->type;
+    else
+        return (i32) (e1->micro_attempts - e2->micro_attempts);
+
 }
 
 #define eh_parent(index) (((index) - 1) / 2)
@@ -258,7 +258,7 @@ void add_entities_for_node(bh_arr(Entity *) *target_arr, AstNode* node, Scope* s
         
         case Ast_Kind_Use: {
             if (((AstUse *) node)->expr->kind == Ast_Kind_Package) {
-                ent.state = Entity_State_Comptime_Resolve_Symbols;
+                ent.state = Entity_State_Resolve_Symbols;
                 ent.type = Entity_Type_Use_Package;
             } else {
                 ent.type = Entity_Type_Use;
@@ -288,7 +288,7 @@ void add_entities_for_node(bh_arr(Entity *) *target_arr, AstNode* node, Scope* s
         }
 
         case Ast_Kind_Static_If: {
-            ent.state = Entity_State_Comptime_Resolve_Symbols;
+            ent.state = Entity_State_Resolve_Symbols;
             ent.type = Entity_Type_Static_If;
             ent.static_if = (AstIf *) node;
             ENTITY_INSERT(ent);
index fefc9295cebc2dfe9c5d4319b6cffc1c8be44669..eaed4488e95b59f7d67d54c75351f6e7a3cb710c 100644 (file)
@@ -499,6 +499,10 @@ static SymresStatus symres_if(AstIfWhile* ifnode) {
     }
 
     if (ifnode->kind == Ast_Kind_Static_If) {
+        if ((ifnode->flags & Ast_Flag_Static_If_Resolved) == 0) {
+            return Symres_Yield_Macro;
+        }
+
         if (static_if_resolution(ifnode)) {
             if (ifnode->true_stmt != NULL)  SYMRES(statement, (AstNode **) &ifnode->true_stmt, NULL);
             
@@ -818,52 +822,56 @@ SymresStatus symres_function(AstFunction* func) {
 
     scope_enter(func->scope);
 
-    bh_arr_each(AstParam, param, func->params) {
-        symbol_introduce(curr_scope, param->local->token, (AstNode *) param->local);
-
-        // CLEANUP: Currently, in order to 'use' parameters, the type must be completely
-        // resolved and built. This is excessive because all that should need to be known
-        // is the names of the members, since all that happens is implicit field accesses
-        // are placed in the scope. So instead, there should be a way to just query all the
-        // member names in the structure, without needing to know their type. This would be
-        // easy if it were not for 'use' statements in structs. It is made even more complicated
-        // by this situtation:
-        //
-        //     Foo :: struct (T: type_expr) {
-        //         use t : T;
-        // 
-        //         something_else := 5 + 6 * 8;
-        //     }
-        //
-        // The 'use t : T' member requires completely knowing the type of T, to know which
-        // members should be brought in. At the moment, that requires completely building the
-        // type of Foo($T).
-        if (param->local->flags & Ast_Flag_Param_Use) {
-            if (param->local->type_node != NULL && param->local->type == NULL) {
-                param->local->type = type_build_from_ast(context.ast_alloc, param->local->type_node);
-            }
-
-            if (type_is_struct(param->local->type)) {
-                Type* st;
-                if (param->local->type->kind == Type_Kind_Struct) {
-                    st = param->local->type;
-                } else {
-                    st = param->local->type->Pointer.elem;
+    if ((func->flags & Ast_Flag_Has_Been_Symres) == 0) {
+        func->flags |= Ast_Flag_Has_Been_Symres;
+
+        bh_arr_each(AstParam, param, func->params) {
+            symbol_introduce(curr_scope, param->local->token, (AstNode *) param->local);
+
+            // CLEANUP: Currently, in order to 'use' parameters, the type must be completely
+            // resolved and built. This is excessive because all that should need to be known
+            // is the names of the members, since all that happens is implicit field accesses
+            // are placed in the scope. So instead, there should be a way to just query all the
+            // member names in the structure, without needing to know their type. This would be
+            // easy if it were not for 'use' statements in structs. It is made even more complicated
+            // by this situtation:
+            //
+            //     Foo :: struct (T: type_expr) {
+            //         use t : T;
+            // 
+            //         something_else := 5 + 6 * 8;
+            //     }
+            //
+            // The 'use t : T' member requires completely knowing the type of T, to know which
+            // members should be brought in. At the moment, that requires completely building the
+            // type of Foo($T).
+            if (param->local->flags & Ast_Flag_Param_Use) {
+                if (param->local->type_node != NULL && param->local->type == NULL) {
+                    param->local->type = type_build_from_ast(context.ast_alloc, param->local->type_node);
                 }
 
-                bh_table_each_start(StructMember, st->Struct.members);
-                    AstFieldAccess* fa = make_field_access(context.ast_alloc, (AstTyped *) param->local, value.name);
-                    symbol_raw_introduce(curr_scope, value.name, param->local->token->pos, (AstNode *) fa);
-                bh_table_each_end;
+                if (type_is_struct(param->local->type)) {
+                    Type* st;
+                    if (param->local->type->kind == Type_Kind_Struct) {
+                        st = param->local->type;
+                    } else {
+                        st = param->local->type->Pointer.elem;
+                    }
 
-            } else if (param->local->type != NULL) {
-                onyx_report_error(param->local->token->pos, "Can only 'use' structures or pointers to structures.");
+                    bh_table_each_start(StructMember, st->Struct.members);
+                        AstFieldAccess* fa = make_field_access(context.ast_alloc, (AstTyped *) param->local, value.name);
+                        symbol_raw_introduce(curr_scope, value.name, param->local->token->pos, (AstNode *) fa);
+                    bh_table_each_end;
 
-            } else {
-                // :ExplicitTyping
-                onyx_report_error(param->local->token->pos, "Cannot deduce type of parameter '%b'; Try adding it explicitly.",
-                    param->local->token->text,
-                    param->local->token->length);
+                } else if (param->local->type != NULL) {
+                    onyx_report_error(param->local->token->pos, "Can only 'use' structures or pointers to structures.");
+
+                } else {
+                    // :ExplicitTyping
+                    onyx_report_error(param->local->token->pos, "Cannot deduce type of parameter '%b'; Try adding it explicitly.",
+                        param->local->token->text,
+                        param->local->token->length);
+                }
             }
         }
     }
@@ -1113,11 +1121,7 @@ void symres_entity(Entity* ent) {
             break;
         }
 
-        case Entity_Type_Static_If: {
-            ss = symres_static_if(ent->static_if);
-            next_state = Entity_State_Comptime_Check_Types;
-            break;
-        }
+        case Entity_Type_Static_If:               ss = symres_static_if(ent->static_if); break;
         
         case Entity_Type_Foreign_Function_Header:
         case Entity_Type_Function_Header:         ss = symres_function_header(ent->function); break;
@@ -1151,9 +1155,13 @@ void symres_entity(Entity* ent) {
         default: break;
     }
 
-    if (ss == Symres_Success)     ent->state = next_state;
     if (ss == Symres_Yield_Macro) ent->macro_attempts++;
     if (ss == Symres_Yield_Micro) ent->micro_attempts++;
+    if (ss == Symres_Success) {
+        ent->macro_attempts = 0;
+        ent->micro_attempts = 0;
+        ent->state = next_state;
+    }
 
     if (ent->scope) curr_scope = old_scope;
 }
index 0c5682074797acc353ff528bb095572733f5a595..321f4a4d4fb37dca648e500690446456e86c6b94 100644 (file)
@@ -57,7 +57,8 @@ void package_reinsert_use_packages(Package* package) {
     if (!package->use_package_entities) return;
 
     bh_arr_each(Entity *, use_package, package->use_package_entities) {
-        (*use_package)->state = Entity_State_Comptime_Resolve_Symbols;
+        (*use_package)->state = Entity_State_Resolve_Symbols;
+        (*use_package)->macro_attempts = 0;
         entity_heap_insert_existing(&context.entities, *use_package);
     }