From 024294c2adf15f8224161f0353770344e6478057 Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Tue, 23 Jun 2020 21:10:40 -0500 Subject: [PATCH] Fully compiling to WASM again --- docs/plan | 6 +- include/onyxwasm.h | 3 +- onyx | Bin 185128 -> 192544 bytes progs/game.onyx | 2 + progs/minimal.onyx | 12 +++- progs/new_minimal.onyx | 8 ++- src/onyx.c | 17 ++--- src/onyxsempass.c | 64 ++++++++++++++++- src/onyxtypecheck.c | 18 ++++- src/onyxwasm.c | 151 +++++++++++++++++++++++++---------------- 10 files changed, 202 insertions(+), 79 deletions(-) diff --git a/docs/plan b/docs/plan index fa9396ab..ac906133 100644 --- a/docs/plan +++ b/docs/plan @@ -62,10 +62,10 @@ HOW: [ ] Simple while loop is functioning as expected [ ] break and continue semantics [X] Function calling works for the builtin types - [ ] Function return values are type checked + [X] Function return values are type checked Stage 2: - [ ] Order of symbol declaration is irrelevant + [X] Order of symbol declaration is irrelevant Either: make a graph of symbol dependencies and produce a schedule on the graph that would allow for all symbols to be resolved @@ -76,7 +76,7 @@ HOW: This could be slow but it would be easier than creating a graph scheduling algorithm. - [ ] Consequence of the above, recursion works + [X] Consequence of the above, recursion works [ ] Devise and implement a simple set of implicit type casting rules. - Numeric literals always type cast to whatever type is needed (very flexible). diff --git a/include/onyxwasm.h b/include/onyxwasm.h index 3ae0f67e..1fcd8d36 100644 --- a/include/onyxwasm.h +++ b/include/onyxwasm.h @@ -292,7 +292,8 @@ typedef struct OnyxWasmModule { i32 export_count; } OnyxWasmModule; -OnyxWasmModule onyx_wasm_generate_module(bh_allocator alloc, OnyxAstNode* program); +OnyxWasmModule onyx_wasm_module_create(bh_allocator alloc); +void onyx_wasm_module_compile(OnyxWasmModule* module, OnyxAstNode* 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 8c6c53a73be7048de096302eae3d6e624f3730f8..1c06a808a2322bcea86d37ecdc07a2903a7c9be0 100755 GIT binary patch delta 59868 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
quNuDH}a>RYV2 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 delta 55067 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

* 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 F{{Uo@UWxz! diff --git a/progs/game.onyx b/progs/game.onyx index 5f90fd72..a37d4c59 100644 --- a/progs/game.onyx +++ b/progs/game.onyx @@ -2,6 +2,8 @@ gfx_draw_rect :: foreign "gfx" "draw_rect" proc (x i32, y i32, w i32, h i32) --- export main :: proc { + update(); + draw(); } update :: proc {} diff --git a/progs/minimal.onyx b/progs/minimal.onyx index 38b1d12e..76197666 100644 --- a/progs/minimal.onyx +++ b/progs/minimal.onyx @@ -4,20 +4,21 @@ print_float :: foreign "host" "print" proc (value f32) --- print_if :: foreign "host" "print" proc (i i32, f f32) --- export main :: proc { - output := do_stuff(); + output := do_stuff() - 1; if output == -66 { new_output := abs(output) * 2; print(new_output); } elseif output == -67 { - new_output := 10; - print(1234); + print(factorial(6)); } else { print(-1); } + print(fib(5)); + print(output); print_float(float_test()); @@ -48,6 +49,11 @@ abs :: proc (val i32) -> i32 { return val; } +fib :: proc (n i32) -> i32 { + if n <= 1 { return 1; } + return fib(n - 1) + fib(n - 2); +} + diff_square :: proc (a i32, b i32) -> i32 { // Typechecked c := a - b; // Mutable diff --git a/progs/new_minimal.onyx b/progs/new_minimal.onyx index 56c8f0b6..d0e74323 100644 --- a/progs/new_minimal.onyx +++ b/progs/new_minimal.onyx @@ -2,7 +2,7 @@ print :: foreign "host" "print" proc (value i32) --- simple_test :: proc { a: i32 = 5; - b: i64 = 6 as i64; + b: i32 = 6; if a > b { foo := 123; @@ -13,6 +13,12 @@ simple_test :: proc { print(c); } +fib :: proc (n i32) -> i32 { + if n <= 1 { return 1; } + + return fib(n - 1) + fib(n - 2); +} + foo :: proc -> i32 { return 10; } diff --git a/src/onyx.c b/src/onyx.c index 4699a7e6..6561b53c 100644 --- a/src/onyx.c +++ b/src/onyx.c @@ -69,14 +69,15 @@ int main(int argc, char *argv[]) { // NOTE: 4th: Generate a WASM module from the parse tree and // write it to a file. -// OnyxWasmModule wasm_mod = onyx_wasm_generate_module(alloc, program); -// -// bh_file out_file; -// bh_file_create(&out_file, "out.wasm"); -// onyx_wasm_module_write_to_file(&wasm_mod, out_file); -// bh_file_close(&out_file); -// -// onyx_wasm_module_free(&wasm_mod); + OnyxWasmModule wasm_mod = onyx_wasm_module_create(alloc); + onyx_wasm_module_compile(&wasm_mod, program); + + bh_file out_file; + bh_file_create(&out_file, "out.wasm"); + onyx_wasm_module_write_to_file(&wasm_mod, out_file); + bh_file_close(&out_file); + + onyx_wasm_module_free(&wasm_mod); main_exit: // NOTE: Cleanup, since C doesn't have defer bh_arena_free(&sp_arena); bh_arena_free(&msg_arena); diff --git a/src/onyxsempass.c b/src/onyxsempass.c index 0426789b..587786a4 100644 --- a/src/onyxsempass.c +++ b/src/onyxsempass.c @@ -1,5 +1,6 @@ #define BH_DEBUG #include "onyxsempass.h" +#include "onyxutils.h" OnyxSemPassState onyx_sempass_create(bh_allocator alloc, bh_allocator node_alloc, OnyxMessages* msgs) { OnyxSemPassState state = { @@ -17,12 +18,71 @@ OnyxSemPassState onyx_sempass_create(bh_allocator alloc, bh_allocator node_alloc return state; } -static void collapse_scopes(OnyxAstNode* root_node, OnyxAstNodeScope* prev_scope) { +// NOTE: If the compiler is expanded to support more targets than just +// 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(OnyxAstNode* root_node) { + bh_arr(OnyxAstNodeBlock*) traversal_queue = NULL; + bh_arr_new(global_scratch_allocator, traversal_queue, 4); + bh_arr_set_length(traversal_queue, 0); + + OnyxAstNode* walker = root_node; + while (walker) { + if (walker->kind == ONYX_AST_NODE_KIND_FUNCDEF) { + OnyxAstNodeScope* top_scope = walker->as_funcdef.body->scope; + + 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 (if_node->false_block) + bh_arr_push(traversal_queue, (OnyxAstNodeBlock *) if_node->false_block); + + } 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; + + 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); + + } 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); + + if (walker->as_if.false_block) + bh_arr_push(traversal_queue, (OnyxAstNodeBlock *) walker->as_if.false_block); + } + + walker = walker->next; + } + } + + bh_arr_deleten(traversal_queue, 0, 1); + } + } + + walker = walker->next; + } } void onyx_sempass(OnyxSemPassState* state, OnyxAstNode* root_node) { onyx_resolve_symbols(state, root_node); onyx_type_check(state, root_node); - collapse_scopes(root_node, NULL); + collapse_scopes(root_node); } diff --git a/src/onyxtypecheck.c b/src/onyxtypecheck.c index 9a620468..3f0cb9e7 100644 --- a/src/onyxtypecheck.c +++ b/src/onyxtypecheck.c @@ -72,7 +72,15 @@ static void typecheck_return(OnyxSemPassState* state, OnyxAstNode* retnode) { } static void typecheck_if(OnyxSemPassState* state, OnyxAstNodeIf* ifnode) { - // NOTE: Add check for boolean type on condition + typecheck_expression(state, ifnode->cond); + if (ifnode->cond->type != &builtin_types[ONYX_TYPE_INFO_KIND_INT32]) { + onyx_message_add(state->msgs, + ONYX_MESSAGE_TYPE_LITERAL, + ifnode->cond->token->pos, + "expected integer type for condition"); + return; + } + if (ifnode->true_block) typecheck_statement(state, ifnode->true_block); if (ifnode->false_block) typecheck_statement(state, ifnode->false_block); } @@ -277,6 +285,14 @@ static void typecheck_function_defintion(OnyxSemPassState* state, OnyxAstNodeFun "function parameter types must be known"); return; } + + if (param->type->size == 0) { + onyx_message_add(state->msgs, + ONYX_MESSAGE_TYPE_LITERAL, + param->token->pos, + "function parameters must have non-void types"); + return; + } } state->expected_return_type = func->return_type; diff --git a/src/onyxwasm.c b/src/onyxwasm.c index 771f913d..4d4a4240 100644 --- a/src/onyxwasm.c +++ b/src/onyxwasm.c @@ -208,48 +208,48 @@ static WasmType onyx_type_to_wasm_type(OnyxTypeInfo* type) { return WASM_TYPE_VOID; } -static void process_function_body(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNodeFuncDef* fd); -static void process_block(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNodeBlock* block); -static void process_statement(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* stmt); -static void process_assign_lval(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* lval); -static void process_assignment(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* assign); -static void process_if(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNodeIf* if_node); -static void process_expression(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* expr); -static void process_cast(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* cast); -static void process_return(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* ret); - -static void process_function_body(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNodeFuncDef* fd) { +static void compile_function_body(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNodeFuncDef* fd); +static void compile_block(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNodeBlock* block); +static void compile_statement(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* stmt); +static void compile_assign_lval(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* lval); +static void compile_assignment(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* assign); +static void compile_if(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNodeIf* if_node); +static void compile_expression(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* expr); +static void compile_cast(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* cast); +static void compile_return(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* ret); + +static void compile_function_body(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNodeFuncDef* fd) { if (fd->body == NULL) return; forll (OnyxAstNode, stmt, fd->body->body, next) { - process_statement(mod, func, stmt); + compile_statement(mod, func, stmt); } bh_arr_push(func->code, ((WasmInstruction){ WI_BLOCK_END, 0x00 })); } -static void process_block(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNodeBlock* block) { +static void compile_block(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNodeBlock* block) { bh_arr_push(func->code, ((WasmInstruction){ WI_BLOCK_START, 0x40 })); forll (OnyxAstNode, stmt, block->body, next) { - process_statement(mod, func, stmt); + compile_statement(mod, func, stmt); } bh_arr_push(func->code, ((WasmInstruction){ WI_BLOCK_END, 0x00 })); } -static void process_statement(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* stmt) { +static void compile_statement(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* stmt) { switch (stmt->kind) { case ONYX_AST_NODE_KIND_SCOPE: break; - case ONYX_AST_NODE_KIND_RETURN: process_return(mod, func, stmt); break; - case ONYX_AST_NODE_KIND_ASSIGNMENT: process_assignment(mod, func, stmt); break; - case ONYX_AST_NODE_KIND_IF: process_if(mod, func, (OnyxAstNodeIf *) stmt); break; - case ONYX_AST_NODE_KIND_CALL: process_expression(mod, func, stmt); break; + case ONYX_AST_NODE_KIND_RETURN: compile_return(mod, func, stmt); break; + case ONYX_AST_NODE_KIND_ASSIGNMENT: compile_assignment(mod, func, stmt); break; + case ONYX_AST_NODE_KIND_IF: compile_if(mod, func, (OnyxAstNodeIf *) stmt); break; + case ONYX_AST_NODE_KIND_CALL: compile_expression(mod, func, stmt); break; default: break; } } -static void process_assign_lval(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* lval) { +static void compile_assign_lval(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* lval) { if (lval->kind == ONYX_AST_NODE_KIND_LOCAL || lval->kind == ONYX_AST_NODE_KIND_PARAM) { i32 localidx = (i32) bh_imap_get(&mod->local_map, (u64) lval); @@ -259,31 +259,44 @@ static void process_assign_lval(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode } } -static void process_if(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNodeIf* if_node) { - process_expression(mod, func, if_node->cond); +static void compile_if(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNodeIf* if_node) { + compile_expression(mod, func, if_node->cond); bh_arr_push(func->code, ((WasmInstruction){ WI_IF_START, 0x40 })); if (if_node->true_block) { // NOTE: This is kind of gross, but making a function for this doesn't feel right - forll (OnyxAstNode, stmt, if_node->true_block, next) { - process_statement(mod, func, stmt); + + if (if_node->true_block->kind == ONYX_AST_NODE_KIND_IF) { + forll (OnyxAstNode, stmt, if_node->true_block, next) { + compile_statement(mod, func, stmt); + } + } else if (if_node->true_block->kind == ONYX_AST_NODE_KIND_BLOCK) { + forll (OnyxAstNode, stmt, if_node->true_block->as_block.body, next) { + compile_statement(mod, func, stmt); + } } } if (if_node->false_block) { bh_arr_push(func->code, ((WasmInstruction){ WI_ELSE, 0x00 })); - forll (OnyxAstNode, stmt, if_node->false_block, next) { - process_statement(mod, func, stmt); + if (if_node->false_block->kind == ONYX_AST_NODE_KIND_IF) { + forll (OnyxAstNode, stmt, if_node->false_block, next) { + compile_statement(mod, func, stmt); + } + } else if (if_node->false_block->kind == ONYX_AST_NODE_KIND_BLOCK) { + forll (OnyxAstNode, stmt, if_node->false_block->as_block.body, next) { + compile_statement(mod, func, stmt); + } } } bh_arr_push(func->code, ((WasmInstruction){ WI_IF_END, 0x00 })); } -static void process_assignment(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* assign) { - process_expression(mod, func, assign->right); - process_assign_lval(mod, func, assign->left); +static void compile_assignment(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* assign) { + compile_expression(mod, func, assign->right); + compile_assign_lval(mod, func, assign->left); } #define BIN_OP_PROCESS(ast_binop, wasm_binop) \ @@ -300,8 +313,8 @@ static void process_assignment(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* default: assert(("Invalid type", 0)); \ } \ \ - process_expression(mod, func, expr->left); \ - process_expression(mod, func, expr->right); \ + compile_expression(mod, func, expr->left); \ + compile_expression(mod, func, expr->right); \ bh_arr_push(func->code, ((WasmInstruction){ instr_type, 0x00 })); \ break; \ } @@ -326,13 +339,13 @@ static void process_assignment(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* default: assert(("Invalid type", 0)); \ } \ \ - process_expression(mod, func, expr->left); \ - process_expression(mod, func, expr->right); \ + compile_expression(mod, func, expr->left); \ + compile_expression(mod, func, expr->right); \ bh_arr_push(func->code, ((WasmInstruction){ instr_type, 0x00 })); \ break; \ } -static void process_expression(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* expr) { +static void compile_expression(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* expr) { switch (expr->kind) { BIN_OP_PROCESS(ADD, ADD); BIN_OP_PROCESS(MINUS, SUB); @@ -361,8 +374,8 @@ static void process_expression(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* default: assert(("Invalid type", 0)); } - process_expression(mod, func, expr->left); - process_expression(mod, func, expr->right); + compile_expression(mod, func, expr->left); + compile_expression(mod, func, expr->right); bh_arr_push(func->code, ((WasmInstruction){ instr_type, 0x00 })); break; } @@ -373,16 +386,16 @@ static void process_expression(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* if (type_kind == ONYX_TYPE_INFO_KIND_INT32) { bh_arr_push(func->code, ((WasmInstruction){ WI_I32_CONST, 0x00 })); - process_expression(mod, func, expr->left); + compile_expression(mod, func, expr->left); bh_arr_push(func->code, ((WasmInstruction){ WI_I32_SUB, 0x00 })); } else if (type_kind == ONYX_TYPE_INFO_KIND_INT64) { bh_arr_push(func->code, ((WasmInstruction){ WI_I64_CONST, 0x00 })); - process_expression(mod, func, expr->left); + compile_expression(mod, func, expr->left); bh_arr_push(func->code, ((WasmInstruction){ WI_I64_SUB, 0x00 })); } else { - process_expression(mod, func, expr->left); + compile_expression(mod, func, expr->left); if (type_kind == ONYX_TYPE_INFO_KIND_FLOAT32) bh_arr_push(func->code, ((WasmInstruction){ WI_F32_NEG, 0x00 })); @@ -402,7 +415,7 @@ static void process_expression(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* break; } - case ONYX_AST_NODE_KIND_CAST: process_cast(mod, func, expr); break; + case ONYX_AST_NODE_KIND_CAST: compile_cast(mod, func, expr); break; case ONYX_AST_NODE_KIND_LITERAL: { OnyxAstNodeNumLit* lit = &expr->as_numlit; @@ -427,13 +440,13 @@ static void process_expression(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* break; } - case ONYX_AST_NODE_KIND_BLOCK: process_block(mod, func, (OnyxAstNodeBlock *) expr); break; + case ONYX_AST_NODE_KIND_BLOCK: compile_block(mod, func, (OnyxAstNodeBlock *) expr); break; case ONYX_AST_NODE_KIND_CALL: { OnyxAstNodeCall* call = &expr->as_call; forll (OnyxAstNode, arg, call->arguments, next) { - process_expression(mod, func, arg->left); + compile_expression(mod, func, arg->left); } i32 func_idx = (i32) bh_imap_get(&mod->func_map, (u64) call->callee); @@ -459,8 +472,8 @@ static const WasmInstructionType cast_map[][6] = { /* F64 */ { WI_I32_FROM_F64_S, WI_I32_FROM_F64_U, WI_I64_FROM_F64_S, WI_I64_FROM_F64_U, WI_F32_FROM_F64, WI_NOP, }, }; -static void process_cast(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* cast) { - process_expression(mod, func, cast->left); +static void compile_cast(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* cast) { + compile_expression(mod, func, cast->left); OnyxTypeInfo* from = cast->left->type; OnyxTypeInfo* to = cast->type; @@ -492,9 +505,9 @@ static void process_cast(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* cast) } } -static void process_return(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* ret) { +static void compile_return(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* ret) { if (ret->left) { - process_expression(mod, func, ret->left); + compile_expression(mod, func, ret->left); } bh_arr_push(func->code, ((WasmInstruction){ WI_RETURN, 0x00 })); @@ -542,7 +555,7 @@ static i32 generate_type_idx(OnyxWasmModule* mod, OnyxAstNodeFuncDef* fd) { return type_idx; } -static void process_function_definition(OnyxWasmModule* mod, OnyxAstNodeFuncDef* fd) { +static void compile_function_definition(OnyxWasmModule* mod, OnyxAstNodeFuncDef* fd) { i32 type_idx = generate_type_idx(mod, fd); WasmFunc wasm_func = { @@ -555,12 +568,12 @@ static void process_function_definition(OnyxWasmModule* mod, OnyxAstNodeFuncDef* }, .code = NULL, }; - i32 func_idx = mod->next_func_idx++; - bh_imap_put(&mod->func_map, (u64) fd, func_idx); if (fd->flags & ONYX_AST_FLAG_EXPORTED) { onyx_token_null_toggle(*fd->token); + i32 func_idx = (i32) bh_imap_get(&mod->func_map, (u64) fd); + WasmExport wasm_export = { .kind = WASM_FOREIGN_FUNCTION, .idx = func_idx, @@ -597,7 +610,7 @@ static void process_function_definition(OnyxWasmModule* mod, OnyxAstNodeFuncDef* } // Generate code - process_function_body(mod, &wasm_func, fd); + compile_function_body(mod, &wasm_func, fd); } else { // NOTE: Empty bodies still need a block end instruction bh_arr_push(wasm_func.code, ((WasmInstruction){ WI_BLOCK_END, 0x00 })); @@ -609,12 +622,10 @@ static void process_function_definition(OnyxWasmModule* mod, OnyxAstNodeFuncDef* bh_imap_clear(&mod->local_map); } -static void process_foreign(OnyxWasmModule* module, OnyxAstNodeForeign* foreign) { +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); - bh_imap_put(&module->func_map, (u64) &foreign->import->as_funcdef, module->next_import_func_idx++); - WasmImport import = { .kind = WASM_FOREIGN_FUNCTION, .idx = type_idx, @@ -631,7 +642,7 @@ static void process_foreign(OnyxWasmModule* module, OnyxAstNodeForeign* foreign) } } -OnyxWasmModule onyx_wasm_generate_module(bh_allocator alloc, OnyxAstNode* program) { +OnyxWasmModule onyx_wasm_module_create(bh_allocator alloc) { OnyxWasmModule module = { .allocator = alloc, @@ -659,12 +670,34 @@ OnyxWasmModule onyx_wasm_generate_module(bh_allocator alloc, OnyxAstNode* progra bh_imap_init(&module.local_map, bh_heap_allocator()); bh_imap_init(&module.func_map, bh_heap_allocator()); - // NOTE: Count number of import functions + return module; +} + +void onyx_wasm_module_compile(OnyxWasmModule* module, OnyxAstNode* program) { OnyxAstNode* walker = program; while (walker) { if (walker->kind == ONYX_AST_NODE_KIND_FOREIGN && walker->as_foreign.import->kind == ONYX_AST_NODE_KIND_FUNCDEF) { - module.next_func_idx++; + module->next_func_idx++; + } + + walker = walker->next; + } + + walker = program; + 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_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); + } } walker = walker->next; @@ -674,18 +707,16 @@ OnyxWasmModule onyx_wasm_generate_module(bh_allocator alloc, OnyxAstNode* progra while (walker) { switch (walker->kind) { case ONYX_AST_NODE_KIND_FUNCDEF: - process_function_definition(&module, &walker->as_funcdef); + compile_function_definition(module, &walker->as_funcdef); break; case ONYX_AST_NODE_KIND_FOREIGN: - process_foreign(&module, &walker->as_foreign); + compile_foreign(module, &walker->as_foreign); break; default: break; } walker = walker->next; } - - return module; } void onyx_wasm_module_free(OnyxWasmModule* module) { -- 2.25.1