From: Brendan Hansen Date: Thu, 2 Jul 2020 21:46:29 +0000 (-0500) Subject: Code cleanup and optimizations X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=f6c25c8979eabdc270b7a14bcc0980588a5a7f80;p=onyx.git Code cleanup and optimizations --- diff --git a/include/onyxparser.h b/include/onyxparser.h index 137a1987..1adf8287 100644 --- a/include/onyxparser.h +++ b/include/onyxparser.h @@ -16,12 +16,11 @@ typedef struct OnyxAstNodeBlock OnyxAstNodeBlock; typedef struct OnyxAstNodeIf OnyxAstNodeIf; typedef struct OnyxAstNodeWhile OnyxAstNodeWhile; typedef struct OnyxAstNodeParam OnyxAstNodeParam; -typedef struct OnyxAstNodeFuncDef OnyxAstNodeFuncDef; +typedef struct OnyxAstNodeFunction OnyxAstNodeFunction; typedef struct OnyxAstNodeForeign OnyxAstNodeForeign; typedef struct OnyxAstNodeGlobal OnyxAstNodeGlobal; typedef struct OnyxAstNodeCall OnyxAstNodeCall; typedef struct OnyxAstNodeUse OnyxAstNodeUse; -typedef struct OnyxAstNodeFile OnyxAstNodeFile; typedef struct OnyxParser { OnyxTokenizer *tokenizer; // NOTE: not used since all tokens are lexed before parsing starts @@ -41,7 +40,7 @@ typedef enum OnyxAstNodeKind { ONYX_AST_NODE_KIND_PROGRAM, ONYX_AST_NODE_KIND_USE, - ONYX_AST_NODE_KIND_FUNCDEF, + ONYX_AST_NODE_KIND_FUNCTION, ONYX_AST_NODE_KIND_FOREIGN, ONYX_AST_NODE_KIND_BLOCK, ONYX_AST_NODE_KIND_SCOPE, @@ -222,7 +221,7 @@ struct OnyxAstNodeWhile { OnyxAstNodeBlock *body; }; -struct OnyxAstNodeFuncDef { +struct OnyxAstNodeFunction { OnyxAstNodeKind kind; u32 flags; OnyxToken *token; // This will point to the symbol token to identify it @@ -262,7 +261,7 @@ struct OnyxAstNodeCall { u64 data; OnyxAstNode *next; OnyxAstNode *callee; // NOTE: Function definition node - OnyxAstNode *arguments; // NOTE: Expressions that form the actual param list + OnyxAstNode *arguments; // NOTE: Expressions that form the actual param list // They will be chained down using the "next" property // unless this becomes used by something else }; @@ -277,16 +276,6 @@ struct OnyxAstNodeUse { OnyxToken *filename; }; -struct OnyxAstNodeFile { - OnyxAstNodeKind kind; - u32 flags; - OnyxToken *token; // NOTE: unused - OnyxTypeInfo *type; // NOTE: unused - u64 data; - OnyxAstNodeFile *next; // NOTE: next file - OnyxAstNode *contents; // NOTE: the first top-level element -}; - union OnyxAstNode { // Generic node structure for capturing all binary ops and statements @@ -302,7 +291,6 @@ union OnyxAstNode { }; OnyxAstNodeBlock as_block; - OnyxAstNodeFuncDef as_funcdef; OnyxAstNodeParam as_param; OnyxAstNodeLocal as_local; OnyxAstNodeScope as_scope; @@ -310,18 +298,25 @@ union OnyxAstNode { OnyxAstNodeNumLit as_numlit; OnyxAstNodeBinOp as_binop; OnyxAstNodeUnaryOp as_unaryop; - OnyxAstNodeForeign as_foreign; - OnyxAstNodeGlobal as_global; OnyxAstNodeIf as_if; OnyxAstNodeWhile as_while; OnyxAstNodeUse as_use; - OnyxAstNodeFile as_file; + OnyxAstNodeFunction as_function; + OnyxAstNodeGlobal as_global; + OnyxAstNodeForeign as_foreign; }; +typedef struct OnyxProgram { + bh_arr(OnyxAstNodeUse *) uses; + bh_arr(OnyxAstNodeGlobal *) globals; + bh_arr(OnyxAstNodeFunction *) functions; + bh_arr(OnyxAstNodeForeign *) foreigns; +} OnyxProgram; + const char* onyx_ast_node_kind_string(OnyxAstNodeKind kind); void* onyx_ast_node_new(bh_allocator alloc, OnyxAstNodeKind kind); OnyxParser onyx_parser_create(bh_allocator alloc, OnyxTokenizer *tokenizer, OnyxMessages* msgs); void onyx_parser_free(OnyxParser* parser); -OnyxAstNodeFile* onyx_parse(OnyxParser *parser); +OnyxAstNode* onyx_parse(OnyxParser *parser); #endif // #ifndef ONYXPARSER_H diff --git a/include/onyxsempass.h b/include/onyxsempass.h index 2174c3f3..eec02722 100644 --- a/include/onyxsempass.h +++ b/include/onyxsempass.h @@ -28,13 +28,13 @@ typedef struct OnyxSemPassState { } OnyxSemPassState; // NOTE: Resolving all symbols in the tree -void onyx_resolve_symbols(OnyxSemPassState* state, OnyxAstNodeFile* root_node); +void onyx_resolve_symbols(OnyxSemPassState* state, OnyxProgram* program); // NOTE: Inferring and checking types in the tree -void onyx_type_check(OnyxSemPassState* state, OnyxAstNodeFile* root_node); +void onyx_type_check(OnyxSemPassState* state, OnyxProgram* program); // NOTE: Full semantic pass OnyxSemPassState onyx_sempass_create(bh_allocator alloc, bh_allocator node_alloc, OnyxMessages* msgs); -void onyx_sempass(OnyxSemPassState* state, OnyxAstNodeFile* root_node); +void onyx_sempass(OnyxSemPassState* state, OnyxProgram* program); #endif diff --git a/include/onyxwasm.h b/include/onyxwasm.h index 327b08b7..1e6dcb90 100644 --- a/include/onyxwasm.h +++ b/include/onyxwasm.h @@ -308,7 +308,7 @@ typedef struct OnyxWasmModule { } OnyxWasmModule; OnyxWasmModule onyx_wasm_module_create(bh_allocator alloc, OnyxMessages* msgs); -void onyx_wasm_module_compile(OnyxWasmModule* module, OnyxAstNodeFile* program); +void onyx_wasm_module_compile(OnyxWasmModule* module, OnyxProgram* program); void onyx_wasm_module_free(OnyxWasmModule* module); void onyx_wasm_module_write_to_file(OnyxWasmModule* module, bh_file file); diff --git a/onyx b/onyx index c8eaac11..28115a9d 100755 Binary files a/onyx and b/onyx differ diff --git a/progs/test.onyx b/progs/test.onyx index 74600384..6a227be4 100644 --- a/progs/test.onyx +++ b/progs/test.onyx @@ -49,6 +49,8 @@ export main2 :: proc { } export main :: proc { + print_bool(in_unit_circle(0.5f, 0.5f)); + big_num := fib(factorial(4)); something :: other_value(0); diff --git a/src/onyx.c b/src/onyx.c index c7decfff..4c1975c4 100644 --- a/src/onyx.c +++ b/src/onyx.c @@ -55,10 +55,8 @@ typedef struct CompilerState { bh_table(bh_file_contents) loaded_files; bh_arr(const char *) queued_files; - OnyxAstNodeFile* first_file; - OnyxAstNodeFile* last_processed_file; - OnyxMessages msgs; + OnyxProgram program; OnyxWasmModule wasm_mod; } CompilerState; @@ -100,7 +98,7 @@ void compile_opts_free(OnyxCompileOptions* opts) { bh_arr_free(opts->files); } -OnyxAstNodeFile* parse_source_file(CompilerState* compiler_state, bh_file_contents* file_contents) { +OnyxAstNode* parse_source_file(CompilerState* compiler_state, bh_file_contents* file_contents) { // NOTE: Maybe don't want to recreate the tokenizer and parser for every file OnyxTokenizer tokenizer = onyx_tokenizer_create(compiler_state->token_alloc, file_contents); bh_printf("[Lexing] %s\n", file_contents->filename); @@ -126,44 +124,57 @@ CompilerProgress process_source_file(CompilerState* compiler_state, OnyxCompileO bh_file_contents fc = bh_file_read_contents(compiler_state->token_alloc, &file); bh_file_close(&file); - bh_table_put(bh_file_contents, compiler_state->loaded_files, (char *) filename, fc); // NOTE: Need to reget the value out of the table so token references work + bh_table_put(bh_file_contents, compiler_state->loaded_files, (char *) filename, fc); fc = bh_table_get(bh_file_contents, compiler_state->loaded_files, (char *) filename); - OnyxAstNodeFile* file_node = parse_source_file(compiler_state, &fc); + OnyxAstNode* root_node = parse_source_file(compiler_state, &fc); if (opts->print_ast) { - onyx_ast_print((OnyxAstNode *) file_node, 0); + onyx_ast_print(root_node, 0); bh_printf("\n"); } - if (!compiler_state->first_file) - compiler_state->first_file = file_node; - - if (compiler_state->last_processed_file) - compiler_state->last_processed_file->next = file_node; - - compiler_state->last_processed_file = file_node; - - - // HACK: This is very cobbled together right now but it will - // do for now - OnyxAstNode* walker = file_node->contents; + OnyxAstNode* walker = root_node; while (walker) { - if (walker->kind == ONYX_AST_NODE_KIND_USE) { - OnyxAstNodeUse* use_node = &walker->as_use; - - char* formatted_name = bh_aprintf( - global_heap_allocator, - "%b.onyx", - use_node->filename->token, use_node->filename->length); - - bh_arr_push(compiler_state->queued_files, formatted_name); + switch (walker->kind) { + case ONYX_AST_NODE_KIND_USE: + bh_arr_push(compiler_state->program.uses, &walker->as_use); + break; + + case ONYX_AST_NODE_KIND_GLOBAL: + bh_arr_push(compiler_state->program.globals, &walker->as_global); + break; + + case ONYX_AST_NODE_KIND_FOREIGN: + bh_arr_push(compiler_state->program.foreigns, &walker->as_foreign); + break; + + case ONYX_AST_NODE_KIND_FUNCTION: + bh_arr_push(compiler_state->program.functions, &walker->as_function); + break; + + case ONYX_AST_NODE_KIND_PROGRAM: + // Dummy initial node + break; + + default: + assert(("Invalid top level node", 0)); + break; } walker = walker->next; } + bh_arr_each(OnyxAstNodeUse *, use_node, compiler_state->program.uses) { + char* formatted_name = bh_aprintf( + global_heap_allocator, + "%b.onyx", + (*use_node)->filename->token, (*use_node)->filename->length); + + bh_arr_push(compiler_state->queued_files, formatted_name); + } + if (onyx_message_has_errors(&compiler_state->msgs)) { return ONYX_COMPILER_PROGRESS_FAILED_PARSE; @@ -212,7 +223,7 @@ i32 onyx_compile(OnyxCompileOptions* opts, CompilerState* compiler_state) { // NOTE: Check types and semantic rules bh_printf("[Checking semantics]\n"); OnyxSemPassState sp_state = onyx_sempass_create(compiler_state->sp_alloc, compiler_state->ast_alloc, &compiler_state->msgs); - onyx_sempass(&sp_state, compiler_state->first_file); + onyx_sempass(&sp_state, &compiler_state->program); if (onyx_message_has_errors(&compiler_state->msgs)) { return ONYX_COMPILER_PROGRESS_FAILED_SEMPASS; @@ -222,7 +233,7 @@ i32 onyx_compile(OnyxCompileOptions* opts, CompilerState* compiler_state) { // NOTE: Generate WASM instructions bh_printf("[Generating WASM]\n"); compiler_state->wasm_mod = onyx_wasm_module_create(opts->allocator, &compiler_state->msgs); - onyx_wasm_module_compile(&compiler_state->wasm_mod, compiler_state->first_file); + onyx_wasm_module_compile(&compiler_state->wasm_mod, &compiler_state->program); if (onyx_message_has_errors(&compiler_state->msgs)) { return ONYX_COMPILER_PROGRESS_FAILED_BINARY_GEN; @@ -259,9 +270,20 @@ int main(int argc, char *argv[]) { OnyxCompileOptions compile_opts = compile_opts_parse(global_heap_allocator, argc, argv); CompilerState compile_state = { + .program = { + .uses = NULL, + .foreigns = NULL, + .globals = NULL, + .functions = NULL + }, .wasm_mod = { 0 } }; + bh_arr_new(global_heap_allocator, compile_state.program.uses, 4); + bh_arr_new(global_heap_allocator, compile_state.program.foreigns, 4); + bh_arr_new(global_heap_allocator, compile_state.program.globals, 4); + bh_arr_new(global_heap_allocator, compile_state.program.functions, 4); + CompilerProgress compiler_progress = ONYX_COMPILER_PROGRESS_FAILED_READ; switch (compile_opts.action) { diff --git a/src/onyxparser.c b/src/onyxparser.c index 5cf6f232..d3379eba 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -8,7 +8,7 @@ static const char* ast_node_names[] = { "PROGRAM", "USE", - "FUNCDEF", + "FUNCTION", "FOREIGN", "BLOCK", "SCOPE", @@ -77,7 +77,7 @@ static OnyxAstNodeBlock* parse_block(OnyxParser* parser); static OnyxAstNode* parse_statement(OnyxParser* parser); static OnyxTypeInfo* parse_type(OnyxParser* parser); static OnyxAstNodeParam* parse_function_params(OnyxParser* parser); -static OnyxAstNodeFuncDef* parse_function_definition(OnyxParser* parser); +static OnyxAstNodeFunction* parse_function_definition(OnyxParser* parser); static OnyxAstNode* parse_top_level_statement(OnyxParser* parser); static void parser_next_token(OnyxParser* parser) { @@ -689,10 +689,10 @@ static OnyxAstNodeParam* parse_function_params(OnyxParser* parser) { return first_param; } -static OnyxAstNodeFuncDef* parse_function_definition(OnyxParser* parser) { +static OnyxAstNodeFunction* parse_function_definition(OnyxParser* parser) { expect(parser, TOKEN_TYPE_KEYWORD_PROC); - OnyxAstNodeFuncDef* func_def = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_FUNCDEF); + OnyxAstNodeFunction* func_def = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_FUNCTION); OnyxAstNodeParam* params = parse_function_params(parser); func_def->params = params; @@ -896,10 +896,10 @@ void onyx_parser_free(OnyxParser* parser) { bh_table_free(parser->identifiers); } -OnyxAstNodeFile* onyx_parse(OnyxParser *parser) { - OnyxAstNodeFile* program = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_PROGRAM); +OnyxAstNode* onyx_parse(OnyxParser *parser) { + OnyxAstNode* program = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_PROGRAM); - OnyxAstNode** prev_stmt = &program->contents; + OnyxAstNode** prev_stmt = &program->next; OnyxAstNode* curr_stmt = NULL; while (parser->curr_token->type != TOKEN_TYPE_END_STREAM) { curr_stmt = parse_top_level_statement(parser); diff --git a/src/onyxsempass.c b/src/onyxsempass.c index 9ce783a8..856055f5 100644 --- a/src/onyxsempass.c +++ b/src/onyxsempass.c @@ -23,80 +23,68 @@ OnyxSemPassState onyx_sempass_create(bh_allocator alloc, bh_allocator node_alloc // WASM, this function may not be needed. It brings all of the locals // defined in sub-scopes up to the function-block level. This is a // requirement of WASM, but not of other targets. -static void collapse_scopes(OnyxAstNodeFile* root_node) { +static void collapse_scopes(OnyxProgram* program) { bh_arr(OnyxAstNodeBlock*) traversal_queue = NULL; bh_arr_new(global_scratch_allocator, traversal_queue, 4); bh_arr_set_length(traversal_queue, 0); - OnyxAstNode* walker; - OnyxAstNodeFile* top_walker = root_node; - while (top_walker) { + bh_arr_each(OnyxAstNodeFunction *, func, program->functions) { + OnyxAstNodeScope* top_scope = (*func)->body->scope; - walker = top_walker->contents; - while (walker) { - if (walker->kind == ONYX_AST_NODE_KIND_FUNCDEF) { - OnyxAstNodeScope* top_scope = walker->as_funcdef.body->scope; + bh_arr_push(traversal_queue, (*func)->body); + while (!bh_arr_is_empty(traversal_queue)) { + OnyxAstNodeBlock* block = traversal_queue[0]; - bh_arr_push(traversal_queue, walker->as_funcdef.body); - while (!bh_arr_is_empty(traversal_queue)) { - OnyxAstNodeBlock* block = traversal_queue[0]; + if (block->kind == ONYX_AST_NODE_KIND_IF) { + OnyxAstNodeIf* if_node = (OnyxAstNodeIf *) block; + if (if_node->true_block) + bh_arr_push(traversal_queue, (OnyxAstNodeBlock *) if_node->true_block); - if (block->kind == ONYX_AST_NODE_KIND_IF) { - OnyxAstNodeIf* if_node = (OnyxAstNodeIf *) block; - if (if_node->true_block) - bh_arr_push(traversal_queue, (OnyxAstNodeBlock *) if_node->true_block); + if (if_node->false_block) + bh_arr_push(traversal_queue, (OnyxAstNodeBlock *) if_node->false_block); - if (if_node->false_block) - bh_arr_push(traversal_queue, (OnyxAstNodeBlock *) if_node->false_block); + } else { - } else { + if (block->scope != top_scope && block->scope->last_local != NULL) { + OnyxAstNodeLocal* last_local = block->scope->last_local; + while (last_local && last_local->prev_local != NULL) last_local = last_local->prev_local; - if (block->scope != top_scope && block->scope->last_local != NULL) { - OnyxAstNodeLocal* last_local = block->scope->last_local; - while (last_local && last_local->prev_local != NULL) last_local = last_local->prev_local; - - last_local->prev_local = top_scope->last_local; - top_scope->last_local = block->scope->last_local; - block->scope->last_local = NULL; - } - - OnyxAstNode* walker = block->body; - while (walker) { - if (walker->kind == ONYX_AST_NODE_KIND_BLOCK) { - bh_arr_push(traversal_queue, (OnyxAstNodeBlock *) walker); + last_local->prev_local = top_scope->last_local; + top_scope->last_local = block->scope->last_local; + block->scope->last_local = NULL; + } - } else if (walker->kind == ONYX_AST_NODE_KIND_WHILE) { - bh_arr_push(traversal_queue, walker->as_while.body); + OnyxAstNode* walker = block->body; + while (walker) { + if (walker->kind == ONYX_AST_NODE_KIND_BLOCK) { + bh_arr_push(traversal_queue, (OnyxAstNodeBlock *) walker); - } else if (walker->kind == ONYX_AST_NODE_KIND_IF) { - if (walker->as_if.true_block) - bh_arr_push(traversal_queue, (OnyxAstNodeBlock *) walker->as_if.true_block); + } else if (walker->kind == ONYX_AST_NODE_KIND_WHILE) { + bh_arr_push(traversal_queue, walker->as_while.body); - if (walker->as_if.false_block) - bh_arr_push(traversal_queue, (OnyxAstNodeBlock *) walker->as_if.false_block); - } + } else if (walker->kind == ONYX_AST_NODE_KIND_IF) { + if (walker->as_if.true_block) + bh_arr_push(traversal_queue, (OnyxAstNodeBlock *) walker->as_if.true_block); - walker = walker->next; - } + if (walker->as_if.false_block) + bh_arr_push(traversal_queue, (OnyxAstNodeBlock *) walker->as_if.false_block); } - bh_arr_deleten(traversal_queue, 0, 1); + walker = walker->next; } } - walker = walker->next; + bh_arr_deleten(traversal_queue, 0, 1); } - - top_walker = top_walker->next; } } -void onyx_sempass(OnyxSemPassState* state, OnyxAstNodeFile* root_node) { - onyx_resolve_symbols(state, root_node); +void onyx_sempass(OnyxSemPassState* state, OnyxProgram* program) { + onyx_resolve_symbols(state, program); if (onyx_message_has_errors(state->msgs)) return; - onyx_type_check(state, root_node); + onyx_type_check(state, program); if (onyx_message_has_errors(state->msgs)) return; - collapse_scopes(root_node); + collapse_scopes(program); } diff --git a/src/onyxsymres.c b/src/onyxsymres.c index 636f05b6..37c39aea 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -17,7 +17,7 @@ static void symres_while(OnyxSemPassState* state, OnyxAstNodeWhile* whilenode); static void symres_statement_chain(OnyxSemPassState* state, OnyxAstNode* walker, OnyxAstNode** trailer); static b32 symres_statement(OnyxSemPassState* state, OnyxAstNode* stmt); static void symres_block(OnyxSemPassState* state, OnyxAstNodeBlock* block); -static void symres_function_definition(OnyxSemPassState* state, OnyxAstNodeFuncDef* func); +static void symres_function(OnyxSemPassState* state, OnyxAstNodeFunction* func); static void symbol_introduce(OnyxSemPassState* state, OnyxAstNode* symbol) { onyx_token_null_toggle(*symbol->token); @@ -238,7 +238,7 @@ static void symres_block(OnyxSemPassState* state, OnyxAstNodeBlock* block) { scope_leave(state); } -static void symres_function_definition(OnyxSemPassState* state, OnyxAstNodeFuncDef* func) { +static void symres_function(OnyxSemPassState* state, OnyxAstNodeFunction* func) { forll(OnyxAstNodeParam, param, func->params, next) { symbol_introduce(state, (OnyxAstNode *) param); } @@ -250,50 +250,24 @@ static void symres_function_definition(OnyxSemPassState* state, OnyxAstNodeFuncD } } -void onyx_resolve_symbols(OnyxSemPassState* state, OnyxAstNodeFile* root_node) { - OnyxAstNode* walker; - OnyxAstNodeFile* top_walker = root_node; - while (top_walker) { - - walker = top_walker->contents; - while (walker) { - switch (walker->kind) { - case ONYX_AST_NODE_KIND_FUNCDEF: - case ONYX_AST_NODE_KIND_GLOBAL: - if (!symbol_unique_introduce(state, walker)) return; - break; - - case ONYX_AST_NODE_KIND_FOREIGN: - if (walker->as_foreign.import->kind == ONYX_AST_NODE_KIND_FUNCDEF - || walker->as_foreign.import->kind == ONYX_AST_NODE_KIND_GLOBAL) { - if (!symbol_unique_introduce(state, walker->as_foreign.import)) return; - } - break; - - default: break; - } +void onyx_resolve_symbols(OnyxSemPassState* state, OnyxProgram* program) { - walker = walker->next; - } + // NOTE: First, introduce all global symbols + bh_arr_each(OnyxAstNodeGlobal *, global, program->globals) + if (!symbol_unique_introduce(state, (OnyxAstNode *) *global)) return; - top_walker = top_walker->next; - } + bh_arr_each(OnyxAstNodeFunction *, function, program->functions) + if (!symbol_unique_introduce(state, (OnyxAstNode *) *function)) return; - top_walker = root_node; - while (top_walker) { + bh_arr_each(OnyxAstNodeForeign *, foreign, program->foreigns) { + OnyxAstNodeKind import_kind = (*foreign)->import->kind; - walker = top_walker->contents; - while (walker) { - switch (walker->kind) { - case ONYX_AST_NODE_KIND_FUNCDEF: - symres_function_definition(state, &walker->as_funcdef); - break; - default: break; - } + if (import_kind == ONYX_AST_NODE_KIND_FUNCTION || import_kind == ONYX_AST_NODE_KIND_GLOBAL) + if (!symbol_unique_introduce(state, (*foreign)->import)) return; + } - walker = walker->next; - } - top_walker = top_walker->next; - } + // NOTE: Then, resolve all symbols in all functions + bh_arr_each(OnyxAstNodeFunction *, function, program->functions) + symres_function(state, *function); } diff --git a/src/onyxtypecheck.c b/src/onyxtypecheck.c index b64bc427..9d2f96e3 100644 --- a/src/onyxtypecheck.c +++ b/src/onyxtypecheck.c @@ -1,7 +1,7 @@ #define BH_DEBUG #include "onyxsempass.h" -static void typecheck_function_defintion(OnyxSemPassState* state, OnyxAstNodeFuncDef* func); +static void typecheck_function(OnyxSemPassState* state, OnyxAstNodeFunction* func); static void typecheck_block(OnyxSemPassState* state, OnyxAstNodeBlock* block); static void typecheck_statement_chain(OnyxSemPassState* state, OnyxAstNode* start); static void typecheck_statement(OnyxSemPassState* state, OnyxAstNode* stmt); @@ -101,7 +101,7 @@ static void typecheck_while(OnyxSemPassState* state, OnyxAstNodeWhile* whilenode } static void typecheck_call(OnyxSemPassState* state, OnyxAstNodeCall* call) { - OnyxAstNodeFuncDef* callee = (OnyxAstNodeFuncDef *) call->callee; + OnyxAstNodeFunction* callee = (OnyxAstNodeFunction *) call->callee; if (callee->kind == ONYX_AST_NODE_KIND_SYMBOL) { onyx_message_add(state->msgs, @@ -111,7 +111,7 @@ static void typecheck_call(OnyxSemPassState* state, OnyxAstNodeCall* call) { return; } - if (callee->kind != ONYX_AST_NODE_KIND_FUNCDEF) { + if (callee->kind != ONYX_AST_NODE_KIND_FUNCTION) { onyx_message_add(state->msgs, ONYX_MESSAGE_TYPE_CALL_NON_FUNCTION, call->token->pos, @@ -322,7 +322,7 @@ static void typecheck_block(OnyxSemPassState* state, OnyxAstNodeBlock* block) { } } -static void typecheck_function_defintion(OnyxSemPassState* state, OnyxAstNodeFuncDef* func) { +static void typecheck_function(OnyxSemPassState* state, OnyxAstNodeFunction* func) { forll(OnyxAstNodeParam, param, func->params, next) { if (!param->type->is_known) { onyx_message_add(state->msgs, @@ -347,46 +347,11 @@ static void typecheck_function_defintion(OnyxSemPassState* state, OnyxAstNodeFun } } -void onyx_type_check(OnyxSemPassState* state, OnyxAstNodeFile* root_node) { - // TODO: This code is very ugly, but the types of globals need to - // be resolved before any function can use them +void onyx_type_check(OnyxSemPassState* state, OnyxProgram* program) { - OnyxAstNode* walker; - OnyxAstNodeFile* top_walker = root_node; - while (top_walker) { + bh_arr_each(OnyxAstNodeGlobal *, global, program->globals) + typecheck_global(state, *global); - walker = top_walker->contents; - while (walker) { - switch (walker->kind) { - case ONYX_AST_NODE_KIND_GLOBAL: - typecheck_global(state, &walker->as_global); - break; - - default: break; - } - - walker = walker->next; - } - - top_walker = top_walker->next; - } - - top_walker = root_node; - while (top_walker) { - - walker = top_walker->contents; - while (walker) { - switch (walker->kind) { - case ONYX_AST_NODE_KIND_FUNCDEF: - typecheck_function_defintion(state, &walker->as_funcdef); - break; - - default: break; - } - - walker = walker->next; - } - - top_walker = top_walker->next; - } + bh_arr_each(OnyxAstNodeFunction *, function, program->functions) + typecheck_function(state, *function); } diff --git a/src/onyxutils.c b/src/onyxutils.c index b40a44c0..20726026 100644 --- a/src/onyxutils.c +++ b/src/onyxutils.c @@ -17,17 +17,6 @@ void onyx_ast_print(OnyxAstNode* node, i32 indent) { bh_printf("(%d) %s ", node->flags, onyx_ast_node_kind_string(node->kind)); switch (node->kind) { - case ONYX_AST_NODE_KIND_PROGRAM: { - OnyxAstNodeFile* file_node = &node->as_file; - if (file_node->contents) - onyx_ast_print(file_node->contents, indent + 1); - - if (node->next) - onyx_ast_print(node->next, indent); - - break; - } - case ONYX_AST_NODE_KIND_USE: { OnyxAstNodeUse* use_node = &node->as_use; bh_printf("%b", use_node->filename->token, use_node->filename->length); @@ -38,10 +27,10 @@ void onyx_ast_print(OnyxAstNode* node, i32 indent) { break; } - case ONYX_AST_NODE_KIND_FUNCDEF: { + case ONYX_AST_NODE_KIND_FUNCTION: { if (node->token) bh_printf("(%b) ", node->token->token, node->token->length); - OnyxAstNodeFuncDef* fd = &node->as_funcdef; + OnyxAstNodeFunction* fd = &node->as_function; print_indent; bh_printf("Params "); @@ -151,7 +140,7 @@ void onyx_ast_print(OnyxAstNode* node, i32 indent) { case ONYX_AST_NODE_KIND_CALL: { OnyxAstNodeCall* call = &node->as_call; if (call->callee) { - if (call->callee->kind == ONYX_AST_NODE_KIND_FUNCDEF) { + if (call->callee->kind == ONYX_AST_NODE_KIND_FUNCTION) { bh_printf("function: %b", call->callee->token->token, call->callee->token->length); } else { onyx_ast_print(call->callee, indent + 1); diff --git a/src/onyxwasm.c b/src/onyxwasm.c index fd9690bf..206883f2 100644 --- a/src/onyxwasm.c +++ b/src/onyxwasm.c @@ -209,7 +209,7 @@ static WasmType onyx_type_to_wasm_type(OnyxTypeInfo* type) { return WASM_TYPE_VOID; } -static void compile_function_body(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNodeFuncDef* fd); +static void compile_function_body(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNodeFunction* fd); static void compile_block(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNodeBlock* block); static void compile_statement(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNode* stmt); static void compile_assign_lval(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNode* lval); @@ -222,7 +222,7 @@ static void compile_expression(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pco static void compile_cast(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNodeUnaryOp* cast); static void compile_return(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNode* ret); -static void compile_function_body(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNodeFuncDef* fd) { +static void compile_function_body(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNodeFunction* fd) { if (fd->body == NULL) return; bh_arr(WasmInstruction) code = *pcode; @@ -639,7 +639,7 @@ static void compile_return(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, *pcode = code; } -static i32 generate_type_idx(OnyxWasmModule* mod, OnyxAstNodeFuncDef* fd) { +static i32 generate_type_idx(OnyxWasmModule* mod, OnyxAstNodeFunction* fd) { static char type_repr_buf[128]; char* t = type_repr_buf; @@ -681,7 +681,7 @@ static i32 generate_type_idx(OnyxWasmModule* mod, OnyxAstNodeFuncDef* fd) { return type_idx; } -static void compile_function_definition(OnyxWasmModule* mod, OnyxAstNodeFuncDef* fd) { +static void compile_function(OnyxWasmModule* mod, OnyxAstNodeFunction* fd) { i32 type_idx = generate_type_idx(mod, fd); WasmFunc wasm_func = { @@ -786,8 +786,8 @@ static void compile_global_declaration(OnyxWasmModule* module, OnyxAstNodeGlobal } static void compile_foreign(OnyxWasmModule* module, OnyxAstNodeForeign* foreign) { - if (foreign->import->kind == ONYX_AST_NODE_KIND_FUNCDEF) { - i32 type_idx = generate_type_idx(module, &foreign->import->as_funcdef); + if (foreign->import->kind == ONYX_AST_NODE_KIND_FUNCTION) { + i32 type_idx = generate_type_idx(module, &foreign->import->as_function); WasmImport import = { .kind = WASM_FOREIGN_FUNCTION, @@ -861,88 +861,37 @@ OnyxWasmModule onyx_wasm_module_create(bh_allocator alloc, OnyxMessages* msgs) { return module; } -void onyx_wasm_module_compile(OnyxWasmModule* module, OnyxAstNodeFile* program) { - OnyxAstNode* walker; - OnyxAstNodeFile* top_walker = program; - while (top_walker) { +void onyx_wasm_module_compile(OnyxWasmModule* module, OnyxProgram* program) { - walker = top_walker->contents; - while (walker) { - if (walker->kind == ONYX_AST_NODE_KIND_FOREIGN) { - if (walker->as_foreign.import->kind == ONYX_AST_NODE_KIND_FUNCDEF) - module->next_func_idx++; + // NOTE: First, introduce all indicies for globals and functions + bh_arr_each(OnyxAstNodeForeign *, foreign, program->foreigns) { + OnyxAstNodeKind import_kind = (*foreign)->import->kind; - if (walker->as_foreign.import->kind == ONYX_AST_NODE_KIND_GLOBAL) - module->next_global_idx++; - } - - walker = walker->next; + if (import_kind == ONYX_AST_NODE_KIND_FUNCTION) { + module->next_func_idx++; + bh_imap_put(&module->func_map, (u64) (*foreign)->import, module->next_import_func_idx++); } - - top_walker = top_walker->next; - } - - top_walker = program; - while (top_walker) { - - walker = top_walker->contents; - while (walker) { - if (walker->kind == ONYX_AST_NODE_KIND_FUNCDEF) { - i32 func_idx = module->next_func_idx++; - bh_imap_put(&module->func_map, (u64) walker, func_idx); - } - - if (walker->kind == ONYX_AST_NODE_KIND_GLOBAL) { - i32 global_idx = module->next_global_idx++; - bh_imap_put(&module->global_map, (u64) walker, global_idx); - } - - if (walker->kind == ONYX_AST_NODE_KIND_FOREIGN) { - OnyxAstNodeForeign* foreign = &walker->as_foreign; - - if (foreign->import->kind == ONYX_AST_NODE_KIND_FUNCDEF) { - i32 func_idx = module->next_import_func_idx++; - bh_imap_put(&module->func_map, (u64) foreign->import, func_idx); - } - - if (foreign->import->kind == ONYX_AST_NODE_KIND_GLOBAL) { - i32 global_idx = module->next_import_global_idx++; - bh_imap_put(&module->global_map, (u64) foreign->import, global_idx); - } - } - - walker = walker->next; + else if (import_kind == ONYX_AST_NODE_KIND_GLOBAL) { + module->next_global_idx++; + bh_imap_put(&module->global_map, (u64) (*foreign)->import, module->next_import_func_idx++); } - top_walker = top_walker->next; + compile_foreign(module, *foreign); } - top_walker = program; - while (top_walker) { + bh_arr_each(OnyxAstNodeFunction *, function, program->functions) + bh_imap_put(&module->func_map, (u64) *function, module->next_func_idx++); - walker = top_walker->contents; - while (walker) { - switch (walker->kind) { - case ONYX_AST_NODE_KIND_FUNCDEF: - compile_function_definition(module, &walker->as_funcdef); - break; + bh_arr_each(OnyxAstNodeGlobal *, global, program->globals) + bh_imap_put(&module->global_map, (u64) *global, module->next_global_idx++); - case ONYX_AST_NODE_KIND_GLOBAL: - compile_global_declaration(module, &walker->as_global); - break; - case ONYX_AST_NODE_KIND_FOREIGN: - compile_foreign(module, &walker->as_foreign); - break; + // NOTE: Then, compile everything + bh_arr_each(OnyxAstNodeFunction *, function, program->functions) + compile_function(module, *function); - default: break; - } - - walker = walker->next; - } - - top_walker = top_walker->next; - } + bh_arr_each(OnyxAstNodeGlobal *, global, program->globals) + compile_global_declaration(module, *global); } void onyx_wasm_module_free(OnyxWasmModule* module) {