static ifs are very powerful now
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 7 Feb 2021 13:56:11 +0000 (07:56 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 7 Feb 2021 13:56:11 +0000 (07:56 -0600)
bin/onyx
include/onyxastnodes.h
include/onyxutils.h
onyx.exe
src/onyxbuiltins.c
src/onyxchecker.c
src/onyxentities.c
src/onyxparser.c
src/onyxsymres.c
src/onyxutils.c

index afcd5eb80909097c837d22c919b829b8d6b0577e..680972bd76d755268bd55c3e10828561f5025f59 100755 (executable)
Binary files a/bin/onyx and b/bin/onyx differ
index 29c2ef9710edc1fdc9a3251b1e48d49401ea9e92..274b97c0fea5f922866f8159c52204db720f813f 100644 (file)
@@ -703,8 +703,12 @@ struct AstInclude       { AstNode_base; char* name; };
 struct AstUsePackage    {
     AstNode_base;
 
-    AstPackage *package;
+    OnyxToken *package_name;
+    Package *package;
+
     OnyxToken *alias;
+    AstPackage *alias_node;
+
     bh_arr(AstAlias *) only;
 };
 struct AstAlias         {
@@ -924,7 +928,9 @@ extern const char* entity_type_strings[Entity_Type_Count];
 typedef struct Entity {
     EntityType type;
     EntityState state;
-    u64 attempts;
+    u32 attempts;
+
+    b32 entered_in_queue : 1;
 
     Package *package;
     Scope *scope;
@@ -976,6 +982,11 @@ struct Package {
 
     Scope *scope;
     Scope *private_scope;
+
+    // NOTE: This tracks all of the 'use package' statements of this package throughout
+    // the code base. This is used when a static if clears and new symbols are introduced.
+    // 'use package' statements have to be reevaluated to pull in the new symbols.
+    bh_arr(Entity *) use_package_entities;
 };
 
 typedef enum CompileAction CompileAction;
@@ -1053,7 +1064,7 @@ extern AstBasicType basic_type_v128;
 // :TypeExprHack
 extern AstNode type_expr_symbol;
 
-extern AstNode   builtin_package_node;
+extern OnyxToken builtin_package_token;
 extern AstNumLit builtin_heap_start;
 extern AstGlobal builtin_stack_top;
 extern AstType  *builtin_string_type;
index 90963f3fd19271dadb77965ac99cae4444572480..37fa8d640b8a73e6cf6fdb8a9e5ee57dd56e2fee 100644 (file)
@@ -12,6 +12,8 @@ const char* onyx_ast_node_kind_string(AstKind kind);
 
 Package* package_lookup(char* package_name);
 Package* package_lookup_or_create(char* package_name, Scope* parent_scope, bh_allocator alloc);
+void package_track_use_package(Package* package, Entity* entity);
+void package_reinsert_use_packages(Package* package);
 
 void scope_include(Scope* target, Scope* source, OnyxFilePos pos);
 b32 symbol_introduce(Scope* scope, OnyxToken* tkn, AstNode* symbol);
index 9b264008afb2259deafa043e919f8eecd8ad68e4..262152ee431c2ba9cf3db3eb35f915108a46ddc2 100644 (file)
Binary files a/onyx.exe and b/onyx.exe differ
index 4ce2a2565000cf07202df732aec7cff60347a401..d036182dcf094b2733e8b930ade7c3f8c931bbc4 100644 (file)
@@ -30,8 +30,7 @@ AstBasicType basic_type_f32x4 = { Ast_Kind_Basic_Type, 0, &simd_token, "f32x4",
 AstBasicType basic_type_f64x2 = { Ast_Kind_Basic_Type, 0, &simd_token, "f64x2", &basic_types[Basic_Kind_F64X2] };
 AstBasicType basic_type_v128  = { Ast_Kind_Basic_Type, 0, &simd_token, "v128",  &basic_types[Basic_Kind_V128]  };
 
-static OnyxToken builtin_package_token = { Token_Type_Symbol, 7, "builtin ", { 0 } };
-AstNode   builtin_package_node  = { Ast_Kind_Symbol, Ast_Flag_No_Clone, &builtin_package_token, NULL };
+OnyxToken builtin_package_token = { Token_Type_Symbol, 7, "builtin ", { 0 } };
 
 static OnyxToken builtin_heap_start_token = { Token_Type_Symbol, 12, "__heap_start ", { 0 } };
 static OnyxToken builtin_stack_top_token  = { Token_Type_Symbol, 11, "__stack_top ",  { 0 } };
index 59f2d0c7f930a41f3a20f652cc683df0221be424..bcd96fc6784de83fb4a8ea147d5f83ee60f8acdc 100644 (file)
@@ -1501,6 +1501,7 @@ CheckStatus check_expression(AstTyped** pexpr) {
 
         default:
             retval = Check_Error;
+            onyx_report_error(expr->token->pos, "UNEXPECTED INTERNAL COMPILER ERROR");
             DEBUG_HERE;
             break;
     }
@@ -1808,6 +1809,11 @@ CheckStatus check_static_if(AstStaticIf* static_if) {
         return Check_Error;
     }
 
+    if (!type_is_bool(static_if->cond->type)) {
+        onyx_report_error(static_if->token->pos, "Expected this condition to be a boolean value.");
+        return Check_Error;
+    }
+
     AstNumLit* condition_value = (AstNumLit *) static_if->cond;
     assert(condition_value->kind == Ast_Kind_NumLit); // This should be right, right?
 
index 17ec1a501d1eed179a4f42467f08860ba0b7802b..ed849d5b509283e72d1718e2297e8cbc4dd21588 100644 (file)
@@ -73,17 +73,21 @@ Entity* entity_heap_register(EntityHeap* entities, Entity e) {
     Entity* entity = bh_alloc_item(alloc, Entity);
     *entity = e;
     entity->attempts = 0;
+    entity->entered_in_queue = 0;
 
     return entity;
 }
 
 void entity_heap_insert_existing(EntityHeap* entities, Entity* e) {
+    if (e->entered_in_queue) return;
+
        if (entities->entities == NULL) {
                bh_arr_new(global_heap_allocator, entities->entities, 128);
-       }       
+       }
 
        bh_arr_push(entities->entities, e);
        eh_shift_up(entities, bh_arr_length(entities->entities) - 1);
+    e->entered_in_queue = 1;
 
        entities->state_count[e->state]++;
     entities->type_count[e->type]++;
@@ -115,6 +119,7 @@ void entity_heap_change_top(EntityHeap* entities, Entity* new_top) {
 void entity_heap_remove_top(EntityHeap* entities) {
     entities->state_count[entities->entities[0]->state]--;
     entities->type_count[entities->entities[0]->type]--;
+    entities->entities[0]->entered_in_queue = 0;
 
        entities->entities[0] = entities->entities[bh_arr_length(entities->entities) - 1];
        bh_arr_pop(entities->entities);
index bb140cb2fa579eb511d6ae129396a7f7518eb49f..7248fef384abf354a89046ac65d2c8eebc614b24 100644 (file)
@@ -1156,25 +1156,24 @@ static AstNode* parse_use_stmt(OnyxParser* parser) {
         AstUsePackage* upack = make_node(AstUsePackage, Ast_Kind_Use_Package);
         upack->token = use_token;
 
-        AstNode* pack_symbol = make_node(AstNode, Ast_Kind_Symbol);
-        pack_symbol->token = expect_token(parser, Token_Type_Symbol);
+        OnyxToken* package_name = expect_token(parser, Token_Type_Symbol);
 
         // CLEANUP: This is just gross.
         if (consume_token_if_next(parser, '.')) {
-            pack_symbol->token->length += 1;
+            package_name->length += 1;
 
             while (1) {
                 if (parser->hit_unexpected_token) break;
 
                 OnyxToken* symbol = expect_token(parser, Token_Type_Symbol);
-                pack_symbol->token->length += symbol->length;
+                package_name->length += symbol->length;
 
-                if (consume_token_if_next(parser, '.')) pack_symbol->token->length += 1;
+                if (consume_token_if_next(parser, '.')) package_name->length += 1;
                 else break;
             }
         }
 
-        upack->package = (AstPackage *) pack_symbol;
+        upack->package_name = package_name;
 
         if (consume_token_if_next(parser, Token_Type_Keyword_As))
             upack->alias = expect_token(parser, Token_Type_Symbol);
@@ -2427,7 +2426,7 @@ void onyx_parse(OnyxParser *parser) {
     bh_arr_push(parser->scope_stack, parser->file_scope);
 
     AstUsePackage* implicit_use_builtin = make_node(AstUsePackage, Ast_Kind_Use_Package);
-    implicit_use_builtin->package = (AstPackage *) &builtin_package_node;
+    implicit_use_builtin->package_name = &builtin_package_token;
     ENTITY_SUBMIT(implicit_use_builtin);
     
     while (parser->curr->type != Token_Type_End_Stream) {
index d4f9a428f2b1538902604f43ced7e5432f7039dc..e02cd155405f95a581ff26e9fd71dee19a11f0be 100644 (file)
@@ -854,13 +854,17 @@ static SymresStatus symres_overloaded_function(AstOverloadedFunction* ofunc) {
 }
 
 static SymresStatus symres_use_package(AstUsePackage* package) {
-    token_toggle_end(package->package->token);
-    Package* p = package_lookup(package->package->token->text);
-    token_toggle_end(package->package->token);
+    if (package->package == NULL) {
+        token_toggle_end(package->package_name);
+        package->package = package_lookup(package->package_name->text);
+        token_toggle_end(package->package_name);
+    }
+
+    Package* p = package->package;
 
     if (p == NULL) { // :SymresStall
         if (report_unresolved_symbols) {
-            onyx_report_error(package->token->pos, "package not found in included source files");
+            onyx_report_error(package->package_name->pos, "package not found in included source files");
             return Symres_Error;
         } else {
             return Symres_Yield;
@@ -870,11 +874,13 @@ static SymresStatus symres_use_package(AstUsePackage* package) {
     if (p->scope == curr_scope) return Symres_Success;
 
     if (package->alias != NULL) {
-        AstPackage *pac_node = onyx_ast_node_new(context.ast_alloc, sizeof(AstPackage), Ast_Kind_Package);
-        pac_node->package = p;
-        pac_node->token = package->alias;
+        if (!package->alias_node) {
+            package->alias_node = onyx_ast_node_new(context.ast_alloc, sizeof(AstPackage), Ast_Kind_Package);
+            package->alias_node->package = p;
+            package->alias_node->token = package->alias;
+        }
 
-        symbol_introduce(curr_scope, package->alias, (AstNode *) pac_node);
+        symbol_introduce(curr_scope, package->alias, (AstNode *) package->alias_node);
     }
 
     if (package->only != NULL) {
@@ -901,6 +907,7 @@ static SymresStatus symres_use_package(AstUsePackage* package) {
 
         scope_include(curr_scope, p->scope, pos);
     }
+
     return Symres_Success;
 }
 
@@ -1032,6 +1039,7 @@ void symres_entity(Entity* ent) {
     switch (ent->type) {
         case Entity_Type_Binding: {
             symbol_introduce(curr_scope, ent->binding->token, ent->binding->node);
+            package_reinsert_use_packages(curr_package);
             next_state = Entity_State_Finalized;
             break;
         }
@@ -1050,6 +1058,7 @@ void symres_entity(Entity* ent) {
         case Entity_Type_Global_Header:       ss = symres_global(ent->global); break;
 
         case Entity_Type_Use_Package:         ss = symres_use_package(ent->use_package);
+                                              if (ent->use_package->package) package_track_use_package(ent->use_package->package, ent);
                                               next_state = Entity_State_Finalized;
                                               break;
 
@@ -1074,4 +1083,5 @@ void symres_entity(Entity* ent) {
     if (ss == Symres_Yield)   ent->attempts++;
 
     if (ent->scope) curr_scope = old_scope;
+    curr_package = NULL;
 }
index c13a654e57acee1855c299580487b01a586290dd..ec76f05abe489a94ff11a9aeeabf75f2d1af852a 100644 (file)
@@ -37,6 +37,7 @@ Package* package_lookup_or_create(char* package_name, Scope* parent_scope, bh_al
         package->name = pac_name;
         package->scope = scope_create(alloc, parent_scope, (OnyxFilePos) { 0 });
         package->private_scope = scope_create(alloc, package->scope, (OnyxFilePos) { 0 });
+        package->use_package_entities = NULL;
 
         bh_table_put(Package *, context.packages, pac_name, package);
 
@@ -44,6 +45,25 @@ Package* package_lookup_or_create(char* package_name, Scope* parent_scope, bh_al
     }
 }
 
+void package_track_use_package(Package* package, Entity* entity) {
+    if (package->use_package_entities == NULL) {
+        bh_arr_new(global_heap_allocator, package->use_package_entities, 4);
+    }
+
+    bh_arr_push(package->use_package_entities, entity);
+}
+
+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;
+        entity_heap_insert_existing(&context.entities, *use_package);
+    } 
+
+    bh_arr_set_length(package->use_package_entities, 0);
+}
+
 
 //
 // Scoping
@@ -130,7 +150,7 @@ AstNode* symbol_resolve(Scope* start_scope, OnyxToken* tkn) {
     token_toggle_end(tkn);
     AstNode* res = symbol_raw_resolve(start_scope, tkn->text);
     token_toggle_end(tkn);
-    
+
     return res;
 }