changed: getting ready for onyx watch
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 21 Apr 2023 15:20:55 +0000 (10:20 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 21 Apr 2023 15:20:55 +0000 (10:20 -0500)
compiler/include/astnodes.h
compiler/src/builtins.c
compiler/src/checker.c
compiler/src/onyx.c
compiler/src/parser.c
compiler/src/utils.c

index 7f2c8e10ff3178f34f063a4974c76e3180745a02..c3e8c73a480a4c0c7cff4f55c53b5dba9c839f2f 100644 (file)
@@ -1667,6 +1667,18 @@ typedef struct OnyxDocInfo {
 } OnyxDocInfo;
 
 
+typedef struct CheckerData {
+    b32 expression_types_must_be_known;
+    b32 all_checks_are_final;
+    b32 inside_for_iterator;
+    bh_arr(AstFor *) for_node_stack;
+    bh_imap __binop_impossible_cache[Binary_Op_Count];
+    AstCall __op_maybe_overloaded;
+    Entity *current_entity;
+    bh_arr(Type **) expected_return_type_stack;
+} CheckerData;
+
+
 typedef struct CompileOptions CompileOptions;
 struct CompileOptions {
     bh_allocator allocator;
@@ -1728,8 +1740,14 @@ struct Context {
     struct SymbolInfoTable *symbol_info;
     struct OnyxDocInfo     *doc_info;
 
+    CheckerData checker;
+    u32 next_package_id;
+    u32 next_scope_id;
+
     u32 cycle_almost_detected : 2;
     b32 cycle_detected : 1;
+
+    b32 builtins_initialized : 1;
 };
 
 extern Context context;
@@ -1815,6 +1833,7 @@ extern IntrinsicTable intrinsic_table;
 extern bh_arr(OverloadOption) operator_overloads[Binary_Op_Count];
 extern bh_arr(OverloadOption) unary_operator_overloads[Unary_Op_Count];
 
+void prepare_builtins();
 void initialize_builtins(bh_allocator a);
 void initalize_special_globals();
 void introduce_build_options(bh_allocator a);
index 6491f3850e4a3e14c6d38d7af1d6240baef90b1b..671f2c160a22a83215d311ce1fb12f3a71f5e7a0 100644 (file)
@@ -376,6 +376,33 @@ static IntrinsicMap builtin_intrinsics[] = {
 bh_arr(OverloadOption) operator_overloads[Binary_Op_Count] = { 0 };
 bh_arr(OverloadOption) unary_operator_overloads[Unary_Op_Count] = { 0 };
 
+void prepare_builtins() {
+    builtin_string_type = NULL;
+    builtin_cstring_type = NULL;
+    builtin_range_type = NULL;
+    builtin_range_type_type = NULL;
+    builtin_vararg_type = NULL;
+    builtin_vararg_type_type = NULL;
+    builtin_context_variable = NULL;
+    builtin_allocator_type = NULL;
+    builtin_iterator_type = NULL;
+    builtin_optional_type = NULL;
+    builtin_callsite_type = NULL;
+    builtin_any_type = NULL;
+    builtin_code_type = NULL;
+    builtin_link_options_type = NULL;
+    builtin_package_id_type = NULL;
+
+    type_table_node = NULL;
+    foreign_blocks_node = NULL;
+    foreign_block_type = NULL;
+    tagged_procedures_node = NULL;
+    builtin_initialize_data_segments = NULL;
+    builtin_run_init_procedures = NULL;
+    init_procedures = NULL;
+    builtin_implicit_bool_cast = NULL;
+}
+
 void initialize_builtins(bh_allocator a) {
     // HACK
     builtin_package_token.text = bh_strdup(global_heap_allocator, builtin_package_token.text);
@@ -491,17 +518,21 @@ void initialize_builtins(bh_allocator a) {
         return;
     }
 
+    init_procedures = NULL;
     bh_arr_new(global_heap_allocator, init_procedures, 4);
 
     fori (i, 0, Binary_Op_Count) {
+        operator_overloads[i] = NULL;
         bh_arr_new(global_heap_allocator, operator_overloads[i], 4); 
     }
 
     fori (i, 0, Unary_Op_Count) {
+        unary_operator_overloads[i] = NULL;
         bh_arr_new(global_heap_allocator, unary_operator_overloads[i], 4); 
     }
 
     IntrinsicMap* intrinsic = &builtin_intrinsics[0];
+    intrinsic_table = NULL;
     while (intrinsic->name != NULL) {
         shput(intrinsic_table, intrinsic->name, intrinsic->intrinsic);
         intrinsic++;
index 9d30c0775f3b8ab963b3e7d755bccc9d5d22f2e3..2515038a5f563b4344a77216399a856be5ace0f2 100644 (file)
@@ -1,3 +1,4 @@
+#define BH_INTERNAL_ALLOCATOR (global_heap_allocator)
 #define BH_DEBUG
 #include "parser.h"
 #include "utils.h"
@@ -111,15 +112,6 @@ CheckStatus check_polyquery(AstPolyQuery *query);
 CheckStatus check_directive_first(AstDirectiveFirst *first);
 CheckStatus check_directive_export_name(AstDirectiveExportName *ename);
 
-// HACK HACK HACK
-b32 expression_types_must_be_known = 0;
-b32 all_checks_are_final           = 1;
-b32 inside_for_iterator            = 0;
-bh_arr(AstFor *) for_node_stack    = NULL;
-static bh_imap __binop_impossible_cache[Binary_Op_Count];
-static AstCall __op_maybe_overloaded;
-static Entity *current_entity = NULL;
-
 
 #define STATEMENT_LEVEL 1
 #define EXPRESSION_LEVEL 2
@@ -133,17 +125,14 @@ static inline void fill_in_type(AstTyped* node) {
     }
 }
 
-// HACK: This should be baked into a structure, not a global variable.
-static bh_arr(Type **) expected_return_type_stack = NULL;
-
 CheckStatus check_return(AstReturn* retnode) {
     Type ** expected_return_type;
     
-    if (retnode->count >= (u32) bh_arr_length(expected_return_type_stack)) {
+    if (retnode->count >= (u32) bh_arr_length(context.checker.expected_return_type_stack)) {
         ERROR_(retnode->token->pos, "Too many repeated 'return's here. Expected a maximum of %d.",
-                bh_arr_length(expected_return_type_stack));
+                bh_arr_length(context.checker.expected_return_type_stack));
     }
-    expected_return_type = expected_return_type_stack[bh_arr_length(expected_return_type_stack) - retnode->count - 1];
+    expected_return_type = context.checker.expected_return_type_stack[bh_arr_length(context.checker.expected_return_type_stack) - retnode->count - 1];
 
     if (retnode->expr) {
         CHECK(expression, &retnode->expr);
@@ -353,22 +342,22 @@ CheckStatus check_for(AstFor* fornode) {
 
 
 fornode_expr_checked:
-    bh_arr_push(for_node_stack, fornode);
+    bh_arr_push(context.checker.for_node_stack, fornode);
 
-    old_inside_for_iterator = inside_for_iterator;
-    inside_for_iterator = 0;
+    old_inside_for_iterator = context.checker.inside_for_iterator;
+    context.checker.inside_for_iterator = 0;
     iter_type = fornode->iter->type;
     if (type_struct_constructed_from_poly_struct(iter_type, builtin_iterator_type)) {
-        inside_for_iterator = 1;
+        context.checker.inside_for_iterator = 1;
     }
 
     do {
         CheckStatus cs = check_block(fornode->stmt);
-        inside_for_iterator = old_inside_for_iterator;
+        context.checker.inside_for_iterator = old_inside_for_iterator;
         if (cs > Check_Errors_Start) return cs;
     } while(0);
 
-    bh_arr_pop(for_node_stack);
+    bh_arr_pop(context.checker.for_node_stack);
     return Check_Success;
 }
 
@@ -817,7 +806,7 @@ static void report_bad_binaryop(AstBinaryOp* binop) {
 }
 
 static AstCall* binaryop_try_operator_overload(AstBinaryOp* binop, AstTyped* third_argument) {
-    if (bh_arr_length(operator_overloads[binop->operation]) == 0) return &__op_maybe_overloaded;
+    if (bh_arr_length(operator_overloads[binop->operation]) == 0) return &context.checker.__op_maybe_overloaded;
 
     if (binop->overload_args == NULL || binop->overload_args->values[1] == NULL) {
         if (binop->overload_args == NULL) {
@@ -829,12 +818,12 @@ static AstCall* binaryop_try_operator_overload(AstBinaryOp* binop, AstTyped* thi
         if (binop_is_assignment(binop->operation)) {
             binop->overload_args->values[0] = (AstTyped *) make_address_of(context.ast_alloc, binop->left);
 
-            u32 current_all_checks_are_final = all_checks_are_final;
-            all_checks_are_final = 0;
+            u32 current_all_checks_are_final = context.checker.all_checks_are_final;
+            context.checker.all_checks_are_final = 0;
             u32 current_checking_level_store = current_checking_level;
             CheckStatus cs = check_address_of((AstAddressOf **) &binop->overload_args->values[0]);
             current_checking_level = current_checking_level_store;
-            all_checks_are_final   = current_all_checks_are_final;
+            context.checker.all_checks_are_final   = current_all_checks_are_final;
 
             if (cs == Check_Yield_Macro)      return (AstCall *) &node_that_signals_a_yield;
             if (cs == Check_Error)            return NULL;
@@ -862,7 +851,7 @@ static AstCall* binaryop_try_operator_overload(AstBinaryOp* binop, AstTyped* thi
 }
 
 static AstCall* unaryop_try_operator_overload(AstUnaryOp* unop) {
-    if (bh_arr_length(unary_operator_overloads[unop->operation]) == 0) return &__op_maybe_overloaded;
+    if (bh_arr_length(unary_operator_overloads[unop->operation]) == 0) return &context.checker.__op_maybe_overloaded;
 
     if (unop->overload_args == NULL || unop->overload_args->values[0] == NULL) {
         if (unop->overload_args == NULL) {
@@ -1231,7 +1220,7 @@ CheckStatus check_binaryop(AstBinaryOp** pbinop) {
         binop->flags |= Ast_Flag_Comptime;
     }
 
-    if (expression_types_must_be_known) {
+    if (context.checker.expression_types_must_be_known) {
         if (binop->left->type == NULL || binop->right->type == NULL) {
             ERROR(binop->token->pos, "Internal compiler error: one of the operands types is unknown here.");
         }
@@ -1242,13 +1231,13 @@ CheckStatus check_binaryop(AstBinaryOp** pbinop) {
 
         u64 cache_key = 0;
         if (binop->left->type && binop->right->type) {
-            if (!__binop_impossible_cache[binop->operation].hashes) {
-                bh_imap_init(&__binop_impossible_cache[binop->operation], global_heap_allocator, 256);
+            if (!context.checker.__binop_impossible_cache[binop->operation].hashes) {
+                bh_imap_init(&context.checker.__binop_impossible_cache[binop->operation], global_heap_allocator, 256);
             }
 
             cache_key = ((u64) (binop->left->type->id) << 32ll) | (u64) binop->right->type->id;
 
-            if (bh_imap_has(&__binop_impossible_cache[binop->operation], cache_key)) {
+            if (bh_imap_has(&context.checker.__binop_impossible_cache[binop->operation], cache_key)) {
                 goto definitely_not_op_overload;
             }
         }
@@ -1258,7 +1247,7 @@ CheckStatus check_binaryop(AstBinaryOp** pbinop) {
         if (implicit_call == (AstCall *) &node_that_signals_a_yield)
             YIELD(binop->token->pos, "Trying to resolve operator overload.");
 
-        if (implicit_call != NULL && implicit_call != &__op_maybe_overloaded) {
+        if (implicit_call != NULL && implicit_call != &context.checker.__op_maybe_overloaded) {
             // NOTE: Not a binary op
             implicit_call->next = binop->next;
             *pbinop = (AstBinaryOp *) implicit_call;
@@ -1267,8 +1256,8 @@ CheckStatus check_binaryop(AstBinaryOp** pbinop) {
             return Check_Success;
         }
 
-        if (cache_key && implicit_call != &__op_maybe_overloaded) {
-            bh_imap_put(&__binop_impossible_cache[binop->operation], cache_key, 1);
+        if (cache_key && implicit_call != &context.checker.__op_maybe_overloaded) {
+            bh_imap_put(&context.checker.__binop_impossible_cache[binop->operation], cache_key, 1);
         }
     }
 
@@ -1340,7 +1329,7 @@ CheckStatus check_binaryop(AstBinaryOp** pbinop) {
          binop->type = &basic_types[Basic_Kind_Bool];
     }
 
-    if (all_checks_are_final) {
+    if (context.checker.all_checks_are_final) {
         binop->flags |= Ast_Flag_Has_Been_Checked;
 
         if (binop->flags & Ast_Flag_Comptime) {
@@ -1403,7 +1392,7 @@ CheckStatus check_unaryop(AstUnaryOp** punop) {
     if (unaryop->operation == Unary_Op_Try) {
         AstCall* call = unaryop_try_operator_overload(unaryop);
         if (call == (AstCall *) &node_that_signals_a_yield) YIELD(unaryop->token->pos, "Waiting on potential operator overload.");
-        if (call != NULL && call != &__op_maybe_overloaded) {
+        if (call != NULL && call != &context.checker.__op_maybe_overloaded) {
             call->next = unaryop->next;
             *(AstCall **) punop = call;
 
@@ -1689,14 +1678,14 @@ CheckStatus check_do_block(AstDoBlock** pdoblock) {
 
     fill_in_type((AstTyped *) doblock);
 
-    bh_arr_push(expected_return_type_stack, &doblock->type);
+    bh_arr_push(context.checker.expected_return_type_stack, &doblock->type);
 
     doblock->block->rules = Block_Rule_Do_Block;
     CHECK(block, doblock->block);
 
     if (doblock->type == &type_auto_return) doblock->type = &basic_types[Basic_Kind_Void];
 
-    bh_arr_pop(expected_return_type_stack);
+    bh_arr_pop(context.checker.expected_return_type_stack);
 
     doblock->flags |= Ast_Flag_Has_Been_Checked;
     return Check_Success;
@@ -2336,7 +2325,7 @@ CheckStatus check_directive_solidify(AstDirectiveSolidify** psolid) {
 }
 
 CheckStatus check_remove_directive(AstDirectiveRemove *remove) {
-    if (!inside_for_iterator) {
+    if (!context.checker.inside_for_iterator) {
         ERROR(remove->token->pos, "#remove is only allowed in the body of a for-loop over an iterator.");
     }
 
@@ -2344,11 +2333,11 @@ CheckStatus check_remove_directive(AstDirectiveRemove *remove) {
 }
 
 CheckStatus check_directive_first(AstDirectiveFirst *first) {
-    if (bh_arr_length(for_node_stack) == 0) {
+    if (bh_arr_length(context.checker.for_node_stack) == 0) {
         ERROR(first->token->pos, "#first is only allowed in the body of a for-loop.");
     }
 
-    first->for_node = bh_arr_last(for_node_stack);
+    first->for_node = bh_arr_last(context.checker.for_node_stack);
     assert(first->for_node);
 
     first->for_node->has_first = 1;
@@ -2542,11 +2531,11 @@ CheckStatus check_function(AstFunction* func) {
         }
     }
 
-    bh_arr_clear(expected_return_type_stack);
-    bh_arr_push(expected_return_type_stack, &func->type->Function.return_type);
+    bh_arr_clear(context.checker.expected_return_type_stack);
+    bh_arr_push(context.checker.expected_return_type_stack, &func->type->Function.return_type);
 
-    inside_for_iterator = 0;
-    if (for_node_stack) bh_arr_clear(for_node_stack);
+    context.checker.inside_for_iterator = 0;
+    if (context.checker.for_node_stack) bh_arr_clear(context.checker.for_node_stack);
 
     if (func->body) {
         CheckStatus status = check_block(func->body);
@@ -2558,8 +2547,8 @@ CheckStatus check_function(AstFunction* func) {
         }
     }
 
-    if (*bh_arr_last(expected_return_type_stack) == &type_auto_return) {
-        *bh_arr_last(expected_return_type_stack) = &basic_types[Basic_Kind_Void];
+    if (*bh_arr_last(context.checker.expected_return_type_stack) == &type_auto_return) {
+        *bh_arr_last(context.checker.expected_return_type_stack) = &basic_types[Basic_Kind_Void];
     }
 
     func->flags |= Ast_Flag_Has_Been_Checked;
@@ -3083,9 +3072,9 @@ CheckStatus check_type(AstType** ptype) {
 }
 
 CheckStatus check_static_if(AstIf* static_if) {
-    expression_types_must_be_known = 1;
+    context.checker.expression_types_must_be_known = 1;
     CheckStatus result = check_expression(&static_if->cond);
-    expression_types_must_be_known = 0;
+    context.checker.expression_types_must_be_known = 0;
     if (result == Check_Yield_Macro) return Check_Yield_Macro;
 
     if (result > Check_Errors_Start || !(static_if->cond->flags & Ast_Flag_Comptime)) {
@@ -3215,7 +3204,7 @@ CheckStatus check_process_directive(AstNode* directive) {
         if (inject->dest->kind == Ast_Kind_Package) {
             pac = ((AstPackage *) inject->dest)->package;
         } else {
-            pac = current_entity->package;
+            pac = context.checker.current_entity->package;
         }
 
         add_entities_for_node(NULL, (AstNode *) binding, scope, pac);
@@ -3541,7 +3530,8 @@ CheckStatus check_arbitrary_job(EntityJobData *job) {
 
 void check_entity(Entity* ent) {
     CheckStatus cs = Check_Success;
-    current_entity = ent;
+    context.checker.current_entity = ent;
+    context.checker.all_checks_are_final = 1;
 
     switch (ent->type) {
         case Entity_Type_Foreign_Function_Header:
index 6996d6a0cbe37bdb59a35033cbe642516b6b27fd..5501b5ac7d27435039022a02b2402aa1501a6c2f 100644 (file)
@@ -122,7 +122,7 @@ static CompileOptions compile_opts_parse(bh_allocator alloc, int argc, char *arg
     core_installation = CORE_INSTALLATION;
     #endif
     #ifdef _BH_WINDOWS
-    core_installation = bh_alloc_array(global_heap_allocator, u8, 512);
+    core_installation = bh_alloc_array(alloc, u8, 512);
     GetEnvironmentVariableA("ONYX_PATH", core_installation, 512);
     #endif
 
@@ -151,7 +151,7 @@ static CompileOptions compile_opts_parse(bh_allocator alloc, int argc, char *arg
         options.passthrough_argument_data  = &argv[2];
         arg_parse_start = argc;
 
-        bh_arr_push(options.files, bh_aprintf(global_heap_allocator, "%s/tools/onyx-pkg.onyx", core_installation));
+        bh_arr_push(options.files, bh_aprintf(alloc, "%s/tools/onyx-pkg.onyx", core_installation));
     }
     #ifdef ENABLE_RUN_WITH_WASMER
     else if (!strcmp(argv[1], "run")) {
@@ -322,6 +322,9 @@ static Entity *runtime_info_proc_tags_entity;
 
 static void context_init(CompileOptions* opts) {
     types_init();
+    prepare_builtins();
+
+    memset(&context, 0, sizeof context);
 
     context.options = opts;
     context.cycle_detected = 0;
@@ -428,8 +431,6 @@ static void context_init(CompileOptions* opts) {
 static void context_free() {
     bh_arena_free(&context.ast_arena);
     bh_arr_free(context.loaded_files);
-
-    compile_opts_free(context.options);
 }
 
 static void parse_source_file(bh_file_contents* file_contents) {
@@ -558,10 +559,6 @@ static b32 process_entity(Entity* ent) {
                    (u32) ent->micro_attempts);
     }
 
-    // CLEANUP: There should be a nicer way to track if the builtins have
-    // already been initialized.
-    static b32 builtins_initialized = 0;
-
     EntityState before_state = ent->state;
     switch (before_state) {
         case Entity_State_Error:
@@ -584,8 +581,8 @@ static b32 process_entity(Entity* ent) {
             break;
 
         case Entity_State_Parse:
-            if (!builtins_initialized) {
-                builtins_initialized = 1;
+            if (!context.builtins_initialized) {
+                context.builtins_initialized = 1;
                 initialize_builtins(context.ast_alloc);
                 introduce_build_options(context.ast_alloc);
             }
@@ -906,23 +903,29 @@ static b32 onyx_run() {
 }
 #endif
 
-bh_managed_heap mh;
-
-int main(int argc, char *argv[]) {
+static bh_managed_heap mh;
 
+CompilerProgress do_compilation(CompileOptions *compile_opts) {
     bh_scratch_init(&global_scratch, bh_heap_allocator(), 256 * 1024); // NOTE: 256 KiB
     global_scratch_allocator = bh_scratch_allocator(&global_scratch);
 
-    // SPEED: This used to be a managed heap allocator where all allocations
-    // were tracked and would be automatically freed at the end of execution.
-    // I don't know why I ever did that because that is the job of the operating
-    // system when a process exits.
-    // global_heap_allocator = bh_heap_allocator();
-    bh_managed_heap_init(&mh);
-    global_heap_allocator = bh_managed_heap_allocator(&mh);
+    // bh_managed_heap_init(&mh);
+    // global_heap_allocator = bh_managed_heap_allocator(&mh);
+    global_heap_allocator = bh_heap_allocator();
+    context_init(compile_opts);
+
+    return onyx_compile();
+}
+
+void cleanup_compilation() {
+    context_free();
+
+    bh_scratch_free(&global_scratch);
+    // bh_managed_heap_free(&mh);
+}
 
-    CompileOptions compile_opts = compile_opts_parse(global_heap_allocator, argc, argv);
-    context_init(&compile_opts);
+int main(int argc, char *argv[]) {
+    CompileOptions compile_opts = compile_opts_parse(bh_heap_allocator(), argc, argv);
 
     CompilerProgress compiler_progress = ONYX_COMPILER_PROGRESS_ERROR;
     switch (compile_opts.action) {
@@ -936,11 +939,11 @@ int main(int argc, char *argv[]) {
         }
 
         case ONYX_COMPILE_ACTION_CHECK:
-            compiler_progress = onyx_compile();
+            compiler_progress = do_compilation(&compile_opts);
             break;
 
         case ONYX_COMPILE_ACTION_COMPILE:
-            compiler_progress = onyx_compile();
+            compiler_progress = do_compilation(&compile_opts);
             if (compiler_progress == ONYX_COMPILER_PROGRESS_SUCCESS) {
                 onyx_flush_module();
             }
@@ -948,7 +951,7 @@ int main(int argc, char *argv[]) {
 
         #ifdef ENABLE_RUN_WITH_WASMER
         case ONYX_COMPILE_ACTION_RUN:
-            compiler_progress = onyx_compile();
+            compiler_progress = do_compilation(&compile_opts);
             if (compiler_progress == ONYX_COMPILER_PROGRESS_SUCCESS) {
                 if (!onyx_run()) {
                     compiler_progress = ONYX_COMPILER_PROGRESS_ERROR;
@@ -969,21 +972,13 @@ int main(int argc, char *argv[]) {
     }
 
     switch (compiler_progress) {
-        case ONYX_COMPILER_PROGRESS_ERROR:
-            break;
-
         case ONYX_COMPILER_PROGRESS_FAILED_OUTPUT:
             bh_printf_err("Failed to open file for writing: '%s'\n", compile_opts.target_file);
             break;
-
-        case ONYX_COMPILER_PROGRESS_SUCCESS:
-            break;
     }
 
-    context_free();
-
-    bh_scratch_free(&global_scratch);
-    bh_managed_heap_free(&mh);
+    cleanup_compilation();
+    compile_opts_free(&compile_opts);
 
     return compiler_progress != ONYX_COMPILER_PROGRESS_SUCCESS;
 }
index 62559ee02037c2a36d783e55b4fdf7d7a336cebe..b0314f63b64e136073e36942d1ded8e00579107e 100644 (file)
@@ -3,6 +3,8 @@
 // such as procedure definitions, string literals, struct definitions
 // and declarations to be introduced into scopes.
 
+#define BH_INTERNAL_ALLOCATOR (global_heap_allocator)
+
 #include "parser.h"
 #include "lex.h"
 #include "errors.h"
index cbc8fff4e42bbaa548f1ad0d2930b908d91bdfa3..0183be6a1e2083acbaf2050953f0f9de2a2ef4b5 100644 (file)
@@ -1,3 +1,4 @@
+#define BH_INTERNAL_ALLOCATOR (global_heap_allocator)
 #define BH_DEBUG
 
 #include "utils.h"
@@ -18,7 +19,6 @@ bh_allocator global_heap_allocator;
 //
 // Program info and packages
 //
-static u64 next_package_id = 1;
 
 Package* package_lookup(char* package_name) {
     i32 index = shgeti(context.packages, package_name);
@@ -44,7 +44,7 @@ Package* package_lookup_or_create(char* package_name, Scope* parent_scope, bh_al
         package->name = pac_name;
         package->unqualified_name = pac_name + bh_str_last_index_of(pac_name, '.');
         package->use_package_entities = NULL;
-        package->id = next_package_id++;
+        package->id = ++context.next_package_id;
         package->parent_id = -1;
         bh_arr_new(global_heap_allocator, package->sub_packages, 4);
 
@@ -114,11 +114,10 @@ void package_mark_as_used(Package* package) {
 //
 // Scoping
 //
-static u64 next_scope_id = 1;
 
 Scope* scope_create(bh_allocator a, Scope* parent, OnyxFilePos created_at) {
     Scope* scope = bh_alloc_item(a, Scope);
-    scope->id = next_scope_id++;
+    scope->id = ++context.next_scope_id;
     scope->parent = parent;
     scope->created_at = created_at;
     scope->name = NULL;