BIG CHANGES TO COMPILER ARCHITECTURE; using entity pumping system
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 10 Oct 2020 04:06:46 +0000 (23:06 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 10 Oct 2020 04:06:46 +0000 (23:06 -0500)
13 files changed:
Makefile
include/onyxastnodes.h
include/onyxsempass.h
include/onyxwasm.h
onyx
src/onyx.c
src/onyxchecker.c
src/onyxentities.c [new file with mode: 0644]
src/onyxparser.c
src/onyxsempass.c
src/onyxsymres.c
src/onyxutils.c
src/onyxwasm.c

index b073230eeda89f834f9f85fed50c0385e357bb00..6568870626909d57d81b350e048a5fd8388aaab0 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -7,6 +7,7 @@ OBJ_FILES=\
        build/onyxclone.o \
        build/onyxtypes.o \
        build/onyxbuiltins.o \
+       build/onyxentities.o \
        build/onyxsempass.o \
        build/onyxsymres.o \
        build/onyxchecker.o \
index 11995de39e126b286589f8b8af3893c1b6c489f5..e3ee250f03d89006fddb909fd59f213d27ce0b63 100644 (file)
@@ -608,7 +608,7 @@ struct AstTypeRawAlias { AstType_base; Type* to; };
 // Top level nodes
 struct AstBinding       { AstTyped_base; AstNode* node; };
 struct AstMemRes        { AstTyped_base; u64 addr; AstTyped *initial_value; };
-struct AstInclude       { AstNode_base; OnyxToken *name; };
+struct AstInclude       { AstNode_base; char* name; };
 struct AstUsePackage    {
     AstNode_base;
 
@@ -691,10 +691,26 @@ struct AstPackage {
     Package* package;
 };
 
+typedef enum EntityState {
+    Entity_State_Error,
+    
+    Entity_State_Parse_Builtin,
+    Entity_State_Parse,
+    Entity_State_Resolve_Symbols,
+    Entity_State_Check_Types,
+    Entity_State_Code_Gen,
+    Entity_State_Finalized,
+
+    Entity_State_Count,
+} EntityState;
+
 // NOTE: An Entity represents something will need to be
 // processed later down the pipeline.
 typedef enum EntityType {
     Entity_Type_Unknown,
+
+    Entity_Type_Include_Folder,
+    Entity_Type_Include_File,
     Entity_Type_Use_Package,
     Entity_Type_String_Literal,
     Entity_Type_File_Contents,
@@ -703,20 +719,25 @@ typedef enum EntityType {
     Entity_Type_Memory_Reservation,
     Entity_Type_Polymorphic_Proc,
     Entity_Type_Foreign_Function_Header,
+    Entity_Type_Foreign_Global_Header,
     Entity_Type_Function_Header,
     Entity_Type_Global_Header,
     Entity_Type_Expression,
     Entity_Type_Global,
     Entity_Type_Overloaded_Function,
     Entity_Type_Function,
+
+    Entity_Type_Count,
 } EntityType;
 
 typedef struct Entity {
     EntityType type;
+    EntityState state;
     Package *package;
     Scope *scope;
 
     union {
+        AstInclude            *include;
         AstUsePackage         *use_package;
         AstFunction           *function;
         AstOverloadedFunction *overloaded_function;
@@ -731,6 +752,21 @@ typedef struct Entity {
     };
 } Entity;
 
+typedef struct EntityHeap {
+    bh_arr(Entity) entities;
+
+    i32 state_count[Entity_State_Count];
+} EntityHeap;
+
+void 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);
+
+void symres_entity(Entity* ent);
+void check_entity(Entity* ent);
+void emit_entity(Entity* ent);
+
 struct Package {
     char *name;
 
@@ -743,13 +779,11 @@ typedef struct ProgramInfo {
     Scope *global_scope;
 
     bh_table(Package *)   packages;
-    bh_arr(Entity)        entities;
+    EntityHeap            entities;
 
     u32 foreign_global_count;
 } ProgramInfo;
 
-i32 sort_entities(const void* e1, const void* e2);
-
 // NOTE: Basic internal types constructed in the parser
 extern AstBasicType basic_type_void;
 extern AstBasicType basic_type_bool;
index d5af9acfb6c665aaaad4e2f4134695fbef501134..9293353b8ed91dc3f9354d2cc734967359858409 100644 (file)
@@ -14,7 +14,6 @@ typedef struct SemState {
 
     // NOTE: Used wherever
     ProgramInfo* program;
-    bh_arr(Entity) other_entities;
 
     // NOTE: Used in symbol resolution phase
     Package*           curr_package;
@@ -31,21 +30,14 @@ typedef struct SemState {
 
 extern SemState semstate;
 
-// NOTE: Resolving all symbols in the tree
-void onyx_resolve_symbols();
-
 AstType* symres_type(AstType* type);
 void symres_function(AstFunction* func);
 
-// NOTE: Inferring and checking types in the tree
-void onyx_type_check();
-
 b32 check_expression(AstTyped** expr);
 b32 check_function_header(AstFunction* func);
 b32 check_function(AstFunction* func);
 
-// NOTE: Full semantic pass
+// TODO: This should be moved elsewhere.
 void onyx_sempass_init(bh_allocator alloc, bh_allocator node_alloc);
-void onyx_sempass(ProgramInfo* program);
 
 #endif
index e9dcdaed52a0680decc38b84e075a44b50f24448..a86b140a2ea54d0ea4ecdf1da193dc81b4a48432 100644 (file)
@@ -531,9 +531,10 @@ typedef struct OnyxWasmModule {
     u32 next_type_idx;
     u32 next_func_idx;
     u32 next_global_idx;
-    u32 next_foreign_global_idx;
     u32 next_datum_offset;
     u32 next_elem_idx;
+    u32 foreign_function_count;
+    u32 foreign_global_count;
 
     i32 *stack_top_ptr;
     u64 stack_base_idx;
@@ -542,6 +543,8 @@ typedef struct OnyxWasmModule {
     b32 has_stack_locals : 1;
 } OnyxWasmModule;
 
+extern OnyxWasmModule global_wasm_module;
+
 OnyxWasmModule onyx_wasm_module_create(bh_allocator alloc);
 void onyx_wasm_module_compile(OnyxWasmModule* module, ProgramInfo* program);
 void onyx_wasm_module_free(OnyxWasmModule* module);
diff --git a/onyx b/onyx
index 77f2b16c3d606c74b7f55fa8039287fb7ad6ceb3..3ff6901b7c8a7deccb05300f89e0af85ac22e438 100755 (executable)
Binary files a/onyx and b/onyx differ
index a5a6d7896b19edd38d7cf251faf22b8ae27220b3..d961cf5fa123d762f9a30c9c31fe4be221bd1d52 100644 (file)
@@ -141,8 +141,7 @@ static void compile_opts_free(OnyxCompileOptions* opts) {
 typedef enum CompilerProgress {
     ONYX_COMPILER_PROGRESS_FAILED_READ,
     ONYX_COMPILER_PROGRESS_FAILED_PARSE,
-    ONYX_COMPILER_PROGRESS_FAILED_SEMPASS,
-    ONYX_COMPILER_PROGRESS_FAILED_BINARY_GEN,
+    ONYX_COMPILER_PROGRESS_ERROR,
     ONYX_COMPILER_PROGRESS_FAILED_OUTPUT,
     ONYX_COMPILER_PROGRESS_SUCCESS
 } CompilerProgress;
@@ -154,14 +153,19 @@ typedef struct CompilerState {
     bh_allocator token_alloc, ast_alloc, sp_alloc;
 
     bh_table(bh_file_contents) loaded_files;
-    bh_arr(const char *) queued_files;
 
     ProgramInfo prog_info;
-    OnyxWasmModule wasm_mod;
 } CompilerState;
 
 static char* lookup_included_file(CompilerState* cs, char* filename);
 
+static AstInclude* create_include_file(bh_allocator alloc, char* filename) {
+    AstInclude* include_node = onyx_ast_node_new(alloc, sizeof(AstInclude), Ast_Kind_Include_File);
+    include_node->name = filename;
+
+    return include_node;
+}
+
 static void compiler_state_init(CompilerState* compiler_state, OnyxCompileOptions* opts) {
     compiler_state->options = opts;
 
@@ -180,30 +184,46 @@ static void compiler_state_init(CompilerState* compiler_state, OnyxCompileOption
     bh_arena_init(&compiler_state->sp_arena, opts->allocator, 16 * 1024);
     compiler_state->sp_alloc = bh_arena_allocator(&compiler_state->sp_arena);
 
-    bh_arr_new(opts->allocator, compiler_state->queued_files, 4);
+    onyx_sempass_init(compiler_state->sp_alloc, compiler_state->ast_alloc);
+
+    // HACK
+    global_wasm_module = onyx_wasm_module_create(compiler_state->options->allocator);
 
-    bh_arr_push(compiler_state->queued_files, lookup_included_file(compiler_state, "core/builtin"));
+    entity_heap_insert(&compiler_state->prog_info.entities, ((Entity) {
+        .state = Entity_State_Parse_Builtin,
+        .type = Entity_Type_Include_File,
+        .package = NULL,
+        .include = create_include_file(compiler_state->sp_alloc, "core/builtin"),
+    }));
 
     // NOTE: Add all files passed by command line to the queue
-    bh_arr_each(const char *, filename, opts->files)
-        bh_arr_push(compiler_state->queued_files, (char *) *filename);
+    bh_arr_each(const char *, filename, opts->files) {
+        entity_heap_insert(&compiler_state->prog_info.entities, ((Entity) {
+            .state = Entity_State_Parse,
+            .type = Entity_Type_Include_File,
+            .package = NULL,
+            .include = create_include_file(compiler_state->sp_alloc, (char *) *filename),
+        }));
+    }
 }
 
 static void compiler_state_free(CompilerState* cs) {
     bh_arena_free(&cs->ast_arena);
     bh_arena_free(&cs->sp_arena);
     bh_table_free(cs->loaded_files);
-    onyx_wasm_module_free(&cs->wasm_mod);
 }
 
-
-
+// NOTE: This should not be called until immediately before using the return value.
+// This function can return a static variable which will change if this is called
+// another time.                                        -brendanfh 2020/10/09
 static char* lookup_included_file(CompilerState* cs, char* filename) {
     static char path[256];
-    fori (i, 0, 256) path[i] = 0;
+    fori (i, 0, 256)
+        path[i] = 0;
 
     static char fn[128];
     fori (i, 0, 128) fn[i] = 0;
+
     if (!bh_str_ends_with(filename, ".onyx")) {
         bh_snprintf(fn, 128, "%s.onyx", filename);
     } else {
@@ -239,17 +259,16 @@ static ParseResults parse_source_file(CompilerState* compiler_state, bh_file_con
 
 static void merge_parse_results(CompilerState* compiler_state, ParseResults* results) {
     bh_arr_each(AstInclude *, include, results->includes) {
-        if ((*include)->kind == Ast_Kind_Include_File) {
-            token_toggle_end((*include)->name);
-            char* filename = lookup_included_file(compiler_state, (*include)->name->text);
-            token_toggle_end((*include)->name);
-
-            char* formatted_name = bh_strdup(global_heap_allocator, filename);
-            bh_arr_push(compiler_state->queued_files, formatted_name);
-        } else if ((*include)->kind == Ast_Kind_Include_Folder) {
-            const char* folder = bh_aprintf(global_heap_allocator, "%b", (*include)->name->text, (*include)->name->length);
-            bh_arr_push(compiler_state->options->included_folders, folder);
-        }
+        EntityType et = Entity_Type_Include_File;
+        if ((*include)->kind == Ast_Kind_Include_Folder)
+            et = Entity_Type_Include_Folder;
+
+        entity_heap_insert(&compiler_state->prog_info.entities, (Entity) {
+            .state = Entity_State_Parse,
+            .type = et,
+            .scope = NULL,
+            .include = *include,
+        });
     }
 
     Entity ent;
@@ -257,6 +276,7 @@ static void merge_parse_results(CompilerState* compiler_state, ParseResults* res
         AstNode* node = n->node;
         AstKind nkind = node->kind;
 
+        ent.state = Entity_State_Resolve_Symbols;
         ent.package = n->package;
         ent.scope   = n->scope;
 
@@ -265,16 +285,16 @@ static void merge_parse_results(CompilerState* compiler_state, ParseResults* res
                 if ((node->flags & Ast_Flag_Foreign) != 0) {
                     ent.type     = Entity_Type_Foreign_Function_Header;
                     ent.function = (AstFunction *) node;
-                    bh_arr_push(compiler_state->prog_info.entities, ent);
+                    entity_heap_insert(&compiler_state->prog_info.entities, ent);
 
                 } else {
                     ent.type     = Entity_Type_Function_Header;
                     ent.function = (AstFunction *) node;
-                    bh_arr_push(compiler_state->prog_info.entities, ent);
+                    entity_heap_insert(&compiler_state->prog_info.entities, ent);
 
                     ent.type     = Entity_Type_Function;
                     ent.function = (AstFunction *) node;
-                    bh_arr_push(compiler_state->prog_info.entities, ent);
+                    entity_heap_insert(&compiler_state->prog_info.entities, ent);
                 }
                 break;
             }
@@ -282,32 +302,39 @@ static void merge_parse_results(CompilerState* compiler_state, ParseResults* res
             case Ast_Kind_Overloaded_Function: {
                 ent.type                = Entity_Type_Overloaded_Function;
                 ent.overloaded_function = (AstOverloadedFunction *) node;
-                bh_arr_push(compiler_state->prog_info.entities, ent);
+                entity_heap_insert(&compiler_state->prog_info.entities, ent);
                 break;
             }
 
             case Ast_Kind_Global: {
-                ent.type   = Entity_Type_Global_Header;
-                ent.global = (AstGlobal *) node;
-                bh_arr_push(compiler_state->prog_info.entities, ent);
+                if ((node->flags & Ast_Flag_Foreign) != 0) {
+                    ent.type   = Entity_Type_Foreign_Global_Header;
+                    ent.global = (AstGlobal *) node;
+                    entity_heap_insert(&compiler_state->prog_info.entities, ent);
 
-                ent.type   = Entity_Type_Global;
-                ent.global = (AstGlobal *) node;
-                bh_arr_push(compiler_state->prog_info.entities, ent);
+                } else {
+                    ent.type   = Entity_Type_Global_Header;
+                    ent.global = (AstGlobal *) node;
+                    entity_heap_insert(&compiler_state->prog_info.entities, ent);
+
+                    ent.type   = Entity_Type_Global;
+                    ent.global = (AstGlobal *) node;
+                    entity_heap_insert(&compiler_state->prog_info.entities, ent);
+                }
                 break;
             }
 
             case Ast_Kind_StrLit: {
                 ent.type   = Entity_Type_String_Literal;
                 ent.strlit = (AstStrLit *) node;
-                bh_arr_push(compiler_state->prog_info.entities, ent);
+                entity_heap_insert(&compiler_state->prog_info.entities, ent);
                 break;
             }
 
             case Ast_Kind_File_Contents: {
                 ent.type = Entity_Type_File_Contents;
                 ent.file_contents = (AstFileContents *) node;
-                bh_arr_push(compiler_state->prog_info.entities, ent);
+                entity_heap_insert(&compiler_state->prog_info.entities, ent);
                 break;
             }
 
@@ -316,42 +343,42 @@ static void merge_parse_results(CompilerState* compiler_state, ParseResults* res
             case Ast_Kind_Poly_Struct_Type: {
                 ent.type = Entity_Type_Type_Alias;
                 ent.type_alias = (AstType *) node;
-                bh_arr_push(compiler_state->prog_info.entities, ent);
+                entity_heap_insert(&compiler_state->prog_info.entities, ent);
                 break;
             }
 
             case Ast_Kind_Enum_Type: {
                 ent.type = Entity_Type_Enum;
                 ent.enum_type = (AstEnumType *) node;
-                bh_arr_push(compiler_state->prog_info.entities, ent);
+                entity_heap_insert(&compiler_state->prog_info.entities, ent);
                 break;
             }
 
             case Ast_Kind_Use_Package: {
                 ent.type = Entity_Type_Use_Package;
                 ent.use_package = (AstUsePackage *) node;
-                bh_arr_push(compiler_state->prog_info.entities, ent);
+                entity_heap_insert(&compiler_state->prog_info.entities, ent);
                 break;
             }
 
             case Ast_Kind_Memres: {
                 ent.type = Entity_Type_Memory_Reservation;
                 ent.mem_res = (AstMemRes *) node;
-                bh_arr_push(compiler_state->prog_info.entities, ent);
+                entity_heap_insert(&compiler_state->prog_info.entities, ent);
                 break;
             }
 
             case Ast_Kind_Polymorphic_Proc: {
                 ent.type = Entity_Type_Polymorphic_Proc;
                 ent.poly_proc = (AstPolyProc *) node;
-                bh_arr_push(compiler_state->prog_info.entities, ent);
+                entity_heap_insert(&compiler_state->prog_info.entities, ent);
                 break;
             }
 
             default: {
                 ent.type = Entity_Type_Expression;
                 ent.expr = (AstTyped *) node;
-                bh_arr_push(compiler_state->prog_info.entities, ent);
+                entity_heap_insert(&compiler_state->prog_info.entities, ent);
                 break;
             }
         }
@@ -369,7 +396,8 @@ static CompilerProgress process_source_file(CompilerState* compiler_state, char*
 
     bh_file_error err = bh_file_open(&file, filename);
     if (err != BH_FILE_ERROR_NONE) {
-        bh_printf_err("Failed to open file %s\n", filename);
+        // bh_printf_err("Failed to open file %s\n", filename);
+        onyx_report_error((OnyxFilePos) { 0 }, "Failed to open file %s\n", filename);
         return ONYX_COMPILER_PROGRESS_FAILED_READ;
     }
 
@@ -407,98 +435,90 @@ static CompilerProgress process_source_file(CompilerState* compiler_state, char*
     }
 }
 
+static b32 process_include_entity(CompilerState* compiler_state, Entity* ent) {
+    assert(ent->type == Entity_Type_Include_File || ent->type == Entity_Type_Include_Folder);
+    AstInclude* include = ent->include;
 
-static i32 onyx_compile(CompilerState* compiler_state) {
+    if (include->kind == Ast_Kind_Include_File) {
+        char* filename = lookup_included_file(compiler_state, include->name);
 
-#ifdef REPORT_TIMES
-    timer_stack_push("Parsing");
-#endif
+        char* formatted_name = bh_strdup(global_heap_allocator, filename);
+        process_source_file(compiler_state, formatted_name);
 
-    // NOTE: While the queue is not empty, process the next file
-    while (!bh_arr_is_empty(compiler_state->queued_files)) {
-        CompilerProgress result = process_source_file(compiler_state, (char *) compiler_state->queued_files[0]);
+    } else if (include->kind == Ast_Kind_Include_Folder) {
+        bh_arr_push(compiler_state->options->included_folders, include->name);
+    }
 
-        if (result != ONYX_COMPILER_PROGRESS_SUCCESS)
-            return result;
+    return 1;
+}
 
-        bh_arr_fastdelete(compiler_state->queued_files, 0);
-    }
+static b32 process_entity(CompilerState* compiler_state, Entity* ent) {
+    i32 changed = 1;
 
-#ifdef REPORT_TIMES
-    timer_stack_pop();
-    
-    timer_stack_push("Checking semantics");
-    timer_stack_push("Initializing builtins");
-#endif
+    switch (ent->state) {
+        case Entity_State_Parse_Builtin:
+        case Entity_State_Parse:
+            process_include_entity(compiler_state, ent);
+            ent->state = Entity_State_Finalized;
+            break;
 
-    initialize_builtins(compiler_state->ast_alloc, &compiler_state->prog_info);
-    if (onyx_has_errors()) {
-        return ONYX_COMPILER_PROGRESS_FAILED_SEMPASS;
+        case Entity_State_Resolve_Symbols: symres_entity(ent); break;
+        case Entity_State_Check_Types:     check_entity(ent);  break;
+        case Entity_State_Code_Gen:        emit_entity(ent);   break;
+
+        default:
+            changed = 0;
     }
 
-    // Add builtin one-time entities
-    bh_arr_push(compiler_state->prog_info.entities, ((Entity) {
-        .type = Entity_Type_Global_Header,
-        .global = &builtin_stack_top
-    }));
-    bh_arr_push(compiler_state->prog_info.entities, ((Entity) {
-        .type = Entity_Type_Global,
-        .global = &builtin_stack_top
-    }));
+    return changed;
+}
 
-    qsort(compiler_state->prog_info.entities,
-            bh_arr_length(compiler_state->prog_info.entities),
-            sizeof(Entity),
-            sort_entities);
 
-#ifdef REPORT_TIMES
-    timer_stack_pop();
-#endif
+static i32 onyx_compile(CompilerState* compiler_state) {
+    {
+        entity_heap_insert(&compiler_state->prog_info.entities, ((Entity) {
+            .state = Entity_State_Resolve_Symbols,
+            .type = Entity_Type_Global_Header,
+            .global = &builtin_stack_top
+        }));
+        entity_heap_insert(&compiler_state->prog_info.entities, ((Entity) {
+            .state = Entity_State_Resolve_Symbols,
+            .type = Entity_Type_Global,
+            .global = &builtin_stack_top
+        }));
 
-    // NOTE: Check types and semantic rules
-    if (compiler_state->options->verbose_output)
-        bh_printf("[Checking semantics]\n");
+        Entity ent = entity_heap_top(&compiler_state->prog_info.entities);
+        assert(ent.state == Entity_State_Parse_Builtin);
+        DEBUG_HERE;
 
-    onyx_sempass_init(compiler_state->sp_alloc, compiler_state->ast_alloc);
-    onyx_sempass(&compiler_state->prog_info);
+        process_entity(compiler_state, &ent);
 
-#ifdef REPORT_TIMES
-    timer_stack_pop();
-#endif
+        if (onyx_has_errors()) return ONYX_COMPILER_PROGRESS_ERROR;
 
-    if (onyx_has_errors()) {
-        return ONYX_COMPILER_PROGRESS_FAILED_SEMPASS;
-    }
+        entity_heap_remove_top(&compiler_state->prog_info.entities);
 
-    if (compiler_state->options->action == ONYX_COMPILE_ACTION_DOCUMENT) {
-        OnyxDocumentation docs = onyx_docs_generate(&compiler_state->prog_info);
-        docs.format = Doc_Format_Tags;
-        onyx_docs_emit(&docs);
+        initialize_builtins(compiler_state->ast_alloc, &compiler_state->prog_info);
 
-        return ONYX_COMPILER_PROGRESS_SUCCESS;
+        semstate.program = &compiler_state->prog_info;
     }
 
-    // NOTE: Generate WASM instructions
-    if (compiler_state->options->verbose_output)
-        bh_printf("[Generating WASM]\n");
+    while (!bh_arr_is_empty(compiler_state->prog_info.entities.entities)) {
+        Entity ent = entity_heap_top(&compiler_state->prog_info.entities);
+        b32 changed = process_entity(compiler_state, &ent);
 
-#ifdef REPORT_TIMES
-    timer_stack_push("Code generation");
-    timer_stack_push("Generating WASM");
-#endif
-
-    compiler_state->wasm_mod = onyx_wasm_module_create(compiler_state->options->allocator);
-    onyx_wasm_module_compile(&compiler_state->wasm_mod, &compiler_state->prog_info);
+        if (onyx_has_errors()) {
+            return ONYX_COMPILER_PROGRESS_ERROR;
+        }
 
-    if (onyx_has_errors()) {
-        return ONYX_COMPILER_PROGRESS_FAILED_BINARY_GEN;
+        if (changed) {
+            if (ent.state == Entity_State_Finalized) {
+                entity_heap_remove_top(&compiler_state->prog_info.entities);
+            } else {
+                entity_heap_change_top(&compiler_state->prog_info.entities, ent);
+            }
+        }
     }
 
-#ifdef REPORT_TIMES
-    timer_stack_pop();
-    timer_stack_push("Write to file");
-#endif
-
     // NOTE: Output to file
     bh_file output_file;
     if (bh_file_create(&output_file, compiler_state->options->target_file) != BH_FILE_ERROR_NONE) {
@@ -508,12 +528,7 @@ static i32 onyx_compile(CompilerState* compiler_state) {
     if (compiler_state->options->verbose_output)
         bh_printf("[Writing WASM] %s\n", output_file.filename);
 
-    onyx_wasm_module_write_to_file(&compiler_state->wasm_mod, output_file);
-
-#ifdef REPORT_TIMES
-    timer_stack_pop();
-    timer_stack_pop();
-#endif
+    onyx_wasm_module_write_to_file(&global_wasm_module, output_file);
 
     return ONYX_COMPILER_PROGRESS_SUCCESS;
 }
@@ -553,8 +568,7 @@ int main(int argc, char *argv[]) {
             break;
 
         case ONYX_COMPILER_PROGRESS_FAILED_PARSE:
-        case ONYX_COMPILER_PROGRESS_FAILED_SEMPASS:
-        case ONYX_COMPILER_PROGRESS_FAILED_BINARY_GEN:
+        case ONYX_COMPILER_PROGRESS_ERROR:
             onyx_errors_print();
             break;
 
index bbd7fcf3099ca6820e58b5bd389dc8e18c495850..1fcd0e5db7621fbed87d80830a57891fe43df2e3 100644 (file)
@@ -1468,55 +1468,44 @@ b32 check_node(AstNode* node) {
     }
 }
 
-void onyx_type_check() {
-    bh_arr_each(Entity, entity, semstate.program->entities) {
-        switch (entity->type) {
-            case Entity_Type_Foreign_Function_Header:
-            case Entity_Type_Function_Header:
-                if (check_function_header(entity->function)) return;
-                break;
-
-            case Entity_Type_Function:
-                if (check_function(entity->function)) return;
-                break;
-
-            case Entity_Type_Overloaded_Function:
-                if (check_overloaded_function(entity->overloaded_function)) return;
-                break;
-
-            case Entity_Type_Global:
-                if (entity->global->flags & Ast_Flag_Foreign)
-                    semstate.program->foreign_global_count++;
-
-                if (check_global(entity->global)) return;
-                break;
-
-            case Entity_Type_Expression:
-                if (check_expression(&entity->expr)) return;
-                break;
-
-            case Entity_Type_Type_Alias:
-                if (entity->type_alias->kind == Ast_Kind_Struct_Type)
-                    if (check_struct((AstStructType *) entity->type_alias)) return;
-                break;
+void check_entity(Entity* ent) {
+    switch (ent->type) {
+        case Entity_Type_Foreign_Function_Header:
+        case Entity_Type_Function_Header:
+            if (check_function_header(ent->function)) return;
+            break;
 
-            case Entity_Type_Memory_Reservation:
-                if (check_memres(entity->mem_res)) return;
-                break;
+        case Entity_Type_Function:
+            if (check_function(ent->function)) return;
+            break;
 
-            case Entity_Type_Enum: break;
+        case Entity_Type_Overloaded_Function:
+            if (check_overloaded_function(ent->overloaded_function)) return;
+            break;
 
-            case Entity_Type_String_Literal: break;
+        case Entity_Type_Foreign_Global_Header:
+            semstate.program->foreign_global_count++;
+            // fallthrough
 
-            case Entity_Type_File_Contents: break;
+        case Entity_Type_Global:
+            if (check_global(ent->global)) return;
+            break;
 
-            case Entity_Type_Global_Header: break;
+        case Entity_Type_Expression:
+            if (check_expression(&ent->expr)) return;
+            break;
 
-            case Entity_Type_Use_Package: break;
+        case Entity_Type_Type_Alias:
+            if (ent->type_alias->kind == Ast_Kind_Struct_Type)
+                if (check_struct((AstStructType *) ent->type_alias)) return;
+            break;
 
-            case Entity_Type_Polymorphic_Proc: break;
+        case Entity_Type_Memory_Reservation:
+            if (check_memres(ent->mem_res)) return;
+            break;
 
-            default: DEBUG_HERE; break;
-        }
+        default: break;
     }
-}
+
+    ent->state = Entity_State_Code_Gen;
+}
\ No newline at end of file
diff --git a/src/onyxentities.c b/src/onyxentities.c
new file mode 100644 (file)
index 0000000..55a5a80
--- /dev/null
@@ -0,0 +1,78 @@
+#include "bh.h"
+#include "onyxastnodes.h"
+#include "onyxutils.h"
+
+// NOTE: Returns >0 if e1 should be processed after e2.
+static i32 entity_compare(Entity* e1, Entity* e2) {
+    if (e1->state != e2->state)
+        return (i32) e1->state - (i32) e2->state;
+    else
+        return (i32) e1->type - (i32) e2->type;
+}
+
+#define eh_parent(index) (((index) - 1) / 2)
+#define eh_lchild(index) (((index) * 2) + 1)
+#define eh_rchild(index) (((index) * 2) + 2)
+
+static void eh_shift_up(EntityHeap* entities, i32 index) {
+       while (index > 0 && entity_compare(&entities->entities[eh_parent(index)], &entities->entities[index]) > 0) {
+               Entity tmp = entities->entities[eh_parent(index)];
+               entities->entities[eh_parent(index)] = entities->entities[index];                       
+               entities->entities[index] = tmp;
+
+               index = eh_parent(index);
+       }
+}
+
+static void eh_shift_down(EntityHeap* entities, i32 index) {
+       i32 min_index = index;
+
+       i32 l = eh_lchild(index);       
+       if (l < bh_arr_length(entities->entities)
+               && entity_compare(&entities->entities[l], &entities->entities[min_index]) <= 0) {
+               min_index = l;
+       }
+
+       i32 r = eh_rchild(index);       
+       if (r < bh_arr_length(entities->entities)
+               && entity_compare(&entities->entities[r], &entities->entities[min_index]) <= 0) {
+               min_index = r;
+       }
+
+       if (index != min_index) {
+               Entity tmp = entities->entities[min_index];
+               entities->entities[min_index] = entities->entities[index];
+               entities->entities[index] = tmp;
+
+               eh_shift_down(entities, min_index);
+       }
+}
+
+void entity_heap_insert(EntityHeap* entities, Entity e) {
+       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);
+
+       entities->state_count[e.state]++;
+}
+
+Entity entity_heap_top(EntityHeap* entities) {
+       return entities->entities[0];
+}
+
+void entity_heap_change_top(EntityHeap* entities, Entity new_top) {
+       entities->state_count[entities->entities[0].state]--;
+       entities->state_count[new_top.state]--;
+       
+       entities->entities[0] = new_top;
+       eh_shift_down(entities, 0);
+}
+
+void entity_heap_remove_top(EntityHeap* entities) {
+       entities->entities[0] = entities->entities[bh_arr_length(entities->entities) - 1];
+       bh_arr_pop(entities->entities);
+       eh_shift_down(entities, 0);
+}
index cc389240c357eb6a5e336b04e06ecb1ed0993705..64ebfe6c1f45d6ba94273526b2f024313be5a2f4 100644 (file)
@@ -1965,14 +1965,26 @@ static AstNode* parse_top_level_statement(OnyxParser* parser) {
                 if (parse_possible_directive(parser, "include_file")) {
                     AstInclude* include = make_node(AstInclude, Ast_Kind_Include_File);
                     include->token = dir_token;
-                    include->name = expect_token(parser, Token_Type_Literal_String);
+
+                    OnyxToken* str_token = expect_token(parser, Token_Type_Literal_String);
+                    if (str_token != NULL) {
+                        token_toggle_end(str_token);
+                        include->name = bh_strdup(parser->allocator, str_token->text);
+                        token_toggle_end(str_token);
+                    }
 
                     return (AstNode *) include;
                 }
                 else if (parse_possible_directive(parser, "include_folder")) {
                     AstInclude* include = make_node(AstInclude, Ast_Kind_Include_Folder);
                     include->token = dir_token;
-                    include->name = expect_token(parser, Token_Type_Literal_String);
+                    
+                    OnyxToken* str_token = expect_token(parser, Token_Type_Literal_String);
+                    if (str_token != NULL) {
+                        token_toggle_end(str_token);
+                        include->name = bh_strdup(parser->allocator, str_token->text);
+                        token_toggle_end(str_token);
+                    }
 
                     return (AstNode *) include;
                 }
index 73e335950504970300b00ef0ac727b37a9f7d654..3de8b26cfa1484132638cb9d1881455c46261e44 100644 (file)
@@ -1,3 +1,5 @@
+// TODO: This file has become useless. It should be removed soon.
+
 #define BH_DEBUG
 #include "onyxsempass.h"
 #include "onyxutils.h"
@@ -13,30 +15,9 @@ void onyx_sempass_init(bh_allocator alloc, bh_allocator node_alloc) {
         .curr_scope = NULL,
 
         .block_stack = NULL,
-        .other_entities = NULL,
 
         .defer_allowed = 1,
     };
 
     bh_arr_new(global_heap_allocator, semstate.block_stack, 4);
-    bh_arr_new(global_heap_allocator, semstate.other_entities, 4);
-}
-
-void onyx_sempass(ProgramInfo* program) {
-    semstate.program = program;
-
-    onyx_resolve_symbols(program);
-    if (onyx_has_errors()) return;
-
-    onyx_type_check(program);
-
-    if (bh_arr_length(semstate.other_entities) > 0) {
-        bh_arr_each(Entity, e, semstate.other_entities)
-            bh_arr_push(semstate.program->entities, *e);
-
-        qsort(semstate.program->entities, bh_arr_length(semstate.program->entities), sizeof(Entity), sort_entities);
-        bh_arr_clear(semstate.other_entities);
-    }
-    
-    if (onyx_has_errors()) return;
 }
index 34aa440b1311aa3a3db303c7b0cbad5dfcae238b..d75a4aae76241a689c97c10e4573e7e82dbb110e 100644 (file)
@@ -774,33 +774,30 @@ static void symres_polyproc(AstPolyProc* pp) {
     pp->poly_scope = scope_create(semstate.node_allocator, semstate.curr_scope, pp->token->pos);
 }
 
-void onyx_resolve_symbols() {
+void symres_entity(Entity* ent) {
+    if (ent->package) {
+        scope_enter(ent->scope);
+        semstate.curr_package = ent->package;
+    }
+
+    switch (ent->type) {
+        case Entity_Type_Foreign_Function_Header:
+        case Entity_Type_Function:            symres_function(ent->function); break;
+
+        case Entity_Type_Use_Package:         symres_use_package(ent->use_package); break;
+        case Entity_Type_Overloaded_Function: symres_overloaded_function(ent->overloaded_function); break;
+        case Entity_Type_Global:              symres_global(ent->global); break;
+        case Entity_Type_Expression:          symres_expression(&ent->expr); break;
+        case Entity_Type_Type_Alias:          ent->type_alias = symres_type(ent->type_alias); break;
+        case Entity_Type_Enum:                symres_enum(ent->enum_type); break;
+        case Entity_Type_Memory_Reservation:  symres_memres(&ent->mem_res); break;
+        case Entity_Type_Polymorphic_Proc:    symres_polyproc(ent->poly_proc); break;
+        case Entity_Type_String_Literal:      symres_expression(&ent->expr); break;
 
-    semstate.curr_scope = semstate.program->global_scope;
+        default: break;
+    }
 
-    bh_arr_each(Entity, entity, semstate.program->entities) {
-        if (entity->package) {
-            scope_enter(entity->scope);
-            semstate.curr_package = entity->package;
-        }
+    ent->state = Entity_State_Check_Types;
 
-        switch (entity->type) {
-            case Entity_Type_Foreign_Function_Header:
-            case Entity_Type_Function:            symres_function(entity->function); break;
-
-            case Entity_Type_Use_Package:         symres_use_package(entity->use_package); break;
-            case Entity_Type_Overloaded_Function: symres_overloaded_function(entity->overloaded_function); break;
-            case Entity_Type_Global:              symres_global(entity->global); break;
-            case Entity_Type_Expression:          symres_expression(&entity->expr); break;
-            case Entity_Type_Type_Alias:          entity->type_alias = symres_type(entity->type_alias); break;
-            case Entity_Type_Enum:                symres_enum(entity->enum_type); break;
-            case Entity_Type_Memory_Reservation:  symres_memres(&entity->mem_res); break;
-            case Entity_Type_Polymorphic_Proc:    symres_polyproc(entity->poly_proc); break;
-            case Entity_Type_String_Literal:      symres_expression(&entity->expr); break;
-
-            default: break;
-        }
-
-        if (entity->package) scope_leave();
-    }
-}
+    if (ent->package) scope_leave();
+}
\ No newline at end of file
index c39768d46d7612c6bfeb2e63637dd47bcd07de6b..2aa7b5e4f974d10f7ff02f5564c8abd2d66f0b8a 100644 (file)
@@ -101,8 +101,8 @@ void program_info_init(ProgramInfo* prog, bh_allocator alloc) {
 
     bh_table_init(alloc, prog->packages, 16);
 
-    prog->entities = NULL;
-    bh_arr_new(alloc, prog->entities, 4);
+    // NOTE: This will be initialized upon the first call to entity_heap_insert.
+    prog->entities.entities = NULL;
 }
 
 Package* program_info_package_lookup(ProgramInfo* prog, char* package_name) {
@@ -537,8 +537,6 @@ AstFunction* polymorphic_proc_lookup(AstPolyProc* pp, PolyProcLookupMethod pp_lo
 
     if (onyx_has_errors()) goto has_error;
     if (check_function_header(func)) goto has_error;
-    if (check_function(func)) goto has_error;
-    if (onyx_has_errors()) goto has_error;
     goto no_errors;
 
 has_error:
@@ -549,16 +547,19 @@ has_error:
 no_errors:
     semstate.expected_return_type = old_return_type;
 
-    bh_arr_push(semstate.other_entities, ((Entity) {
+    entity_heap_insert(&semstate.program->entities, (Entity) {
+        .state = Entity_State_Code_Gen,
         .type = Entity_Type_Function_Header,
         .function = func,
         .package = NULL,
-    }));
-    bh_arr_push(semstate.other_entities, ((Entity) {
+    });
+
+    entity_heap_insert(&semstate.program->entities, (Entity) {
+        .state = Entity_State_Check_Types,
         .type = Entity_Type_Function,
         .function = func,
         .package = NULL,
-    }));
+    });
 
     return func;
 }
@@ -641,7 +642,3 @@ no_errors:
 
     return concrete_struct;
 }
-
-i32 sort_entities(const void* e1, const void* e2) {
-    return ((Entity *)e1)->type - ((Entity *)e2)->type;
-}
index 3d5acfc1e4f31c7563bf0af8110476ab7b9511fc..0a4611b8b93ba1f41e9147e6d6e206615f5ec2be 100644 (file)
@@ -2,6 +2,8 @@
 #include "onyxwasm.h"
 #include "onyxutils.h"
 
+OnyxWasmModule global_wasm_module;
+
 // NOTE: Allows easier testing of types since most of the characters
 // corresponding to these values are not printable
 #if 1
@@ -2666,11 +2668,11 @@ static void emit_function(OnyxWasmModule* mod, AstFunction* fd) {
 
     bh_arr_new(mod->allocator, wasm_func.code, 4);
 
+    i32 func_idx = (i32) bh_imap_get(&mod->index_map, (u64) fd);
+
     if (fd->flags & Ast_Flag_Exported) {
         token_toggle_end(fd->exported_name);
 
-        i32 func_idx = (i32) bh_imap_get(&mod->index_map, (u64) fd);
-
         WasmExport wasm_export = {
             .kind = WASM_FOREIGN_FUNCTION,
             .idx = func_idx,
@@ -2734,7 +2736,10 @@ static void emit_function(OnyxWasmModule* mod, AstFunction* fd) {
 
     bh_arr_push(wasm_func.code, ((WasmInstruction){ WI_BLOCK_END, 0x00 }));
 
-    bh_arr_push(mod->funcs, wasm_func);
+    // HACK: This is gross
+    bh_arr_grow(mod->funcs, func_idx - mod->foreign_function_count + 1);
+    mod->funcs[func_idx - mod->foreign_function_count] = wasm_func;
+    bh_arr_set_length(mod->funcs, bh_max(bh_arr_length(mod->funcs), func_idx - mod->foreign_function_count + 1));
 
     // NOTE: Clear the local map on exit of generating this function
     bh_imap_clear(&mod->local_map);
@@ -2759,29 +2764,17 @@ static void emit_foreign_function(OnyxWasmModule* mod, AstFunction* fd) {
 static void emit_global(OnyxWasmModule* module, AstGlobal* global) {
     WasmType global_type = onyx_type_to_wasm_type(global->type);
 
-    if (global->flags & Ast_Flag_Foreign) {
-        WasmImport import = {
-            .kind = WASM_FOREIGN_GLOBAL,
-            .idx  = global_type,
-            .mod  = global->foreign_module,
-            .name = global->foreign_name,
-        };
-
-        bh_arr_push(module->imports, import);
-        return;
-    }
-
     WasmGlobal glob = {
         .type = global_type,
         .mutable = (global->flags & Ast_Flag_Const) == 0,
         .initial_value = NULL,
     };
 
+    i32 global_idx = (i32) bh_imap_get(&module->index_map, (u64) global);
+
     if ((global->flags & Ast_Flag_Exported) != 0) {
         token_toggle_end(global->exported_name);
 
-        i32 global_idx = (i32) bh_imap_get(&module->index_map, (u64) global);
-
         WasmExport wasm_export = {
             .kind = WASM_FOREIGN_GLOBAL,
             .idx = global_idx,
@@ -2803,11 +2796,31 @@ static void emit_global(OnyxWasmModule* module, AstGlobal* global) {
         default: assert(("Invalid global type", 0)); break;
     }
 
-    bh_arr_push(module->globals, glob);
+    bh_arr_grow(module->globals, global_idx + 1);
+    module->globals[global_idx] = glob;
+    bh_arr_set_length(module->globals, bh_max(bh_arr_length(module->globals), global_idx + 1));
+
+    bh_arr_grow(module->globals, global_idx - module->foreign_global_count + 1);
+    module->globals[global_idx - module->foreign_global_count] = glob;
+    bh_arr_set_length(module->globals, bh_max(bh_arr_length(module->globals), global_idx - module->foreign_global_count + 1));
 
     if (global->flags & Ast_Flag_Global_Stack_Top)
-        module->stack_top_ptr = &bh_arr_last(module->globals).initial_value[0].data.i1;
+        module->stack_top_ptr = &module->globals[global_idx].initial_value[0].data.i1;
+}
+
+static void emit_foreign_global(OnyxWasmModule* module, AstGlobal* global) {
+    WasmType global_type = onyx_type_to_wasm_type(global->type);
+
+    if (global->flags & Ast_Flag_Foreign) {
+        WasmImport import = {
+            .kind = WASM_FOREIGN_GLOBAL,
+            .idx  = global_type,
+            .mod  = global->foreign_module,
+            .name = global->foreign_name,
+        };
 
+        bh_arr_push(module->imports, import);
+    }
 }
 
 static void emit_string_literal(OnyxWasmModule* mod, AstStrLit* strlit) {
@@ -3025,7 +3038,6 @@ OnyxWasmModule onyx_wasm_module_create(bh_allocator alloc) {
 
         .globals = NULL,
         .next_global_idx = 0,
-        .next_foreign_global_idx = 0,
 
         .data = NULL,
         .next_datum_offset = 0,
@@ -3037,6 +3049,9 @@ OnyxWasmModule onyx_wasm_module_create(bh_allocator alloc) {
 
         .stack_top_ptr = NULL,
         .stack_base_idx = 0,
+
+        .foreign_function_count = 0,
+        .foreign_global_count = 0,
     };
 
     bh_arena* eid = bh_alloc(global_heap_allocator, sizeof(bh_arena));
@@ -3066,77 +3081,77 @@ OnyxWasmModule onyx_wasm_module_create(bh_allocator alloc) {
 
     bh_arr_new(global_heap_allocator, module.deferred_stmts, 4);
 
-    return module;
-}
-
-void onyx_wasm_module_compile(OnyxWasmModule* module, ProgramInfo* program) {
-    module->next_global_idx = program->foreign_global_count;
-
     WasmExport mem_export = {
         .kind = WASM_FOREIGN_MEMORY,
         .idx = 0,
     };
-    bh_table_put(WasmExport, module->exports, "memory", mem_export);
-    module->export_count++;
+    bh_table_put(WasmExport, module.exports, "memory", mem_export);
+    module.export_count++;
 
-    bh_arr_each(Entity, entity, program->entities) {
+    return module;
+}
 
-        if (module->stack_top_ptr) {
-            *module->stack_top_ptr = module->next_datum_offset;
+void emit_entity(Entity* ent) {
+    OnyxWasmModule* module = &global_wasm_module;
 
-            if (*module->stack_top_ptr % 16 != 0) {
-                *module->stack_top_ptr += 16 - (*module->stack_top_ptr % 16);
-            }
+    if (module->stack_top_ptr) {
+        *module->stack_top_ptr = module->next_datum_offset;
 
-            builtin_heap_start.value.i = *module->stack_top_ptr + (1 << 16);
-            if (builtin_heap_start.value.i % 16 != 0) {
-                builtin_heap_start.value.i += 16 - (builtin_heap_start.value.i % 16);
-            }
+        if (*module->stack_top_ptr % 16 != 0) {
+            *module->stack_top_ptr += 16 - (*module->stack_top_ptr % 16);
         }
 
-        switch (entity->type) {
-            case Entity_Type_Foreign_Function_Header:
-                emit_foreign_function(module, entity->function);
-                // fallthrough
+        builtin_heap_start.value.i = *module->stack_top_ptr + (1 << 16);
+        if (builtin_heap_start.value.i % 16 != 0) {
+            builtin_heap_start.value.i += 16 - (builtin_heap_start.value.i % 16);
+        }
+    }
 
-            case Entity_Type_Function_Header:
-                if (!should_emit_function(entity->function)) break;
+    switch (ent->type) {
+        case Entity_Type_Foreign_Function_Header:
+            if (!should_emit_function(ent->function)) break;
+            
+            module->foreign_function_count++;
+            emit_foreign_function(module, ent->function);
+            // fallthrough
 
-                bh_imap_put(&module->index_map, (u64) entity->function, module->next_func_idx++);
-                break;
+        case Entity_Type_Function_Header:
+            if (!should_emit_function(ent->function)) break;
 
-            case Entity_Type_Global_Header: {
-                u64 global_idx;
-                if ((entity->global->flags & Ast_Flag_Foreign) != 0)
-                    global_idx = module->next_foreign_global_idx++;
-                else
-                    global_idx = module->next_global_idx++;
+            bh_imap_put(&module->index_map, (u64) ent->function, module->next_func_idx++);
+            break;
 
-                bh_imap_put(&module->index_map, (u64) entity->global, global_idx);
-                break;
-            }
+        case Entity_Type_Foreign_Global_Header:
+            module->foreign_global_count++;
+            emit_foreign_global(module, ent->global);
+            // fallthrough
 
-            case Entity_Type_String_Literal: {
-                emit_string_literal(module, (AstStrLit *) entity->strlit);
-                break;
-            }
-
-            case Entity_Type_File_Contents: {
-                emit_file_contents(module, (AstFileContents *) entity->file_contents);
-                break;
-            }
+        case Entity_Type_Global_Header:
+            bh_imap_put(&module->index_map, (u64) ent->global, module->next_global_idx++);
+            break;
 
-            case Entity_Type_Memory_Reservation: {
-                emit_memory_reservation(module, (AstMemRes *) entity->mem_res);
-                break;
-            }
+        case Entity_Type_String_Literal: {
+            emit_string_literal(module, (AstStrLit *) ent->strlit);
+            break;
+        }
 
-            case Entity_Type_Function: emit_function(module, entity->function); break;
-            case Entity_Type_Global:   emit_global(module,   entity->global); break;
+        case Entity_Type_File_Contents: {
+            emit_file_contents(module, (AstFileContents *) ent->file_contents);
+            break;
+        }
 
-            default: break;
+        case Entity_Type_Memory_Reservation: {
+            emit_memory_reservation(module, (AstMemRes *) ent->mem_res);
+            break;
         }
+
+        case Entity_Type_Function: emit_function(module, ent->function); break;
+        case Entity_Type_Global:   emit_global(module,   ent->global); break;
+
+        default: break;
     }
+
+    ent->state = Entity_State_Finalized;
 }
 
 void onyx_wasm_module_free(OnyxWasmModule* module) {