From: Brendan Hansen Date: Wed, 24 Jun 2020 02:10:40 +0000 (-0500) Subject: Fully compiling to WASM again X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=024294c2adf15f8224161f0353770344e6478057;p=onyx.git Fully compiling to WASM again --- 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 8c6c53a7..1c06a808 100755 Binary files a/onyx and b/onyx differ 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) {