Started working on an IR; decided it's not needed
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 16 Jul 2020 18:13:38 +0000 (13:13 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Thu, 16 Jul 2020 18:13:38 +0000 (13:13 -0500)
Leaving the code for it in the tree though

15 files changed:
docs/thoughts
include/onyxastnodes.h
include/onyxir.h [new file with mode: 0644]
include/onyxsempass.h
include/onyxwasm.h
onyx
progs/basic.onyx
progs/test.onyx
src/onyx.c
src/onyxchecker.c
src/onyxir.c [new file with mode: 0644]
src/onyxsempass.c
src/onyxsymres.c
src/onyxutils.c
src/onyxwasm.c

index b9402481a6078e69f1c5ddf9d6013ca3c071c5c0..188e314d586030aea5fbda2cb9bc02088506e159 100644 (file)
@@ -57,9 +57,6 @@ Treating top level declarations differently:
         global :: 5     - This would replace all instances of 'global' with the integer constant
                             5. This would not make a global in WASM.
 
-        global := 5     - This would work as expected but will make generating the WASM more difficult.
-                            This feature may wait to come back.
-
         global :: i32   - This would work as a type alias. 'global' would have the type node as it's 'node'
 
         print :: proc #foriegn "host" "print" (...) ---
@@ -102,3 +99,5 @@ Explicit overriden functions:
 
         min(2, 5);
         min(4.5, 10.4);
+
+
index ba6fe398d75dcbf11d6c455bb7cf4e7bee2a7010..081d20f1865d0845ebab7adc7fdc05bbc0aec264 100644 (file)
@@ -228,12 +228,13 @@ typedef enum OnyxIntrinsic {
 // same position as AstNodeCall
 struct AstIntrinsicCall { AstTyped base; AstArgument *arguments; OnyxIntrinsic intrinsic; };
 
-typedef struct OnyxProgram {
+// NOTE: Simple data structure for storing what comes out of the parser
+typedef struct ParserOutput {
     bh_arr(AstBinding *)  top_level_bindings;
     bh_arr(AstNode *)     nodes_to_process;
 
     bh_arr(AstFunction *) functions;
-} OnyxProgram;
+} ParserOutput;
 
 
 
diff --git a/include/onyxir.h b/include/onyxir.h
new file mode 100644 (file)
index 0000000..97e0a3c
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef ONYXIR_H
+#define ONYXIR_H
+
+#include "bh.h"
+#include "onyxastnodes.h"
+#include "onyxtypes.h"
+#include "onyxmsgs.h"
+
+typedef struct IrFunction {
+    AstFunction* ast_func;
+    Type* type;
+    bh_arr(AstLocal *) locals;
+    AstLocal* first_param;
+    AstNode* body;
+
+    // NOTE: A function can either be either be:
+    //      Normal
+    //      Intrinsic
+    //      Exported
+    //      Foreign
+    union {
+        // NOTE: Set if the function is exported
+        char* exported_name;
+
+        // NOTE: Set if the function is a foreign
+        struct {
+            char* foreign_module;
+            char* foreign_name;
+        };
+
+        // NOTE: Set if the function is intrinsic
+        OnyxIntrinsic intrinsic;
+    };
+
+    u32 is_exported  : 1;
+    u32 is_foreign   : 1;
+    u32 is_intrinsic : 1;
+
+} IrFunction;
+
+typedef struct IrContext {
+    // NOTE: Properties used after ir generation is done
+    bh_allocator allocator;
+
+    bh_arr(IrFunction *) functions;
+
+    // NOTE: Properties used while ir is generating
+    IrFunction* curr_function;
+
+    OnyxMessages* msgs;
+} IrContext;
+
+
+IrContext ir_context_create(bh_allocator allocator);
+void ir_context_free(IrContext* context);
+void ir_generate(IrContext* context, ParserOutput parse_output);
+
+#endif // #ifndef ONYXIR_H
index 138ef8e09580e8f7277776cc5efd593a8375b4a6..c2d1a52959e092c304b067d35fb93dbea9230019 100644 (file)
@@ -29,13 +29,13 @@ typedef struct OnyxSemPassState {
 } OnyxSemPassState;
 
 // NOTE: Resolving all symbols in the tree
-void onyx_resolve_symbols(OnyxSemPassState* state, OnyxProgram* program);
+void onyx_resolve_symbols(OnyxSemPassState* state, ParserOutput* program);
 
 // NOTE: Inferring and checking types in the tree
-void onyx_type_check(OnyxSemPassState* state, OnyxProgram* program);
+void onyx_type_check(OnyxSemPassState* state, ParserOutput* program);
 
 // NOTE: Full semantic pass
 OnyxSemPassState onyx_sempass_create(bh_allocator alloc, bh_allocator node_alloc, OnyxMessages* msgs);
-void onyx_sempass(OnyxSemPassState* state, OnyxProgram* program);
+void onyx_sempass(OnyxSemPassState* state, ParserOutput* program);
 
 #endif
index fe0e32c3873ecd8760b343531f29000ca500ec79..24b951c16906746e12698e92f6db9048d6dc8b09 100644 (file)
@@ -5,6 +5,7 @@
 
 #include "onyxastnodes.h"
 #include "onyxmsgs.h"
+#include "onyxir.h"
 
 typedef u8 WasmType;
 
@@ -301,14 +302,12 @@ typedef struct OnyxWasmModule {
 
     u16 next_type_idx;
     u16 next_func_idx;
-    u16 next_import_func_idx;
     u16 next_global_idx;
-    u16 next_import_global_idx;
     u16 export_count;
 } OnyxWasmModule;
 
 OnyxWasmModule onyx_wasm_module_create(bh_allocator alloc, OnyxMessages* msgs);
-void onyx_wasm_module_compile(OnyxWasmModule* module, OnyxProgram* program);
+void onyx_wasm_module_compile(OnyxWasmModule* module, ParserOutput* 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 9fb8a4b9ebbe69027e5cec4721d2b8fd8a5fc919..791a5a192ba0d7047a7baf0f5a01f8c9578418b2 100755 (executable)
Binary files a/onyx and b/onyx differ
index e7a0c5f00e11e20abe4ddbe69b17f54d249de954..fdba0aec73de5ad58cac029ae25bb7d8a6162711 100644 (file)
@@ -37,8 +37,7 @@ main :: proc #export {
     b := 1 + foo(2);
     print(b);
 
-    if b == 13
-        ---
+    if b == 13 {}
     else {
         print(1024);
     }
index 6214b2789b9f8a668b4e81ae7fbe801fdfed6cca..1522bf3b21432a74a8720f8a66dcac50a7f88933 100644 (file)
@@ -24,11 +24,11 @@ local_brute :: proc {
     c := 123.0;
 
     {
-        a := 5.0f;
-        b := 12.3;
+        d := 5.0f;
+        e := 12.3;
 
-        print_f32(a);
-        print_f64(b);
+        print_f32(d);
+        print_f64(e);
     }
 
     print_i32(a);
@@ -91,6 +91,8 @@ main2 :: proc #export {
 // }
 
 main :: proc #export {
+    local_brute();
+
     print_i32(clz_i32(16));
     print_f32(sqrt_f32(2.0f));
 
index b7c24e298fb726590ed79107296a439c60856ca1..93824ca0d0b5c43668241b00f1006eab402f2638 100644 (file)
@@ -60,7 +60,7 @@ typedef struct CompilerState {
     bh_arr(const char *) queued_files;
 
     OnyxMessages msgs;
-    OnyxProgram program;
+    ParserOutput parse_output;
     OnyxWasmModule wasm_mod;
 } CompilerState;
 
@@ -154,10 +154,10 @@ static CompilerProgress process_source_file(CompilerState* compiler_state, char*
     }
 
     bh_arr_each(AstBinding *, binding_node, results.bindings)
-        bh_arr_push(compiler_state->program.top_level_bindings, *binding_node);
+        bh_arr_push(compiler_state->parse_output.top_level_bindings, *binding_node);
 
     bh_arr_each(AstNode *, node, results.nodes_to_process)
-        bh_arr_push(compiler_state->program.nodes_to_process, *node);
+        bh_arr_push(compiler_state->parse_output.nodes_to_process, *node);
 
     if (onyx_message_has_errors(&compiler_state->msgs)) {
         return ONYX_COMPILER_PROGRESS_FAILED_PARSE;
@@ -169,8 +169,9 @@ static CompilerProgress process_source_file(CompilerState* compiler_state, char*
 static void compiler_state_init(CompilerState* compiler_state, OnyxCompileOptions* opts) {
     compiler_state->options = opts;
 
-    bh_arr_new(global_heap_allocator, compiler_state->program.top_level_bindings, 4);
-    bh_arr_new(global_heap_allocator, compiler_state->program.functions, 4);
+    bh_arr_new(global_heap_allocator, compiler_state->parse_output.top_level_bindings, 4);
+    bh_arr_new(global_heap_allocator, compiler_state->parse_output.nodes_to_process, 4);
+    bh_arr_new(global_heap_allocator, compiler_state->parse_output.functions, 4);
 
     bh_arena_init(&compiler_state->msg_arena, opts->allocator, 4096);
     compiler_state->msg_alloc = bh_arena_allocator(&compiler_state->msg_arena);
@@ -214,7 +215,7 @@ static i32 onyx_compile(CompilerState* compiler_state) {
         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->program);
+    onyx_sempass(&sp_state, &compiler_state->parse_output);
 
     if (onyx_message_has_errors(&compiler_state->msgs)) {
         return ONYX_COMPILER_PROGRESS_FAILED_SEMPASS;
@@ -226,7 +227,7 @@ static i32 onyx_compile(CompilerState* compiler_state) {
         bh_printf("[Generating WASM]\n");
 
     compiler_state->wasm_mod = onyx_wasm_module_create(compiler_state->options->allocator, &compiler_state->msgs);
-    onyx_wasm_module_compile(&compiler_state->wasm_mod, &compiler_state->program);
+    onyx_wasm_module_compile(&compiler_state->wasm_mod, &compiler_state->parse_output);
 
     if (onyx_message_has_errors(&compiler_state->msgs)) {
         return ONYX_COMPILER_PROGRESS_FAILED_BINARY_GEN;
@@ -265,7 +266,7 @@ int main(int argc, char *argv[]) {
 
     OnyxCompileOptions compile_opts = compile_opts_parse(global_heap_allocator, argc, argv);
     CompilerState compile_state = {
-        .program = {
+        .parse_output = {
             .top_level_bindings = NULL,
             .nodes_to_process   = NULL,
 
index 365a11c9033a00b440d2e01a6dd490328a69fc50..64e6836dd48fdb6fd3a66ebe820144645869e3c6 100644 (file)
@@ -518,30 +518,19 @@ static b32 check_function(OnyxSemPassState* state, AstFunction* func) {
 
 static b32 check_node(OnyxSemPassState* state, AstNode* node) {
     switch (node->kind) {
-        case Ast_Kind_Function: return check_function(state, (AstFunction *) node);
-        case Ast_Kind_Block: return check_block(state, (AstBlock *) node);
-        case Ast_Kind_Assignment: return check_assignment(state, (AstAssign *) node);
-        case Ast_Kind_Return: return check_return(state, (AstReturn *) node);
-        case Ast_Kind_If: return check_if(state, (AstIf *) node);
-        case Ast_Kind_While: return check_while(state, (AstWhile *) node);
-        case Ast_Kind_Call: return check_call(state, (AstCall *) node);
-        case Ast_Kind_Binary_Op: return check_binaryop(state, (AstBinaryOp *) node);
-        default: return check_expression(state, (AstTyped *) node);
+        case Ast_Kind_Function:     return check_function(state, (AstFunction *) node);
+        case Ast_Kind_Block:        return check_block(state, (AstBlock *) node);
+        case Ast_Kind_Assignment:   return check_assignment(state, (AstAssign *) node);
+        case Ast_Kind_Return:       return check_return(state, (AstReturn *) node);
+        case Ast_Kind_If:           return check_if(state, (AstIf *) node);
+        case Ast_Kind_While:        return check_while(state, (AstWhile *) node);
+        case Ast_Kind_Call:         return check_call(state, (AstCall *) node);
+        case Ast_Kind_Binary_Op:    return check_binaryop(state, (AstBinaryOp *) node);
+        default:                    return check_expression(state, (AstTyped *) node);
     }
 }
 
-void onyx_type_check(OnyxSemPassState* state, OnyxProgram* program) {
-
-    // bh_arr_each(AstForeign *, foreign, program->foreigns)
-    //     if ((*foreign)->import->kind == Ast_Kind_Function)
-    //         check_function(state, (AstFunction *) (*foreign)->import);
-
-    // bh_arr_each(AstGlobal *, global, program->globals)
-    //     check_global(state, *global);
-
-    // bh_arr_each(AstFunction *, function, program->functions)
-    //     check_function(state, *function);
-
+void onyx_type_check(OnyxSemPassState* state, ParserOutput* program) {
     bh_arr_each(AstNode *, node, program->nodes_to_process) {
         check_node(state, *node);
 
diff --git a/src/onyxir.c b/src/onyxir.c
new file mode 100644 (file)
index 0000000..1002249
--- /dev/null
@@ -0,0 +1,190 @@
+#include "onyxir.h"
+
+#define IR_FUNC(kind, ...) static void ir_ ## kind (IrContext* c, __VA_ARGS__)
+
+IR_FUNC(function,       AstFunction* ast_func);
+IR_FUNC(function_body,  AstFunction* fd);
+IR_FUNC(block,          AstBlock* block);
+IR_FUNC(statement,      AstNode* stmt);
+IR_FUNC(assign_lval,    AstTyped* lval);
+IR_FUNC(assignment,     AstAssign* assign);
+IR_FUNC(if,             AstIf* if_node);
+IR_FUNC(while,          AstWhile* while_node);
+IR_FUNC(binop,          AstBinaryOp* binop);
+IR_FUNC(unaryop,        AstUnaryOp* unop);
+IR_FUNC(call,           AstCall* call);
+IR_FUNC(intrinsic_call, AstIntrinsicCall* call);
+IR_FUNC(expression,     AstTyped* expr);
+IR_FUNC(cast,           AstUnaryOp* cast);
+IR_FUNC(return,         AstReturn* ret);
+
+static OnyxIntrinsic intrinsic_lookup(char* name) {
+    if (!strcmp("memory_size", name))       return ONYX_INTRINSIC_MEMORY_SIZE;
+    else if (!strcmp("memory_grow", name))  return ONYX_INTRINSIC_MEMORY_GROW;
+
+    else if (!strcmp("clz_i32", name))      return ONYX_INTRINSIC_I32_CLZ;
+    else if (!strcmp("ctz_i32", name))      return ONYX_INTRINSIC_I32_CTZ;
+    else if (!strcmp("popcnt_i32", name))   return ONYX_INTRINSIC_I32_POPCNT;
+    else if (!strcmp("and_i32", name))      return ONYX_INTRINSIC_I32_AND;
+    else if (!strcmp("or_i32", name))       return ONYX_INTRINSIC_I32_OR;
+    else if (!strcmp("xor_i32", name))      return ONYX_INTRINSIC_I32_XOR;
+    else if (!strcmp("shl_i32", name))      return ONYX_INTRINSIC_I32_SHL;
+    else if (!strcmp("slr_i32", name))      return ONYX_INTRINSIC_I32_SLR;
+    else if (!strcmp("sar_i32", name))      return ONYX_INTRINSIC_I32_SAR;
+    else if (!strcmp("rotl_i32", name))     return ONYX_INTRINSIC_I32_ROTL;
+    else if (!strcmp("rotr_i32", name))     return ONYX_INTRINSIC_I32_ROTR;
+
+    else if (!strcmp("clz_i64", name))      return ONYX_INTRINSIC_I64_CLZ;
+    else if (!strcmp("ctz_i64", name))      return ONYX_INTRINSIC_I64_CTZ;
+    else if (!strcmp("popcnt_i64", name))   return ONYX_INTRINSIC_I64_POPCNT;
+    else if (!strcmp("and_i64", name))      return ONYX_INTRINSIC_I64_AND;
+    else if (!strcmp("or_i64", name))       return ONYX_INTRINSIC_I64_OR;
+    else if (!strcmp("xor_i64", name))      return ONYX_INTRINSIC_I64_XOR;
+    else if (!strcmp("shl_i64", name))      return ONYX_INTRINSIC_I64_SHL;
+    else if (!strcmp("slr_i64", name))      return ONYX_INTRINSIC_I64_SLR;
+    else if (!strcmp("sar_i64", name))      return ONYX_INTRINSIC_I64_SAR;
+    else if (!strcmp("rotl_i64", name))     return ONYX_INTRINSIC_I64_ROTL;
+    else if (!strcmp("rotr_i64", name))     return ONYX_INTRINSIC_I64_ROTR;
+
+    else if (!strcmp("abs_f32", name))      return ONYX_INTRINSIC_F32_ABS;
+    else if (!strcmp("ceil_f32", name))     return ONYX_INTRINSIC_F32_CEIL;
+    else if (!strcmp("floor_f32", name))    return ONYX_INTRINSIC_F32_FLOOR;
+    else if (!strcmp("trunc_f32", name))    return ONYX_INTRINSIC_F32_TRUNC;
+    else if (!strcmp("nearest_f32", name))  return ONYX_INTRINSIC_F32_NEAREST;
+    else if (!strcmp("sqrt_f32", name))     return ONYX_INTRINSIC_F32_SQRT;
+    else if (!strcmp("min_f32", name))      return ONYX_INTRINSIC_F32_MIN;
+    else if (!strcmp("max_f32", name))      return ONYX_INTRINSIC_F32_MAX;
+    else if (!strcmp("copysign_f32", name)) return ONYX_INTRINSIC_F32_COPYSIGN;
+
+    else if (!strcmp("abs_f64", name))      return ONYX_INTRINSIC_F64_ABS;
+    else if (!strcmp("ceil_f64", name))     return ONYX_INTRINSIC_F64_CEIL;
+    else if (!strcmp("floor_f64", name))    return ONYX_INTRINSIC_F64_FLOOR;
+    else if (!strcmp("trunc_f64", name))    return ONYX_INTRINSIC_F64_TRUNC;
+    else if (!strcmp("nearest_f64", name))  return ONYX_INTRINSIC_F64_NEAREST;
+    else if (!strcmp("sqrt_f64", name))     return ONYX_INTRINSIC_F64_SQRT;
+    else if (!strcmp("min_f64", name))      return ONYX_INTRINSIC_F64_MIN;
+    else if (!strcmp("max_f64", name))      return ONYX_INTRINSIC_F64_MAX;
+    else if (!strcmp("copysign_f64", name)) return ONYX_INTRINSIC_F64_COPYSIGN;
+    else                                    return ONYX_INTRINSIC_UNDEFINED;
+}
+
+static void ir_add_local(IrContext* c, AstLocal* local) {
+    bh_arr_push(c->curr_function->locals, local);
+}
+
+IR_FUNC(ir_function, AstFunction* ast_func) {
+    IrFunction* func = bh_alloc_item(c->allocator, IrFunction);
+
+    func->ast_func = ast_func;
+    func->body = ast_func->body->body;
+    func->first_param = ast_func->params;
+
+    // NOTE: This is actually the return type (for now)
+    func->type = ast_func->base.type;
+
+    func->locals = NULL;
+    bh_arr_new(c->allocator, func->locals, 4);
+
+    func->is_exported  = (ast_func->base.flags & Ast_Flag_Exported) != 0;
+    func->is_foreign   = (ast_func->base.flags & Ast_Flag_Foreign) != 0;
+    func->is_intrinsic = (ast_func->base.flags & Ast_Flag_Intrinsic) != 0;
+
+    if (func->is_intrinsic) {
+        onyx_token_null_toggle(ast_func->base.token);
+        func->intrinsic = intrinsic_lookup(ast_func->base.token->text);
+        onyx_token_null_toggle(ast_func->base.token);
+    }
+
+    else if (func->is_exported) {
+        onyx_token_null_toggle(ast_func->base.token);
+        func->exported_name = bh_aprintf(c->allocator, "%s", ast_func->base.token->text);
+        onyx_token_null_toggle(ast_func->base.token);
+    }
+
+    else if (func->is_foreign) {
+        onyx_token_null_toggle(ast_func->foreign_module);
+        func->foreign_module = bh_aprintf(c->allocator, "%s", ast_func->foreign_module);
+        onyx_token_null_toggle(ast_func->foreign_module);
+
+        onyx_token_null_toggle(ast_func->foreign_name);
+        func->foreign_module = bh_aprintf(c->allocator, "%s", ast_func->foreign_name);
+        onyx_token_null_toggle(ast_func->foreign_name);
+    }
+
+    if (func->body != NULL) {
+        c->curr_function = func;
+    }
+}
+
+IR_FUNC(function_body, AstFunction* fd) {
+    if (fd->body == NULL) return;
+    ir_block(c, fd->body);
+}
+
+IR_FUNC(block, AstBlock* block) {
+    forll (AstLocal, local, block->locals->last_local, prev_local) {
+        ir_add_local(c, local);
+    }
+
+    forll (AstNode, stmt, block->body, next) {
+        ir_statement(c, stmt);
+    }
+}
+
+IR_FUNC(statement, AstNode* stmt) {
+    switch (stmt->kind) {
+        case Ast_Kind_Return:       return ir_return(c, (AstReturn *) stmt);
+        case Ast_Kind_Assignment:   return ir_assignment(c, (AstAssign *) stmt);
+        case Ast_Kind_If:           return ir_if(c, (AstIf *) stmt);
+        case Ast_Kind_While:        return ir_while(c, (AstWhile *) stmt);
+        case Ast_Kind_Block:        return ir_block(c, (AstBlock *) stmt);
+
+        default: break;
+    }
+}
+
+IR_FUNC(if, AstIf* if_node) {
+    if (if_node->true_block.as_if->base.kind == Ast_Kind_Block) {
+        ir_block(c, if_node->true_block.as_block);
+    }
+
+    if (if_node->false_block.as_if->base.kind == Ast_Kind_Block) {
+        ir_block(c, if_node->false_block.as_block);
+    }
+}
+
+IR_FUNC(while, AstWhile* while_node) {
+    ir_block(c, while_node->body);
+}
+
+// NOTE: Currently, these functions don't have anything to
+// do so they are empty and not called. When I have a reason
+// to use them, I will populate their bodies
+IR_FUNC(assign_lval,    AstTyped* lval)          {}
+IR_FUNC(assignment,     AstAssign* assign)       {}
+IR_FUNC(binop,          AstBinaryOp* binop)      {}
+IR_FUNC(unaryop,        AstUnaryOp* unop)        {}
+IR_FUNC(expression,     AstTyped* expr)          {}
+IR_FUNC(cast,           AstUnaryOp* cast)        {}
+IR_FUNC(return,         AstReturn* ret)          {}
+
+IrContext ir_context_create(bh_allocator allocator) {
+    IrContext context = {
+        .allocator = allocator,
+        .functions = NULL,
+
+        .curr_function = NULL,
+    };
+
+    bh_arr_new(allocator, context.functions, 4);
+
+    return context;
+}
+
+void ir_context_free(IrContext* context) {
+    bh_arr_free(context.functions);
+}
+
+void ir_generate(IrContext* context, ParserOutput parse_output) {
+
+}
index 9c8d225c30ff5031577651a4bbd40fd27f727913..68ea2e2d3bb517cd8b6a2a67c8c90845d039ffd1 100644 (file)
@@ -23,68 +23,70 @@ 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(OnyxProgram* program) {
-//     bh_arr(AstBlock*) traversal_queue = NULL;
-//     bh_arr_new(global_scratch_allocator, traversal_queue, 4);
-//     bh_arr_set_length(traversal_queue, 0);
-//
-//     bh_arr_each(AstFunction *, func, program->functions) {
-//         AstLocalGroup* top_locals = (*func)->body->locals;
-//
-//         bh_arr_push(traversal_queue, (*func)->body);
-//         while (!bh_arr_is_empty(traversal_queue)) {
-//             AstBlock* block = traversal_queue[0];
-//
-//             if (block->base.kind == Ast_Kind_If) {
-//                 AstIf* if_node = (AstIf *) block;
-//                 if (if_node->true_block.as_block != NULL)
-//                     bh_arr_push(traversal_queue, if_node->true_block.as_block);
-//
-//                 if (if_node->false_block.as_block != NULL)
-//                     bh_arr_push(traversal_queue, if_node->false_block.as_block);
-//
-//             } else {
-//
-//                 if (block->locals != top_locals && block->locals->last_local != NULL) {
-//                     AstLocal* last_local = block->locals->last_local;
-//                     while (last_local && last_local->prev_local != NULL) last_local = last_local->prev_local;
-//
-//                     last_local->prev_local = top_locals->last_local;
-//                     top_locals->last_local = block->locals->last_local;
-//                     block->locals->last_local = NULL;
-//                 }
-//
-//                 AstNode* walker = block->body;
-//                 while (walker) {
-//                     if (walker->kind == Ast_Kind_Block) {
-//                         bh_arr_push(traversal_queue, (AstBlock *) walker);
-//
-//                     } else if (walker->kind == Ast_Kind_While) {
-//                         bh_arr_push(traversal_queue, ((AstWhile *) walker)->body);
-//
-//                     } else if (walker->kind == Ast_Kind_If) {
-//                         if (((AstIf *) walker)->true_block.as_block != NULL)
-//                             bh_arr_push(traversal_queue, ((AstIf *) walker)->true_block.as_block);
-//
-//                         if (((AstIf *) walker)->false_block.as_block != NULL)
-//                             bh_arr_push(traversal_queue, ((AstIf *) walker)->false_block.as_block);
-//                     }
-//
-//                     walker = walker->next;
-//                 }
-//             }
-//
-//             bh_arr_deleten(traversal_queue, 0, 1);
-//         }
-//     }
-// }
-
-void onyx_sempass(OnyxSemPassState* state, OnyxProgram* program) {
+static void collapse_scopes(ParserOutput* program) {
+    bh_arr(AstBlock*) traversal_queue = NULL;
+    bh_arr_new(global_scratch_allocator, traversal_queue, 4);
+    bh_arr_set_length(traversal_queue, 0);
+
+    bh_arr_each(AstFunction *, func, program->functions) {
+        if ((*func)->base.flags & Ast_Flag_Intrinsic) continue;
+
+        AstLocalGroup* top_locals = (*func)->body->locals;
+
+        bh_arr_push(traversal_queue, (*func)->body);
+        while (!bh_arr_is_empty(traversal_queue)) {
+            AstBlock* block = traversal_queue[0];
+
+            if (block->base.kind == Ast_Kind_If) {
+                AstIf* if_node = (AstIf *) block;
+                if (if_node->true_block.as_block != NULL)
+                    bh_arr_push(traversal_queue, if_node->true_block.as_block);
+
+                if (if_node->false_block.as_block != NULL)
+                    bh_arr_push(traversal_queue, if_node->false_block.as_block);
+
+            } else {
+
+                if (block->locals != top_locals && block->locals->last_local != NULL) {
+                    AstLocal* last_local = block->locals->last_local;
+                    while (last_local && last_local->prev_local != NULL) last_local = last_local->prev_local;
+
+                    last_local->prev_local = top_locals->last_local;
+                    top_locals->last_local = block->locals->last_local;
+                    block->locals->last_local = NULL;
+                }
+
+                AstNode* walker = block->body;
+                while (walker) {
+                    if (walker->kind == Ast_Kind_Block) {
+                        bh_arr_push(traversal_queue, (AstBlock *) walker);
+
+                    } else if (walker->kind == Ast_Kind_While) {
+                        bh_arr_push(traversal_queue, ((AstWhile *) walker)->body);
+
+                    } else if (walker->kind == Ast_Kind_If) {
+                        if (((AstIf *) walker)->true_block.as_block != NULL)
+                            bh_arr_push(traversal_queue, ((AstIf *) walker)->true_block.as_block);
+
+                        if (((AstIf *) walker)->false_block.as_block != NULL)
+                            bh_arr_push(traversal_queue, ((AstIf *) walker)->false_block.as_block);
+                    }
+
+                    walker = walker->next;
+                }
+            }
+
+            bh_arr_deleten(traversal_queue, 0, 1);
+        }
+    }
+}
+
+void onyx_sempass(OnyxSemPassState* state, ParserOutput* program) {
     onyx_resolve_symbols(state, program);
     if (onyx_message_has_errors(state->msgs)) return;
 
     onyx_type_check(state, program);
     if (onyx_message_has_errors(state->msgs)) return;
 
-    // collapse_scopes(program);
+    collapse_scopes(program);
 }
index c363c3962700a491defe0674cd4c2f871d87c9f9..027741257358831e58c0f84c9a835d325d258a60 100644 (file)
@@ -314,7 +314,7 @@ static void symres_top_node(OnyxSemPassState* state, AstNode** node) {
     }
 }
 
-void onyx_resolve_symbols(OnyxSemPassState* state, OnyxProgram* program) {
+void onyx_resolve_symbols(OnyxSemPassState* state, ParserOutput* program) {
 
     // NOTE: Add types to global scope
     symbol_basic_type_introduce(state, &basic_type_void);
index 26a384f33e78fc99a7e571a1dac54e0987452df6..098813745acdda5f5f7d50d565dc4c7985c82e2c 100644 (file)
@@ -35,7 +35,6 @@ static const char* ast_node_names[] = {
     "PARAM",
     "ARGUMENT",
     "CALL",
-    "INTRINSIC_CALL",
     "ASSIGN",
     "RETURN",
 
index b67b091e50157ef5465922c3102f9582f5f25455..8dc425b4481acd6ddadc6c06ed71013d78651627 100644 (file)
@@ -209,7 +209,7 @@ static WasmType onyx_type_to_wasm_type(Type* type) {
         }
         if (basic->flags & Basic_Flag_Float) {
             if (basic->size <= 4) return WASM_TYPE_FLOAT32;
-            if (basic->size == 8) return WASM_TYPE_FLOAT64;;
+            if (basic->size == 8) return WASM_TYPE_FLOAT64;
         }
         if (basic->size == 0) return WASM_TYPE_VOID;
     }
@@ -296,13 +296,13 @@ COMPILE_FUNC(statement, AstNode* stmt) {
     bh_arr(WasmInstruction) code = *pcode;
 
     switch (stmt->kind) {
-        case Ast_Kind_Return: compile_return(mod, &code, (AstReturn *) stmt); break;
+        case Ast_Kind_Return:     compile_return(mod, &code, (AstReturn *) stmt); break;
         case Ast_Kind_Assignment: compile_assignment(mod, &code, (AstAssign *) stmt); break;
-        case Ast_Kind_If: compile_if(mod, &code, (AstIf *) stmt); break;
-        case Ast_Kind_While: compile_while(mod, &code, (AstWhile *) stmt); break;
-        case Ast_Kind_Break: compile_structured_jump(mod, &code, 0); break;
-        case Ast_Kind_Continue: compile_structured_jump(mod, &code, 1); break;
-        case Ast_Kind_Block: compile_block(mod, &code, (AstBlock *) stmt); break;
+        case Ast_Kind_If:         compile_if(mod, &code, (AstIf *) stmt); break;
+        case Ast_Kind_While:      compile_while(mod, &code, (AstWhile *) stmt); break;
+        case Ast_Kind_Break:      compile_structured_jump(mod, &code, 0); break;
+        case Ast_Kind_Continue:   compile_structured_jump(mod, &code, 1); break;
+        case Ast_Kind_Block:      compile_block(mod, &code, (AstBlock *) stmt); break;
 
         case Ast_Kind_Call:
         case Ast_Kind_Intrinsic_Call:
@@ -453,8 +453,8 @@ COMPILE_FUNC(binop, AstBinaryOp* binop) {
 
     WasmType operator_type = onyx_type_to_wasm_type(binop->left->type);
     i32 optype = 0;
-    if (operator_type == WASM_TYPE_INT32) optype = 0;
-    else if (operator_type == WASM_TYPE_INT64) optype = 1;
+    if      (operator_type == WASM_TYPE_INT32)   optype = 0;
+    else if (operator_type == WASM_TYPE_INT64)   optype = 1;
     else if (operator_type == WASM_TYPE_FLOAT32) optype = 2;
     else if (operator_type == WASM_TYPE_FLOAT64) optype = 3;
 
@@ -961,8 +961,6 @@ OnyxWasmModule onyx_wasm_module_create(bh_allocator alloc, OnyxMessages* msgs) {
         .export_count = 0,
 
         .imports = NULL,
-        .next_import_func_idx = 0,
-        .next_import_global_idx = 0,
 
         .globals = NULL,
         .next_global_idx = 0,
@@ -989,7 +987,7 @@ OnyxWasmModule onyx_wasm_module_create(bh_allocator alloc, OnyxMessages* msgs) {
     return module;
 }
 
-void onyx_wasm_module_compile(OnyxWasmModule* module, OnyxProgram* program) {
+void onyx_wasm_module_compile(OnyxWasmModule* module, ParserOutput* program) {
 
     // NOTE: First, introduce all indicies for globals and functions
     // bh_arr_each(AstForeign *, foreign, program->foreigns) {
@@ -1015,7 +1013,7 @@ void onyx_wasm_module_compile(OnyxWasmModule* module, OnyxProgram* program) {
 
     bh_arr_each(AstFunction *, function, program->functions) {
         if ((*function)->base.flags & Ast_Flag_Foreign) continue;
-        
+
         if (((*function)->base.flags & Ast_Flag_Intrinsic) == 0)
             bh_imap_put(&module->func_map, (u64) *function, module->next_func_idx++);
     }