build/onyxclone.o \
build/onyxtypes.o \
build/onyxbuiltins.o \
+ build/onyxentities.o \
build/onyxsempass.o \
build/onyxsymres.o \
build/onyxchecker.o \
// 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;
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,
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;
};
} 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;
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;
// NOTE: Used wherever
ProgramInfo* program;
- bh_arr(Entity) other_entities;
// NOTE: Used in symbol resolution phase
Package* curr_package;
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
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;
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);
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;
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;
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 {
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;
AstNode* node = n->node;
AstKind nkind = node->kind;
+ ent.state = Entity_State_Resolve_Symbols;
ent.package = n->package;
ent.scope = n->scope;
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;
}
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;
}
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;
}
}
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;
}
}
}
+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) {
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;
}
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;
}
}
-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
--- /dev/null
+#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);
+}
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;
}
+// TODO: This file has become useless. It should be removed soon.
+
#define BH_DEBUG
#include "onyxsempass.h"
#include "onyxutils.h"
.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;
}
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
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) {
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:
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;
}
return concrete_struct;
}
-
-i32 sort_entities(const void* e1, const void* e2) {
- return ((Entity *)e1)->type - ((Entity *)e2)->type;
-}
#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
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,
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);
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,
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) {
.globals = NULL,
.next_global_idx = 0,
- .next_foreign_global_idx = 0,
.data = NULL,
.next_datum_offset = 0,
.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));
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) {