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
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,
OnyxAstNodeBlock *body;
};
-struct OnyxAstNodeFuncDef {
+struct OnyxAstNodeFunction {
OnyxAstNodeKind kind;
u32 flags;
OnyxToken *token; // This will point to the symbol token to identify it
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
};
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
};
OnyxAstNodeBlock as_block;
- OnyxAstNodeFuncDef as_funcdef;
OnyxAstNodeParam as_param;
OnyxAstNodeLocal as_local;
OnyxAstNodeScope as_scope;
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
} 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
} 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);
}
export main :: proc {
+ print_bool(in_unit_circle(0.5f, 0.5f));
+
big_num := fib(factorial(4));
something :: other_value(0);
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;
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);
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;
// 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;
// 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;
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) {
"PROGRAM",
"USE",
- "FUNCDEF",
+ "FUNCTION",
"FOREIGN",
"BLOCK",
"SCOPE",
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) {
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;
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);
// 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);
}
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);
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);
}
}
}
-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);
}
#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);
}
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,
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,
}
}
-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,
}
}
-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);
}
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);
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 ");
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);
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);
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;
*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;
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 = {
}
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,
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) {