Refactored the AST node structure
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 3 Jul 2020 04:30:39 +0000 (23:30 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 3 Jul 2020 04:30:39 +0000 (23:30 -0500)
This involved rewriting a lot of the code that was there

13 files changed:
include/onyxlex.h
include/onyxparser.h
include/onyxsempass.h
include/onyxutils.h
onyx
src/onyx.c
src/onyxlex.c
src/onyxparser.c
src/onyxsempass.c
src/onyxsymres.c
src/onyxtypecheck.c
src/onyxutils.c
src/onyxwasm.c

index 559a203020f7917bb259a35acf3530d5ea5092a7..ed65258e5e79f2ea775a14e4d98ebd629e17114d 100644 (file)
@@ -3,7 +3,7 @@
 
 #include "bh.h"
 
-typedef enum OnyxTokenType {
+typedef enum TokenType {
     TOKEN_TYPE_UNKNOWN,
     TOKEN_TYPE_END_STREAM,
 
@@ -61,7 +61,7 @@ typedef enum OnyxTokenType {
     TOKEN_TYPE_LITERAL_BOOL_FALSE,
 
     TOKEN_TYPE_COUNT
-} OnyxTokenType;
+} TokenType;
 
 typedef struct OnyxFilePos {
     const char* filename;
@@ -69,7 +69,7 @@ typedef struct OnyxFilePos {
 } OnyxFilePos;
 
 typedef struct OnyxToken {
-    OnyxTokenType type;
+    TokenType type;
     i32 length;
     char* token;
     OnyxFilePos pos;
@@ -86,8 +86,8 @@ typedef struct OnyxTokenizer {
     bh_arr(OnyxToken) tokens;
 } OnyxTokenizer;
 
-const char* onyx_get_token_type_name(OnyxTokenType tkn_type);
-void onyx_token_null_toggle(OnyxToken tkn);
+const char* onyx_get_token_type_name(TokenType tkn_type);
+void onyx_token_null_toggle(OnyxToken* tkn);
 OnyxToken* onyx_get_token(OnyxTokenizer* tokenizer);
 OnyxTokenizer onyx_tokenizer_create(bh_allocator allocator, bh_file_contents *fc);
 void onyx_tokenizer_free(OnyxTokenizer* tokenizer);
index 1adf82870c7dcedaeb537a54dd73e06719f9d7ca..095797a459f6f7705534437783cdb5a6c4f90e25 100644 (file)
@@ -6,21 +6,24 @@
 #include "onyxlex.h"
 #include "onyxmsgs.h"
 
-typedef union OnyxAstNode OnyxAstNode;
-typedef struct OnyxAstNodeUnaryOp OnyxAstNodeUnaryOp;
-typedef struct OnyxAstNodeBinOp OnyxAstNodeBinOp;
-typedef struct OnyxAstNodeNumLit OnyxAstNodeNumLit;
-typedef struct OnyxAstNodeLocal OnyxAstNodeLocal;
-typedef struct OnyxAstNodeScope OnyxAstNodeScope;
-typedef struct OnyxAstNodeBlock OnyxAstNodeBlock;
-typedef struct OnyxAstNodeIf OnyxAstNodeIf;
-typedef struct OnyxAstNodeWhile OnyxAstNodeWhile;
-typedef struct OnyxAstNodeParam OnyxAstNodeParam;
-typedef struct OnyxAstNodeFunction OnyxAstNodeFunction;
-typedef struct OnyxAstNodeForeign OnyxAstNodeForeign;
-typedef struct OnyxAstNodeGlobal OnyxAstNodeGlobal;
-typedef struct OnyxAstNodeCall OnyxAstNodeCall;
-typedef struct OnyxAstNodeUse OnyxAstNodeUse;
+typedef struct AstNode AstNode;
+typedef struct AstNodeTyped AstNodeTyped;
+typedef struct AstNodeUnaryOp AstNodeUnaryOp;
+typedef struct AstNodeBinOp AstNodeBinOp;
+typedef struct AstNodeAssign AstNodeAssign;
+typedef struct AstNodeNumLit AstNodeNumLit;
+typedef struct AstNodeLocal AstNodeLocal;
+typedef struct AstNodeScope AstNodeScope;
+typedef struct AstNodeReturn AstNodeReturn;
+typedef struct AstNodeBlock AstNodeBlock;
+typedef struct AstNodeIf AstNodeIf;
+typedef struct AstNodeWhile AstNodeWhile;
+typedef struct AstNodeFunction AstNodeFunction;
+typedef struct AstNodeForeign AstNodeForeign;
+typedef struct AstNodeGlobal AstNodeGlobal;
+typedef struct AstNodeCall AstNodeCall;
+typedef struct AstNodeArgument AstNodeArgument;
+typedef struct AstNodeUse AstNodeUse;
 
 typedef struct OnyxParser {
     OnyxTokenizer *tokenizer; // NOTE: not used since all tokens are lexed before parsing starts
@@ -29,62 +32,62 @@ typedef struct OnyxParser {
 
     // NOTE: Identifiers currently is only used to resolve type names
     // at parse time, since these are the only symbols we know.
-    bh_table(OnyxAstNode *) identifiers;
+    bh_table(AstNode *) identifiers;
     OnyxMessages *msgs;
 
     bh_allocator allocator;
 } OnyxParser;
 
-typedef enum OnyxAstNodeKind {
-    ONYX_AST_NODE_KIND_ERROR,
-    ONYX_AST_NODE_KIND_PROGRAM,
-    ONYX_AST_NODE_KIND_USE,
-
-    ONYX_AST_NODE_KIND_FUNCTION,
-    ONYX_AST_NODE_KIND_FOREIGN,
-    ONYX_AST_NODE_KIND_BLOCK,
-    ONYX_AST_NODE_KIND_SCOPE,
-    ONYX_AST_NODE_KIND_LOCAL,
-    ONYX_AST_NODE_KIND_GLOBAL,
-    ONYX_AST_NODE_KIND_SYMBOL,
-
-    ONYX_AST_NODE_KIND_UNARY_OP,
-    ONYX_AST_NODE_KIND_BIN_OP,
-
-    ONYX_AST_NODE_KIND_TYPE,
-    ONYX_AST_NODE_KIND_LITERAL,
-    ONYX_AST_NODE_KIND_PARAM,
-    ONYX_AST_NODE_KIND_ARGUMENT,
-    ONYX_AST_NODE_KIND_CALL,
-    ONYX_AST_NODE_KIND_ASSIGNMENT,
-    ONYX_AST_NODE_KIND_RETURN,
-
-    ONYX_AST_NODE_KIND_IF,
-    ONYX_AST_NODE_KIND_WHILE,
-    ONYX_AST_NODE_KIND_BREAK,
-    ONYX_AST_NODE_KIND_CONTINUE,
-
-    ONYX_AST_NODE_KIND_COUNT
-} OnyxAstNodeKind;
-
-typedef enum OnyxTypeInfoKind {
-    ONYX_TYPE_INFO_KIND_UNKNOWN,
-    ONYX_TYPE_INFO_KIND_VOID,
-    ONYX_TYPE_INFO_KIND_BOOL,
-
-    ONYX_TYPE_INFO_KIND_UINT32,
-    ONYX_TYPE_INFO_KIND_UINT64,
-
-    ONYX_TYPE_INFO_KIND_INT32,
-    ONYX_TYPE_INFO_KIND_INT64,
-
-    ONYX_TYPE_INFO_KIND_FLOAT32,
-    ONYX_TYPE_INFO_KIND_FLOAT64,
-    ONYX_TYPE_INFO_KIND_SOFT_FLOAT, // 64-bits of data but could be treated as 32-bit
-} OnyxTypeInfoKind;
-
-typedef struct OnyxTypeInfo {
-    OnyxTypeInfoKind kind;
+typedef enum AstNodeKind {
+    AST_NODE_KIND_ERROR,
+    AST_NODE_KIND_PROGRAM,
+    AST_NODE_KIND_USE,
+
+    AST_NODE_KIND_FUNCTION,
+    AST_NODE_KIND_FOREIGN,
+    AST_NODE_KIND_BLOCK,
+    AST_NODE_KIND_SCOPE,
+    AST_NODE_KIND_LOCAL,
+    AST_NODE_KIND_GLOBAL,
+    AST_NODE_KIND_SYMBOL,
+
+    AST_NODE_KIND_UNARY_OP,
+    AST_NODE_KIND_BIN_OP,
+
+    AST_NODE_KIND_TYPE,
+    AST_NODE_KIND_LITERAL,
+    AST_NODE_KIND_PARAM,
+    AST_NODE_KIND_ARGUMENT,
+    AST_NODE_KIND_CALL,
+    AST_NODE_KIND_ASSIGNMENT,
+    AST_NODE_KIND_RETURN,
+
+    AST_NODE_KIND_IF,
+    AST_NODE_KIND_WHILE,
+    AST_NODE_KIND_BREAK,
+    AST_NODE_KIND_CONTINUE,
+
+    AST_NODE_KIND_COUNT
+} AstNodeKind;
+
+typedef enum TypeInfoKind {
+    TYPE_INFO_KIND_UNKNOWN,
+    TYPE_INFO_KIND_VOID,
+    TYPE_INFO_KIND_BOOL,
+
+    TYPE_INFO_KIND_UINT32,
+    TYPE_INFO_KIND_UINT64,
+
+    TYPE_INFO_KIND_INT32,
+    TYPE_INFO_KIND_INT64,
+
+    TYPE_INFO_KIND_FLOAT32,
+    TYPE_INFO_KIND_FLOAT64,
+    TYPE_INFO_KIND_SOFT_FLOAT, // 64-bits of data but could be treated as 32-bit
+} TypeInfoKind;
+
+typedef struct TypeInfo {
+    TypeInfoKind kind;
     u32 size; // in bytes
     const char* name;
     u32 is_int : 1;
@@ -92,9 +95,9 @@ typedef struct OnyxTypeInfo {
     u32 is_float : 1;
     u32 is_bool : 1;
     u32 is_known : 1;
-} OnyxTypeInfo;
+} TypeInfo;
 
-extern OnyxTypeInfo builtin_types[];
+extern TypeInfo builtin_types[];
 
 // NOTE: Some of these flags will overlap since there are
 // only 32-bits of flags to play with
@@ -127,196 +130,147 @@ typedef enum OnyxBinaryOp {
     ONYX_BINARY_OP_GREATER_EQUAL = 10,
 } OnyxBinaryOp;
 
-struct OnyxAstNodeBinOp {
-    OnyxAstNodeKind kind;
+// NOTE: AstNode and AstNodeTyped need to be EXACTLY the same for
+// all arguments existing in AstNode. I do this to avoid a nested
+// "inheiritance" where you would have to say node.base.base.next
+// for example
+struct AstNode {
+    AstNodeKind kind;
     u32 flags;
     OnyxToken *token;
-    OnyxTypeInfo *type;
-    OnyxBinaryOp operation;
-    OnyxAstNode *next;
-    OnyxAstNode *left;
-    OnyxAstNode *right;
+    AstNode *next;
 };
 
-struct OnyxAstNodeUnaryOp {
-    OnyxAstNodeKind kind;
+struct AstNodeTyped {
+    AstNodeKind kind;
     u32 flags;
     OnyxToken *token;
-    OnyxTypeInfo *type;
+    AstNode *next;
+    TypeInfo *type;
+};
+
+struct AstNodeBinOp {
+    AstNodeTyped base;
+
+    OnyxBinaryOp operation;
+
+    AstNodeTyped *left, *right;
+};
+
+struct AstNodeUnaryOp {
+    AstNodeTyped base;
+
     OnyxUnaryOp operation;
-    OnyxAstNode *next;
-    OnyxAstNode *left;
+
+    AstNodeTyped *expr;
 };
 
-struct OnyxAstNodeNumLit {
-    OnyxAstNodeKind kind;
-    u32 flags;
-    OnyxToken *token;
-    OnyxTypeInfo *type;
-    u64 data;
-    OnyxAstNode *next;
+struct AstNodeAssign {
+    AstNode base;
+
+    AstNodeTyped* lval;
+    AstNodeTyped* expr;
+};
+
+struct AstNodeNumLit {
+    AstNodeTyped base;
+
     union { i32 i; i64 l; f32 f; f64 d; } value;
 };
 
-struct OnyxAstNodeLocal {
-    OnyxAstNodeKind kind;
-    u32 flags;
-    OnyxToken *token;
-    OnyxTypeInfo *type;
-    u64 data;                   // NOTE: Unused
-    OnyxAstNode *next;
-    OnyxAstNodeLocal *prev_local;
+struct AstNodeLocal {
+    AstNodeTyped base;
+
+    AstNodeLocal *prev_local;
 };
 
-struct OnyxAstNodeParam {
-    OnyxAstNodeKind kind;
-    u32 flags;
-    OnyxToken *token;            // NOTE: Symbol name i.e. 'a', 'b'
-    OnyxTypeInfo *type;
-    u64 data;                   // NOTE: UNUSED
-    OnyxAstNodeParam *next;
-    OnyxAstNodeLocal *prev_local;
+struct AstNodeReturn {
+    AstNode base;
+
+    AstNodeTyped* expr;
 };
 
-struct OnyxAstNodeScope {
-    OnyxAstNodeKind kind;
-    u32 flags;
-    OnyxToken *token;    // NOTE: UNUSED
-    OnyxTypeInfo *type; // NOTE: UNUSED
-    u64 data;           // NOTE: UNUSED
-    OnyxAstNodeScope *prev_scope;
-    OnyxAstNodeLocal *last_local;
+struct AstNodeScope {
+    AstNode base;
+
+    AstNodeScope *prev_scope;
+    AstNodeLocal *last_local;
 };
 
-struct OnyxAstNodeBlock {
-    OnyxAstNodeKind kind;
-    u32 flags;
-    OnyxToken *token;
-    OnyxTypeInfo *return_type;
-    u64 data;                       // NOTE: UNUSED
-    OnyxAstNode *next;
-    OnyxAstNode *body;
-    OnyxAstNodeScope *scope;
+struct AstNodeBlock {
+    AstNode base;
+
+    AstNode *body;
+    AstNodeScope *scope;
 };
 
-struct OnyxAstNodeIf {
-    OnyxAstNodeKind kind;
-    u32 flags;
-    OnyxToken *token;    // NOTE: UNUSED
-    u64 data;            // NOTE: UNUSED
-    OnyxAstNode *false_block;
-    OnyxAstNode *next;
-    OnyxAstNode *cond;
-    OnyxAstNode *true_block;
+struct AstNodeIf {
+    AstNode base;
+
+    AstNodeTyped *cond;
+    AstNode *true_block;
+    AstNode *false_block;
 };
 
-struct OnyxAstNodeWhile {
-    OnyxAstNodeKind kind;
-    u32 flags;
-    OnyxToken *token;   // NOTE: UNUSED
-    OnyxTypeInfo *type;
-    u64 data;
-    OnyxAstNode *next;
-    OnyxAstNode *cond;
-    OnyxAstNodeBlock *body;
+struct AstNodeWhile {
+    AstNode base;
+
+    AstNodeTyped *cond;
+    AstNodeBlock *body;
 };
 
-struct OnyxAstNodeFunction {
-    OnyxAstNodeKind kind;
-    u32 flags;
-    OnyxToken *token; // This will point to the symbol token to identify it
-    OnyxTypeInfo *return_type;
-    u64 data;
-    OnyxAstNode *next;
-    OnyxAstNodeBlock *body;
-    OnyxAstNodeParam *params;
+struct AstNodeFunction {
+    AstNodeTyped base;
+
+    AstNodeBlock *body;
+    AstNodeLocal *params;
 };
 
-struct OnyxAstNodeForeign {
-    OnyxAstNodeKind kind;
-    u32 flags;
-    OnyxToken *mod_token;
-    OnyxTypeInfo *type;
-    u64 data;
-    OnyxAstNode *next;
-    OnyxToken *name_token;
-    OnyxAstNode *import;
+struct AstNodeForeign {
+    AstNode base;
+
+    OnyxToken *mod_token, *name_token;
+    AstNode *import;
 };
 
-struct OnyxAstNodeGlobal {
-    OnyxAstNodeKind kind;
-    u32 flags;
-    OnyxToken *token;
-    OnyxTypeInfo *type;
-    u64 data;
-    OnyxAstNode* next;
-    OnyxAstNode* initial_value;
+struct AstNodeGlobal {
+    AstNodeTyped base;
+
+    AstNodeTyped *initial_value;
 };
 
-struct OnyxAstNodeCall {
-    OnyxAstNodeKind kind;
-    u32 flags;
-    OnyxToken *token;
-    OnyxTypeInfo *type;         // NOTE: The type that the function returns
-    u64 data;
-    OnyxAstNode *next;
-    OnyxAstNode *callee;        // NOTE: Function definition node
-    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
+struct AstNodeCall {
+    AstNodeTyped base;
+
+    AstNode *callee;                // NOTE: Function definition node
+    AstNodeArgument *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
 };
 
-struct OnyxAstNodeUse {
-    OnyxAstNodeKind kind;
-    u32 flags;
-    OnyxToken *token;
-    OnyxTypeInfo *type;
-    u64 data;
-    OnyxAstNode *next;
-    OnyxToken *filename;
+struct AstNodeArgument {
+    AstNodeTyped base;
+
+    AstNodeTyped *value;
 };
 
-union OnyxAstNode {
-
-    // Generic node structure for capturing all binary ops and statements
-    struct {
-        OnyxAstNodeKind kind;
-        u32 flags;
-        OnyxToken *token;
-        OnyxTypeInfo *type;
-        u64 data;
-        OnyxAstNode *next;
-        OnyxAstNode *left;
-        OnyxAstNode *right;
-    };
-
-    OnyxAstNodeBlock as_block;
-    OnyxAstNodeParam as_param;
-    OnyxAstNodeLocal as_local;
-    OnyxAstNodeScope as_scope;
-    OnyxAstNodeCall as_call;
-    OnyxAstNodeNumLit as_numlit;
-    OnyxAstNodeBinOp as_binop;
-    OnyxAstNodeUnaryOp as_unaryop;
-    OnyxAstNodeIf as_if;
-    OnyxAstNodeWhile as_while;
-    OnyxAstNodeUse as_use;
-    OnyxAstNodeFunction as_function;
-    OnyxAstNodeGlobal as_global;
-    OnyxAstNodeForeign as_foreign;
+struct AstNodeUse {
+    AstNode base;
+
+    OnyxToken *filename;
 };
 
 typedef struct OnyxProgram {
-    bh_arr(OnyxAstNodeUse *) uses;
-    bh_arr(OnyxAstNodeGlobal *) globals;
-    bh_arr(OnyxAstNodeFunction *) functions;
-    bh_arr(OnyxAstNodeForeign *) foreigns;
+    bh_arr(AstNodeUse *) uses;
+    bh_arr(AstNodeGlobal *) globals;
+    bh_arr(AstNodeFunction *) functions;
+    bh_arr(AstNodeForeign *) foreigns;
 } OnyxProgram;
 
-const char* onyx_ast_node_kind_string(OnyxAstNodeKind kind);
-void* onyx_ast_node_new(bh_allocator alloc, OnyxAstNodeKind kind);
+const char* onyx_ast_node_kind_string(AstNodeKind kind);
+void* onyx_ast_node_new(bh_allocator alloc, i32 size, AstNodeKind kind);
 OnyxParser onyx_parser_create(bh_allocator alloc, OnyxTokenizer *tokenizer, OnyxMessages* msgs);
 void onyx_parser_free(OnyxParser* parser);
-OnyxAstNode* onyx_parse(OnyxParser *parser);
+AstNode* onyx_parse(OnyxParser *parser);
 
 #endif // #ifndef ONYXPARSER_H
index eec0272281e4a37db8e0762ad2eedf075188c4f2..2e4b1d22bb2f04261b51216bf206911636d04fd7 100644 (file)
@@ -8,7 +8,7 @@
 #include "onyxmsgs.h"
 
 typedef struct SemPassSymbol {
-    OnyxAstNode *node;
+    AstNode *node;
     struct SemPassSymbol *shadowed;
 } SemPassSymbol;
 
@@ -19,10 +19,10 @@ typedef struct OnyxSemPassState {
     OnyxMessages *msgs;
 
     // NOTE: Used in symbol resolution phase
-    OnyxAstNodeScope* curr_scope;
+    AstNodeScope* curr_scope;
 
     // NOTE: Used in type checking phase
-    OnyxTypeInfo* expected_return_type;
+    TypeInfo* expected_return_type;
 
     bh_table(SemPassSymbol *) symbols;
 } OnyxSemPassState;
index 07fa1e82b898a689ebc3e6e5a069b4e56f012f1a..fa325d8cea30dad28e74e03142430259811d50ea 100644 (file)
@@ -8,4 +8,4 @@ extern bh_allocator global_scratch_allocator;
 extern bh_managed_heap global_heap;
 extern bh_allocator global_heap_allocator;
 
-void onyx_ast_print(OnyxAstNode* program, i32 indent);
+void onyx_ast_print(AstNode* program, i32 indent);
diff --git a/onyx b/onyx
index 2f2f2d9b1e3ac8320f2eb21d76a722a2cce8bee4..ead39f24013624edd5a41908db9705c84703eb31 100755 (executable)
Binary files a/onyx and b/onyx differ
index 1239491d7ce15ddcdd009589e96300f5a8c3e5ea..4fbe8464cdca1a25b7dc91234e2e11cda1bfc864 100644 (file)
@@ -106,7 +106,7 @@ static void compile_opts_free(OnyxCompileOptions* opts) {
     bh_arr_free(opts->files);
 }
 
-static OnyxAstNode* parse_source_file(CompilerState* compiler_state, bh_file_contents* file_contents) {
+static AstNode* 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
     if (compiler_state->options->verbose_output)
         bh_printf("[Lexing]       %s\n", file_contents->filename);
@@ -142,33 +142,33 @@ static CompilerProgress process_source_file(CompilerState* compiler_state, char*
     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);
 
-    OnyxAstNode* root_node = parse_source_file(compiler_state, &fc);
+    AstNode* root_node = parse_source_file(compiler_state, &fc);
 
     if (compiler_state->options->print_ast) {
         onyx_ast_print(root_node, 0);
         bh_printf("\n");
     }
 
-    OnyxAstNode* walker = root_node;
+    AstNode* walker = root_node;
     while (walker) {
         switch (walker->kind) {
-            case ONYX_AST_NODE_KIND_USE:
-                bh_arr_push(compiler_state->program.uses, &walker->as_use);
+            case AST_NODE_KIND_USE:
+                bh_arr_push(compiler_state->program.uses, (AstNodeUse *) walker);
                 break;
 
-            case ONYX_AST_NODE_KIND_GLOBAL:
-                bh_arr_push(compiler_state->program.globals, &walker->as_global);
+            case AST_NODE_KIND_GLOBAL:
+                bh_arr_push(compiler_state->program.globals, (AstNodeGlobal *) walker);
                 break;
 
-            case ONYX_AST_NODE_KIND_FOREIGN:
-                bh_arr_push(compiler_state->program.foreigns, &walker->as_foreign);
+            case AST_NODE_KIND_FOREIGN:
+                bh_arr_push(compiler_state->program.foreigns, (AstNodeForeign *) walker);
                 break;
 
-            case ONYX_AST_NODE_KIND_FUNCTION:
-                bh_arr_push(compiler_state->program.functions, &walker->as_function);
+            case AST_NODE_KIND_FUNCTION:
+                bh_arr_push(compiler_state->program.functions, (AstNodeFunction *) walker);
                 break;
 
-            case ONYX_AST_NODE_KIND_PROGRAM:
+            case AST_NODE_KIND_PROGRAM:
                 // Dummy initial node
                 break;
 
@@ -180,7 +180,7 @@ static CompilerProgress process_source_file(CompilerState* compiler_state, char*
         walker = walker->next;
     }
 
-    bh_arr_each(OnyxAstNodeUse *, use_node, compiler_state->program.uses) {
+    bh_arr_each(AstNodeUse *, use_node, compiler_state->program.uses) {
         char* formatted_name = bh_aprintf(
                 global_heap_allocator,
                 "%b.onyx",
index 95c543a4d42d85ef3c4f9cffe6247066e1ef2e69..b16d9736995f3e9ffef4b1104ddccab8d08af79d 100644 (file)
@@ -1,7 +1,7 @@
 #include "bh.h"
 #include "onyxlex.h"
 
-static const char* onyx_token_type_names[] = {
+static const char* token_type_names[] = {
     "TOKEN_TYPE_UNKNOWN",
     "TOKEN_TYPE_END_STREAM",
 
@@ -76,7 +76,7 @@ static const char* onyx_token_type_names[] = {
 }
 #endif
 
-static b32 token_lit(OnyxTokenizer* tokenizer, OnyxToken* tk, char* lit, b32 is_word, OnyxTokenType type) {
+static b32 token_lit(OnyxTokenizer* tokenizer, OnyxToken* tk, char* lit, b32 is_word, TokenType type) {
     i64 len = chars_match(tokenizer->curr, lit);
     if (len > 0) {
         if (is_word && char_is_alphanum(*(tokenizer->curr + len)) || charset_contains("_$", *(tokenizer->curr + len)))
@@ -95,14 +95,14 @@ static b32 token_lit(OnyxTokenizer* tokenizer, OnyxToken* tk, char* lit, b32 is_
     return 0;
 }
 
-const char* onyx_get_token_type_name(OnyxTokenType tkn_type) {
-    return onyx_token_type_names[tkn_type];
+const char* onyx_get_token_type_name(TokenType tkn_type) {
+    return token_type_names[tkn_type];
 }
 
-void onyx_token_null_toggle(OnyxToken tkn) {
+void onyx_token_null_toggle(OnyxToken* tkn) {
     static char backup = 0;
-    char tmp = tkn.token[tkn.length];
-    tkn.token[tkn.length] = backup;
+    char tmp = tkn->token[tkn->length];
+    tkn->token[tkn->length] = backup;
     backup = tmp;
 }
 
index d3379eba08d2f3f79b28c678ba139861cdb814f2..3bc38e8d384aa973c12d31fd15c0eacddeadb10d 100644 (file)
@@ -3,6 +3,9 @@
 #include "onyxparser.h"
 #include "onyxutils.h"
 
+// NOTE: The one weird define you need to know before read the code below
+#define make_node(nclass, kind) onyx_ast_node_new(parser->allocator, sizeof(nclass), kind)
+
 static const char* ast_node_names[] = {
     "ERROR",
     "PROGRAM",
@@ -32,53 +35,53 @@ static const char* ast_node_names[] = {
     "BREAK",
     "CONTINUE",
 
-    "ONYX_AST_NODE_KIND_COUNT",
+    "AST_NODE_KIND_COUNT",
 };
 
-struct OnyxTypeInfo builtin_types[] = {
-    { ONYX_TYPE_INFO_KIND_UNKNOWN, 0, "unknown" },
-    { ONYX_TYPE_INFO_KIND_VOID, 0, "void", 0, 0, 0, 0, 1 },
+struct TypeInfo builtin_types[] = {
+    { TYPE_INFO_KIND_UNKNOWN, 0, "unknown" },
+    { TYPE_INFO_KIND_VOID, 0, "void", 0, 0, 0, 0, 1 },
 
-    { ONYX_TYPE_INFO_KIND_BOOL, 1, "bool", 0, 1, 0, 1, 1 },
+    { TYPE_INFO_KIND_BOOL, 1, "bool", 0, 1, 0, 1, 1 },
 
-    { ONYX_TYPE_INFO_KIND_UINT32, 4, "u32", 1, 1, 0, 0, 1 },
-    { ONYX_TYPE_INFO_KIND_UINT64, 8, "u64", 1, 1, 0, 0, 1 },
+    { TYPE_INFO_KIND_UINT32, 4, "u32", 1, 1, 0, 0, 1 },
+    { TYPE_INFO_KIND_UINT64, 8, "u64", 1, 1, 0, 0, 1 },
 
-    { ONYX_TYPE_INFO_KIND_INT32, 4, "i32", 1, 0, 0, 0, 1 },
-    { ONYX_TYPE_INFO_KIND_INT64, 8, "i64", 1, 0, 0, 0, 1 },
+    { TYPE_INFO_KIND_INT32, 4, "i32", 1, 0, 0, 0, 1 },
+    { TYPE_INFO_KIND_INT64, 8, "i64", 1, 0, 0, 0, 1 },
 
-    { ONYX_TYPE_INFO_KIND_FLOAT32, 4, "f32", 0, 0, 1, 0, 1 },
-    { ONYX_TYPE_INFO_KIND_FLOAT64, 8, "f64", 0, 0, 1, 0, 1},
-    { ONYX_TYPE_INFO_KIND_SOFT_FLOAT, 8, "sf64", 0, 0, 1, 0, 1 },
+    { TYPE_INFO_KIND_FLOAT32, 4, "f32", 0, 0, 1, 0, 1 },
+    { TYPE_INFO_KIND_FLOAT64, 8, "f64", 0, 0, 1, 0, 1},
+    { TYPE_INFO_KIND_SOFT_FLOAT, 8, "sf64", 0, 0, 1, 0, 1 },
 
     { 0xffffffff } // Sentinel
 };
 
-static OnyxAstNode error_node = { { ONYX_AST_NODE_KIND_ERROR, 0, NULL, &builtin_types[0], 0, NULL, NULL, NULL } };
+static AstNode error_node = { AST_NODE_KIND_ERROR, 0, NULL, NULL };
 
 // NOTE: Forward declarations
 static void parser_next_token(OnyxParser* parser);
 static void parser_prev_token(OnyxParser* parser);
-static b32 is_terminating_token(OnyxTokenType token_type);
-static OnyxToken* expect(OnyxParser* parser, OnyxTokenType token_type);
-static OnyxAstNodeScope* enter_scope(OnyxParser* parser);
-static OnyxAstNodeScope* leave_scope(OnyxParser* parser);
-static void insert_identifier(OnyxParser* parser, OnyxAstNode* ident, b32 is_local);
-static void remove_identifier(OnyxParser* parser, OnyxAstNode* ident);
-static OnyxAstNodeNumLit* parse_numeric_literal(OnyxParser* parser);
-static OnyxAstNode* parse_factor(OnyxParser* parser);
-static OnyxAstNode* parse_bin_op(OnyxParser* parser, OnyxAstNode* left);
-static OnyxAstNode* parse_expression(OnyxParser* parser);
-static OnyxAstNodeIf* parse_if_stmt(OnyxParser* parser);
-static OnyxAstNodeWhile* parse_while_stmt(OnyxParser* parser);
-static b32 parse_symbol_statement(OnyxParser* parser, OnyxAstNode** ret);
-static OnyxAstNode* parse_return_statement(OnyxParser* parser);
-static OnyxAstNodeBlock* parse_block(OnyxParser* parser);
-static OnyxAstNode* parse_statement(OnyxParser* parser);
-static OnyxTypeInfo* parse_type(OnyxParser* parser);
-static OnyxAstNodeParam* parse_function_params(OnyxParser* parser);
-static OnyxAstNodeFunction* parse_function_definition(OnyxParser* parser);
-static OnyxAstNode* parse_top_level_statement(OnyxParser* parser);
+static b32 is_terminating_token(TokenType token_type);
+static OnyxToken* expect(OnyxParser* parser, TokenType token_type);
+static AstNodeScope* enter_scope(OnyxParser* parser);
+static AstNodeScope* leave_scope(OnyxParser* parser);
+static void insert_identifier(OnyxParser* parser, AstNode* ident, b32 is_local);
+static void remove_identifier(OnyxParser* parser, AstNode* ident);
+static AstNodeNumLit* parse_numeric_literal(OnyxParser* parser);
+static AstNodeTyped* parse_factor(OnyxParser* parser);
+static AstNodeTyped* parse_bin_op(OnyxParser* parser, AstNode* left);
+static AstNodeTyped* parse_expression(OnyxParser* parser);
+static AstNodeIf* parse_if_stmt(OnyxParser* parser);
+static AstNodeWhile* parse_while_stmt(OnyxParser* parser);
+static b32 parse_symbol_statement(OnyxParser* parser, AstNode** ret);
+static AstNodeReturn* parse_return_statement(OnyxParser* parser);
+static AstNodeBlock* parse_block(OnyxParser* parser);
+static AstNode* parse_statement(OnyxParser* parser);
+static TypeInfo* parse_type(OnyxParser* parser);
+static AstNodeLocal* parse_function_params(OnyxParser* parser);
+static AstNodeFunction* parse_function_definition(OnyxParser* parser);
+static AstNode* parse_top_level_statement(OnyxParser* parser);
 
 static void parser_next_token(OnyxParser* parser) {
     parser->prev_token = parser->curr_token;
@@ -93,7 +96,7 @@ static void parser_prev_token(OnyxParser* parser) {
     parser->prev_token--;
 }
 
-static b32 is_terminating_token(OnyxTokenType token_type) {
+static b32 is_terminating_token(TokenType token_type) {
     switch (token_type) {
     case TOKEN_TYPE_SYM_SEMICOLON:
     case TOKEN_TYPE_CLOSE_BRACE:
@@ -105,14 +108,14 @@ static b32 is_terminating_token(OnyxTokenType token_type) {
     }
 }
 
-static void find_token(OnyxParser* parser, OnyxTokenType token_type) {
+static void find_token(OnyxParser* parser, TokenType token_type) {
     while (parser->curr_token->type != token_type && !is_terminating_token(parser->curr_token->type)) {
         parser_next_token(parser);
     }
 }
 
 // Advances to next token no matter what
-static OnyxToken* expect(OnyxParser* parser, OnyxTokenType token_type) {
+static OnyxToken* expect(OnyxParser* parser, TokenType token_type) {
     OnyxToken* token = parser->curr_token;
     parser_next_token(parser);
 
@@ -127,51 +130,51 @@ static OnyxToken* expect(OnyxParser* parser, OnyxTokenType token_type) {
     return token;
 }
 
-static OnyxAstNodeNumLit* parse_numeric_literal(OnyxParser* parser) {
-    OnyxAstNodeNumLit* lit_node = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_LITERAL);
-    lit_node->token = expect(parser, TOKEN_TYPE_LITERAL_NUMERIC);
-    lit_node->flags |= ONYX_AST_FLAG_COMPTIME;
+static AstNodeNumLit* parse_numeric_literal(OnyxParser* parser) {
+    AstNodeNumLit* lit_node = make_node(AstNodeNumLit, AST_NODE_KIND_LITERAL);
+    lit_node->base.token = expect(parser, TOKEN_TYPE_LITERAL_NUMERIC);
+    lit_node->base.flags |= ONYX_AST_FLAG_COMPTIME;
     lit_node->value.l = 0ll;
 
-    onyx_token_null_toggle(*lit_node->token);
+    onyx_token_null_toggle(lit_node->base.token);
 
-    OnyxTypeInfo* type;
-    char* tok = lit_node->token->token;
+    TypeInfo* type;
+    char* tok = lit_node->base.token->token;
 
     // NOTE: charset_contains() behaves more like string_contains()
     // so I'm using it in this case
     if (charset_contains(tok, '.')) {
-        if (tok[lit_node->token->length - 1] == 'f') {
-            type = &builtin_types[ONYX_TYPE_INFO_KIND_FLOAT32];
+        if (tok[lit_node->base.token->length - 1] == 'f') {
+            type = &builtin_types[TYPE_INFO_KIND_FLOAT32];
             lit_node->value.f = strtof(tok, NULL);
         } else {
-            type = &builtin_types[ONYX_TYPE_INFO_KIND_FLOAT64];
+            type = &builtin_types[TYPE_INFO_KIND_FLOAT64];
             lit_node->value.d = strtod(tok, NULL);
         }
     } else {
         i64 value = strtoll(tok, NULL, 0);
         if (bh_abs(value) < ((u64) 1 << 32)) {
-            type = &builtin_types[ONYX_TYPE_INFO_KIND_INT32];
+            type = &builtin_types[TYPE_INFO_KIND_INT32];
         } else {
-            type = &builtin_types[ONYX_TYPE_INFO_KIND_INT64];
+            type = &builtin_types[TYPE_INFO_KIND_INT64];
         }
 
         lit_node->value.l = value;
     }
 
-    lit_node->type = type;
-    onyx_token_null_toggle(*lit_node->token);
+    lit_node->base.type = type;
+    onyx_token_null_toggle(lit_node->base.token);
     return lit_node;
 }
 
-static OnyxAstNode* parse_factor(OnyxParser* parser) {
-    OnyxAstNode* retval = NULL;
+static AstNodeTyped* parse_factor(OnyxParser* parser) {
+    AstNodeTyped* retval = NULL;
 
     switch (parser->curr_token->type) {
         case TOKEN_TYPE_OPEN_PAREN:
             {
                 parser_next_token(parser);
-                OnyxAstNode* expr = parse_expression(parser);
+                AstNodeTyped* expr = parse_expression(parser);
                 expect(parser, TOKEN_TYPE_CLOSE_PAREN);
                 retval = expr;
                 break;
@@ -180,25 +183,24 @@ static OnyxAstNode* parse_factor(OnyxParser* parser) {
         case TOKEN_TYPE_SYM_MINUS:
             {
                 parser_next_token(parser);
-                OnyxAstNode* factor = parse_factor(parser);
+                AstNodeTyped* factor = parse_factor(parser);
 
-                OnyxAstNodeUnaryOp* negate_node = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_UNARY_OP);
+                AstNodeUnaryOp* negate_node = make_node(AstNodeUnaryOp, AST_NODE_KIND_UNARY_OP);
                 negate_node->operation = ONYX_UNARY_OP_NEGATE;
-                negate_node->left = factor;
-                negate_node->type = factor->type;
+                negate_node->expr = factor;
 
                 if ((factor->flags & ONYX_AST_FLAG_COMPTIME) != 0) {
-                    negate_node->flags |= ONYX_AST_FLAG_COMPTIME;
+                    negate_node->base.flags |= ONYX_AST_FLAG_COMPTIME;
                 }
 
-                retval = (OnyxAstNode *) negate_node;
+                retval = (AstNodeTyped *) negate_node;
                 break;
             }
 
         case TOKEN_TYPE_SYMBOL:
             {
                 OnyxToken* sym_token = expect(parser, TOKEN_TYPE_SYMBOL);
-                OnyxAstNode* sym_node = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_SYMBOL);
+                AstNodeTyped* sym_node = make_node(AstNode, AST_NODE_KIND_SYMBOL);
                 sym_node->token = sym_token;
 
                 if (parser->curr_token->type != TOKEN_TYPE_OPEN_PAREN) {
@@ -207,23 +209,19 @@ static OnyxAstNode* parse_factor(OnyxParser* parser) {
                 }
 
                 // NOTE: Function call
-                OnyxAstNodeCall* call_node = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_CALL);
-                call_node->token = expect(parser, TOKEN_TYPE_OPEN_PAREN);
-                call_node->callee = sym_node;
-                // NOTE: Return type is stored on function definition's type
-                // This may have to change if we want multiple returns
-                call_node->type = sym_node->type;
-
-                OnyxAstNode** prev = &call_node->arguments;
-                OnyxAstNode* curr = NULL;
+                AstNodeCall* call_node = make_node(AstNodeCall, AST_NODE_KIND_CALL);
+                call_node->base.token = expect(parser, TOKEN_TYPE_OPEN_PAREN);
+                call_node->callee = (AstNode *) sym_node;
+
+                AstNodeArgument** prev = &call_node->arguments;
+                AstNodeArgument* curr = NULL;
                 while (parser->curr_token->type != TOKEN_TYPE_CLOSE_PAREN) {
-                    curr = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_ARGUMENT);
-                    curr->left = parse_expression(parser);
-                    curr->type = curr->left->type;
+                    curr = make_node(AstNodeArgument, AST_NODE_KIND_ARGUMENT);
+                    curr->value = parse_expression(parser);
 
-                    if (curr != NULL && curr->kind != ONYX_AST_NODE_KIND_ERROR) {
+                    if (curr != NULL && curr->base.kind != AST_NODE_KIND_ERROR) {
                         *prev = curr;
-                        prev = &curr->next;
+                        prev = (AstNodeArgument **) &curr->base.next;
                     }
 
                     if (parser->curr_token->type == TOKEN_TYPE_CLOSE_PAREN)
@@ -235,38 +233,38 @@ static OnyxAstNode* parse_factor(OnyxParser* parser) {
                                 parser->curr_token->pos,
                                 onyx_get_token_type_name(TOKEN_TYPE_SYM_COMMA),
                                 onyx_get_token_type_name(parser->curr_token->type));
-                        return &error_node;
+                        return (AstNodeTyped *) &error_node;
                     }
 
                     parser_next_token(parser);
                 }
                 parser_next_token(parser);
 
-                retval = (OnyxAstNode *) call_node;
+                retval = (AstNodeTyped *) call_node;
                 break;
             }
 
         case TOKEN_TYPE_LITERAL_NUMERIC:
-            retval = (OnyxAstNode *) parse_numeric_literal(parser);
+            retval = (AstNodeTyped *) parse_numeric_literal(parser);
             break;
 
         case TOKEN_TYPE_LITERAL_BOOL_TRUE:
             {
-                OnyxAstNodeNumLit* bool_node = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_LITERAL);
-                bool_node->type = &builtin_types[ONYX_TYPE_INFO_KIND_BOOL];
-                bool_node->token = expect(parser, TOKEN_TYPE_LITERAL_BOOL_TRUE);
+                AstNodeNumLit* bool_node = make_node(AstNodeNumLit, AST_NODE_KIND_LITERAL);
+                bool_node->base.type = &builtin_types[TYPE_INFO_KIND_BOOL];
+                bool_node->base.token = expect(parser, TOKEN_TYPE_LITERAL_BOOL_TRUE);
                 bool_node->value.i = 1;
-                retval = (OnyxAstNode *) bool_node;
+                retval = (AstNodeTyped *) bool_node;
                 break;
             }
 
         case TOKEN_TYPE_LITERAL_BOOL_FALSE:
             {
-                OnyxAstNodeNumLit* bool_node = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_LITERAL);
-                bool_node->type = &builtin_types[ONYX_TYPE_INFO_KIND_BOOL];
-                bool_node->token = expect(parser, TOKEN_TYPE_LITERAL_BOOL_FALSE);
+                AstNodeNumLit* bool_node = make_node(AstNodeNumLit, AST_NODE_KIND_LITERAL);
+                bool_node->base.type = &builtin_types[TYPE_INFO_KIND_BOOL];
+                bool_node->base.token = expect(parser, TOKEN_TYPE_LITERAL_BOOL_FALSE);
                 bool_node->value.i = 0;
-                retval = (OnyxAstNode *) bool_node;
+                retval = (AstNodeTyped *) bool_node;
                 break;
             }
 
@@ -281,11 +279,11 @@ static OnyxAstNode* parse_factor(OnyxParser* parser) {
     if (parser->curr_token->type == TOKEN_TYPE_KEYWORD_CAST) {
         parser_next_token(parser);
 
-        OnyxAstNodeUnaryOp* cast_node = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_UNARY_OP);
+        AstNodeUnaryOp* cast_node = make_node(AstNodeUnaryOp, AST_NODE_KIND_UNARY_OP);
+        cast_node->base.type = parse_type(parser);
         cast_node->operation = ONYX_UNARY_OP_CAST;
-        cast_node->type = parse_type(parser);
-        cast_node->left = retval;
-        retval = (OnyxAstNode *) cast_node;
+        cast_node->expr = retval;
+        retval = (AstNodeTyped *) cast_node;
     }
 
     return retval;
@@ -312,14 +310,14 @@ static inline i32 get_precedence(OnyxBinaryOp kind) {
     }
 }
 
-static OnyxAstNode* parse_expression(OnyxParser* parser) {
-    bh_arr(OnyxAstNodeBinOp*) tree_stack = NULL;
+static AstNodeTyped* parse_expression(OnyxParser* parser) {
+    bh_arr(AstNodeBinOp*) tree_stack = NULL;
     bh_arr_new(global_scratch_allocator, tree_stack, 4);
     bh_arr_set_length(tree_stack, 0);
 
-    OnyxAstNode* left = parse_factor(parser);
-    OnyxAstNode* right;
-    OnyxAstNode* root = left;
+    AstNodeTyped* left = parse_factor(parser);
+    AstNodeTyped* right;
+    AstNodeTyped* root = left;
 
     OnyxBinaryOp bin_op_kind;
     OnyxToken* bin_op_tok;
@@ -346,9 +344,9 @@ static OnyxAstNode* parse_expression(OnyxParser* parser) {
             bin_op_tok = parser->curr_token;
             parser_next_token(parser);
 
-            OnyxAstNodeBinOp* bin_op = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_BIN_OP);
+            AstNodeBinOp* bin_op = make_node(AstNodeBinOp, AST_NODE_KIND_BIN_OP);
             bin_op->operation = bin_op_kind;
-            bin_op->token = bin_op_tok;
+            bin_op->base.token = bin_op_tok;
 
             while ( !bh_arr_is_empty(tree_stack) &&
                     get_precedence(bh_arr_last(tree_stack)->operation) >= get_precedence(bin_op_kind))
@@ -357,20 +355,19 @@ static OnyxAstNode* parse_expression(OnyxParser* parser) {
             if (bh_arr_is_empty(tree_stack)) {
                 // NOTE: new is now the root node
                 bin_op->left = root;
-                root = (OnyxAstNode *) bin_op;
+                root = (AstNodeTyped *) bin_op;
             } else {
                 bin_op->left = bh_arr_last(tree_stack)->right;
-                bh_arr_last(tree_stack)->right = (OnyxAstNode *) bin_op;
+                bh_arr_last(tree_stack)->right = (AstNodeTyped *) bin_op;
             }
 
             bh_arr_push(tree_stack, bin_op);
 
             right = parse_factor(parser);
             bin_op->right = right;
-            bin_op->type = right->type;
 
             if ((left->flags & ONYX_AST_FLAG_COMPTIME) != 0 && (right->flags & ONYX_AST_FLAG_COMPTIME) != 0) {
-                bin_op->flags |= ONYX_AST_FLAG_COMPTIME;
+                bin_op->base.flags |= ONYX_AST_FLAG_COMPTIME;
             }
         }
     }
@@ -379,14 +376,14 @@ expression_done:
     return root;
 }
 
-static OnyxAstNodeIf* parse_if_stmt(OnyxParser* parser) {
+static AstNodeIf* parse_if_stmt(OnyxParser* parser) {
     expect(parser, TOKEN_TYPE_KEYWORD_IF);
 
-    OnyxAstNode* cond = parse_expression(parser);
-    OnyxAstNode* true_block = (OnyxAstNode *) parse_block(parser);
+    AstNodeTyped* cond = parse_expression(parser);
+    AstNode* true_block = (AstNode *) parse_block(parser);
 
-    OnyxAstNodeIf* if_node = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_IF);
-    OnyxAstNodeIf* root_if = if_node;
+    AstNodeIf* if_node = make_node(AstNodeIf, AST_NODE_KIND_IF);
+    AstNodeIf* root_if = if_node;
 
     if_node->cond = cond;
     if (true_block != NULL)
@@ -394,23 +391,23 @@ static OnyxAstNodeIf* parse_if_stmt(OnyxParser* parser) {
 
     while (parser->curr_token->type == TOKEN_TYPE_KEYWORD_ELSEIF) {
         parser_next_token(parser);
-        OnyxAstNodeIf* elseif_node = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_IF);
+        AstNodeIf* elseif_node = make_node(AstNodeIf, AST_NODE_KIND_IF);
 
         cond = parse_expression(parser);
-        true_block = (OnyxAstNode *) parse_block(parser);
+        true_block = (AstNode *) parse_block(parser);
 
         elseif_node->cond = cond;
         if (true_block != NULL)
             elseif_node->true_block = true_block;
 
-        if_node->false_block = (OnyxAstNode *) elseif_node;
+        if_node->false_block = (AstNode *) elseif_node;
         if_node = elseif_node;
     }
 
     if (parser->curr_token->type == TOKEN_TYPE_KEYWORD_ELSE) {
         parser_next_token(parser);
 
-        OnyxAstNode* false_block = (OnyxAstNode *) parse_block(parser);
+        AstNode* false_block = (AstNode *) parse_block(parser);
         if (false_block != NULL)
             if_node->false_block = false_block;
     }
@@ -418,14 +415,14 @@ static OnyxAstNodeIf* parse_if_stmt(OnyxParser* parser) {
     return root_if;
 }
 
-static OnyxAstNodeWhile* parse_while_stmt(OnyxParser* parser) {
+static AstNodeWhile* parse_while_stmt(OnyxParser* parser) {
     OnyxToken* while_token = expect(parser, TOKEN_TYPE_KEYWORD_WHILE);
 
-    OnyxAstNode* cond = parse_expression(parser);
-    OnyxAstNodeBlock* body = parse_block(parser);
+    AstNodeTyped* cond = parse_expression(parser);
+    AstNodeBlock* body = parse_block(parser);
 
-    OnyxAstNodeWhile* while_node = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_WHILE);
-    while_node->token = while_token;
+    AstNodeWhile* while_node = make_node(AstNodeWhile, AST_NODE_KIND_WHILE);
+    while_node->base.token = while_token;
     while_node->cond = cond;
     while_node->body = body;
 
@@ -434,7 +431,7 @@ static OnyxAstNodeWhile* parse_while_stmt(OnyxParser* parser) {
 
 // Returns 1 if the symbol was consumed. Returns 0 otherwise
 // ret is set to the statement to insert
-static b32 parse_symbol_statement(OnyxParser* parser, OnyxAstNode** ret) {
+static b32 parse_symbol_statement(OnyxParser* parser, AstNode** ret) {
     if (parser->curr_token->type != TOKEN_TYPE_SYMBOL) return 0;
     OnyxToken* symbol = expect(parser, TOKEN_TYPE_SYMBOL);
 
@@ -443,44 +440,44 @@ static b32 parse_symbol_statement(OnyxParser* parser, OnyxAstNode** ret) {
         case TOKEN_TYPE_SYM_COLON:
             {
                 parser_next_token(parser);
-                OnyxTypeInfo* type = &builtin_types[ONYX_TYPE_INFO_KIND_UNKNOWN];
+                TypeInfo* type = &builtin_types[TYPE_INFO_KIND_UNKNOWN];
 
                 // NOTE: var: type
                 if (parser->curr_token->type == TOKEN_TYPE_SYMBOL) {
                     type = parse_type(parser);
                 }
 
-                OnyxAstNodeLocal* local = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_LOCAL);
-                local->token = symbol;
-                local->type = type;
-                local->flags |= ONYX_AST_FLAG_LVAL; // NOTE: DELETE
-                *ret = (OnyxAstNode *) local;
+                AstNodeLocal* local = make_node(AstNodeLocal, AST_NODE_KIND_LOCAL);
+                local->base.token = symbol;
+                local->base.type = type;
+                local->base.flags |= ONYX_AST_FLAG_LVAL; // NOTE: DELETE
+                *ret = (AstNode *) local;
 
                 if (parser->curr_token->type == TOKEN_TYPE_SYM_EQUALS || parser->curr_token->type == TOKEN_TYPE_SYM_COLON) {
                     if (parser->curr_token->type == TOKEN_TYPE_SYM_COLON) {
-                        local->flags |= ONYX_AST_FLAG_CONST;
+                        local->base.flags |= ONYX_AST_FLAG_CONST;
                     }
 
-                    OnyxAstNode* assignment = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_ASSIGNMENT);
-                    local->next = assignment;
-                    assignment->token = parser->curr_token;
+                    AstNodeAssign* assignment = make_node(AstNodeAssign, AST_NODE_KIND_ASSIGNMENT);
+                    local->base.next = (AstNode *) assignment;
+                    assignment->base.token = parser->curr_token;
                     parser_next_token(parser);
 
-                    OnyxAstNode* expr = parse_expression(parser);
+                    AstNodeTyped* expr = parse_expression(parser);
                     if (expr == NULL) {
-                        onyx_token_null_toggle(*parser->curr_token);
+                        onyx_token_null_toggle(parser->curr_token);
                         onyx_message_add(parser->msgs,
                                 ONYX_MESSAGE_TYPE_EXPECTED_EXPRESSION,
-                                assignment->token->pos,
+                                assignment->base.token->pos,
                                 parser->curr_token->token);
-                        onyx_token_null_toggle(*parser->curr_token);
+                        onyx_token_null_toggle(parser->curr_token);
                         return 1;
                     }
-                    assignment->right = expr;
+                    assignment->expr = expr;
 
-                    OnyxAstNode* left_symbol = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_SYMBOL);
+                    AstNode* left_symbol = make_node(AstNode, AST_NODE_KIND_SYMBOL);
                     left_symbol->token = symbol;
-                    assignment->left = left_symbol;
+                    assignment->lval = (AstNodeTyped *) left_symbol;
                 }
                 return 1;
             }
@@ -488,17 +485,17 @@ static b32 parse_symbol_statement(OnyxParser* parser, OnyxAstNode** ret) {
             // NOTE: Assignment
         case TOKEN_TYPE_SYM_EQUALS:
             {
-                OnyxAstNode* assignment = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_ASSIGNMENT);
-                assignment->token = parser->curr_token;
+                AstNodeAssign* assignment = make_node(AstNodeAssign, AST_NODE_KIND_ASSIGNMENT);
+                assignment->base.token = parser->curr_token;
                 parser_next_token(parser);
 
-                OnyxAstNode* lval = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_SYMBOL);
+                AstNode* lval = make_node(AstNode, AST_NODE_KIND_SYMBOL);
                 lval->token = symbol;
 
-                OnyxAstNode* rval = parse_expression(parser);
-                assignment->right = rval;
-                assignment->left = lval;
-                *ret = assignment;
+                AstNodeTyped* rval = parse_expression(parser);
+                assignment->expr = rval;
+                assignment->lval = (AstNodeTyped *) lval;
+                *ret = (AstNode *) assignment;
                 return 1;
             }
 
@@ -509,37 +506,37 @@ static b32 parse_symbol_statement(OnyxParser* parser, OnyxAstNode** ret) {
     return 0;
 }
 
-static OnyxAstNode* parse_return_statement(OnyxParser* parser) {
-    OnyxAstNode* return_node = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_RETURN);
-    return_node->token = expect(parser, TOKEN_TYPE_KEYWORD_RETURN);
+static AstNodeReturn* parse_return_statement(OnyxParser* parser) {
+    AstNodeReturn* return_node = make_node(AstNodeReturn, AST_NODE_KIND_RETURN);
+    return_node->base.token = expect(parser, TOKEN_TYPE_KEYWORD_RETURN);
 
-    OnyxAstNode* expr = NULL;
+    AstNodeTyped* expr = NULL;
 
     if (parser->curr_token->type != TOKEN_TYPE_SYM_SEMICOLON) {
         expr = parse_expression(parser);
 
-        if (expr == NULL || expr == &error_node) {
-            return &error_node;
+        if (expr == NULL || expr == (AstNodeTyped *) &error_node) {
+            return (AstNodeReturn *) &error_node;
         } else {
-            return_node->left = expr;
+            return_node->expr = expr;
         }
     }
 
     return return_node;
 }
 
-static OnyxAstNode* parse_statement(OnyxParser* parser) {
+static AstNode* parse_statement(OnyxParser* parser) {
     b32 needs_semicolon = 1;
-    OnyxAstNode* retval = NULL;
+    AstNode* retval = NULL;
 
     switch (parser->curr_token->type) {
         case TOKEN_TYPE_KEYWORD_RETURN:
-            retval = parse_return_statement(parser);
+            retval = (AstNode *) parse_return_statement(parser);
             break;
 
         case TOKEN_TYPE_OPEN_BRACE:
             needs_semicolon = 0;
-            retval = (OnyxAstNode *) parse_block(parser);
+            retval = (AstNode *) parse_block(parser);
             break;
 
         case TOKEN_TYPE_SYMBOL:
@@ -552,26 +549,26 @@ static OnyxAstNode* parse_statement(OnyxParser* parser) {
         case TOKEN_TYPE_SYM_BANG:
         case TOKEN_TYPE_LITERAL_NUMERIC:
         case TOKEN_TYPE_LITERAL_STRING:
-            retval = parse_expression(parser);
+            retval = (AstNode *) parse_expression(parser);
             break;
 
         case TOKEN_TYPE_KEYWORD_IF:
             needs_semicolon = 0;
-            retval = (OnyxAstNode *) parse_if_stmt(parser);
+            retval = (AstNode *) parse_if_stmt(parser);
             break;
 
         case TOKEN_TYPE_KEYWORD_WHILE:
             needs_semicolon = 0;
-            retval = (OnyxAstNode *) parse_while_stmt(parser);
+            retval = (AstNode *) parse_while_stmt(parser);
             break;
 
         case TOKEN_TYPE_KEYWORD_BREAK:
-            retval = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_BREAK);
+            retval = make_node(AstNode, AST_NODE_KIND_BREAK);
             retval->token = expect(parser, TOKEN_TYPE_KEYWORD_BREAK);
             break;
 
         case TOKEN_TYPE_KEYWORD_CONTINUE:
-            retval = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_CONTINUE);
+            retval = make_node(AstNode, AST_NODE_KIND_BREAK);
             retval->token = expect(parser, TOKEN_TYPE_KEYWORD_CONTINUE);
             break;
 
@@ -595,9 +592,9 @@ static OnyxAstNode* parse_statement(OnyxParser* parser) {
     return retval;
 }
 
-static OnyxAstNodeBlock* parse_block(OnyxParser* parser) {
-    OnyxAstNodeBlock* block = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_BLOCK);
-    OnyxAstNodeScope* scope = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_SCOPE);
+static AstNodeBlock* parse_block(OnyxParser* parser) {
+    AstNodeBlock* block = make_node(AstNodeBlock, AST_NODE_KIND_BLOCK);
+    AstNodeScope* scope = make_node(AstNodeScope, AST_NODE_KIND_SCOPE);
     block->scope = scope;
 
     // --- is for an empty block
@@ -610,12 +607,12 @@ static OnyxAstNodeBlock* parse_block(OnyxParser* parser) {
 
     expect(parser, TOKEN_TYPE_OPEN_BRACE);
 
-    OnyxAstNode** next = &block->body;
-    OnyxAstNode* stmt = NULL;
+    AstNode** next = &block->body;
+    AstNode* stmt = NULL;
     while (parser->curr_token->type != TOKEN_TYPE_CLOSE_BRACE) {
         stmt = parse_statement(parser);
 
-        if (stmt != NULL && stmt->kind != ONYX_AST_NODE_KIND_ERROR) {
+        if (stmt != NULL && stmt->kind != AST_NODE_KIND_ERROR) {
             *next = stmt;
 
             while (stmt->next != NULL) stmt = stmt->next;
@@ -628,29 +625,29 @@ static OnyxAstNodeBlock* parse_block(OnyxParser* parser) {
     return block;
 }
 
-static OnyxTypeInfo* parse_type(OnyxParser* parser) {
-    OnyxTypeInfo* type_info = &builtin_types[ONYX_TYPE_INFO_KIND_UNKNOWN];
+static TypeInfo* parse_type(OnyxParser* parser) {
+    TypeInfo* type_info = &builtin_types[TYPE_INFO_KIND_UNKNOWN];
 
     OnyxToken* symbol = expect(parser, TOKEN_TYPE_SYMBOL);
     if (symbol == NULL) return type_info;
 
-    onyx_token_null_toggle(*symbol);
+    onyx_token_null_toggle(symbol);
 
-    if (!bh_table_has(OnyxAstNode*, parser->identifiers, symbol->token)) {
+    if (!bh_table_has(AstNode*, parser->identifiers, symbol->token)) {
         onyx_message_add(parser->msgs, ONYX_MESSAGE_TYPE_UNKNOWN_TYPE, symbol->pos, symbol->token);
     } else {
-        OnyxAstNode* type_info_node = bh_table_get(OnyxAstNode*, parser->identifiers, symbol->token);
+        AstNodeTyped* type_info_node = bh_table_get(AstNodeTyped*, parser->identifiers, symbol->token);
 
-        if (type_info_node->kind == ONYX_AST_NODE_KIND_TYPE) {
+        if (type_info_node->kind == AST_NODE_KIND_TYPE) {
             type_info = type_info_node->type;
         }
     }
 
-    onyx_token_null_toggle(*symbol);
+    onyx_token_null_toggle(symbol);
     return type_info;
 }
 
-static OnyxAstNodeParam* parse_function_params(OnyxParser* parser) {
+static AstNodeLocal* parse_function_params(OnyxParser* parser) {
     if (parser->curr_token->type != TOKEN_TYPE_OPEN_PAREN)
         return NULL;
 
@@ -661,9 +658,9 @@ static OnyxAstNodeParam* parse_function_params(OnyxParser* parser) {
         return NULL;
     }
 
-    OnyxAstNodeParam* first_param = NULL;
-    OnyxAstNodeParam* curr_param = NULL;
-    OnyxAstNodeParam* trailer = NULL;
+    AstNodeLocal* first_param = NULL;
+    AstNodeLocal* curr_param = NULL;
+    AstNodeLocal* trailer = NULL;
 
     OnyxToken* symbol;
     while (parser->curr_token->type != TOKEN_TYPE_CLOSE_PAREN) {
@@ -672,15 +669,15 @@ static OnyxAstNodeParam* parse_function_params(OnyxParser* parser) {
         symbol = expect(parser, TOKEN_TYPE_SYMBOL);
         expect(parser, TOKEN_TYPE_SYM_COLON);
 
-        curr_param = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_PARAM);
-        curr_param->token = symbol;
-        curr_param->type = parse_type(parser);
-        curr_param->flags |= ONYX_AST_FLAG_CONST;
+        curr_param = make_node(AstNodeLocal, AST_NODE_KIND_PARAM);
+        curr_param->base.token = symbol;
+        curr_param->base.flags |= ONYX_AST_FLAG_CONST;
+        curr_param->base.type = parse_type(parser);
 
         if (first_param == NULL) first_param = curr_param;
 
-        curr_param->next = NULL;
-        if (trailer) trailer->next = curr_param;
+        curr_param->base.next = NULL;
+        if (trailer) trailer->base.next = (AstNode *) curr_param;
 
         trailer = curr_param;
     }
@@ -689,21 +686,21 @@ static OnyxAstNodeParam* parse_function_params(OnyxParser* parser) {
     return first_param;
 }
 
-static OnyxAstNodeFunction* parse_function_definition(OnyxParser* parser) {
+static AstNodeFunction* parse_function_definition(OnyxParser* parser) {
     expect(parser, TOKEN_TYPE_KEYWORD_PROC);
 
-    OnyxAstNodeFunction* func_def = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_FUNCTION);
+    AstNodeFunction* func_def = make_node(AstNodeFunction, AST_NODE_KIND_FUNCTION);
 
-    OnyxAstNodeParam* params = parse_function_params(parser);
+    AstNodeLocal* params = parse_function_params(parser);
     func_def->params = params;
 
     if (parser->curr_token->type == TOKEN_TYPE_RIGHT_ARROW) {
         expect(parser, TOKEN_TYPE_RIGHT_ARROW);
 
-        OnyxTypeInfo* return_type = parse_type(parser);
-        func_def->return_type = return_type;
+        TypeInfo* return_type = parse_type(parser);
+        func_def->base.type = return_type;
     } else {
-        func_def->return_type = &builtin_types[ONYX_TYPE_INFO_KIND_VOID];
+        func_def->base.type = &builtin_types[TYPE_INFO_KIND_VOID];
     }
 
     func_def->body = parse_block(parser);
@@ -711,62 +708,62 @@ static OnyxAstNodeFunction* parse_function_definition(OnyxParser* parser) {
     return func_def;
 }
 
-static OnyxAstNode* parse_foreign(OnyxParser* parser) {
+static AstNode* parse_foreign(OnyxParser* parser) {
     expect(parser, TOKEN_TYPE_KEYWORD_FOREIGN);
 
-    OnyxAstNodeForeign* foreign = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_FOREIGN);
+    AstNodeForeign* foreign = make_node(AstNodeForeign, AST_NODE_KIND_FOREIGN);
     foreign->mod_token = expect(parser, TOKEN_TYPE_LITERAL_STRING);
     foreign->name_token = expect(parser, TOKEN_TYPE_LITERAL_STRING);
 
     if (parser->curr_token->type == TOKEN_TYPE_KEYWORD_PROC) {
-        foreign->import = (OnyxAstNode *) parse_function_definition(parser);
+        foreign->import = (AstNode *) parse_function_definition(parser);
 
     } else {
-        OnyxTypeInfo* type = parse_type(parser);
+        TypeInfo* type = parse_type(parser);
 
-        OnyxAstNodeGlobal* global = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_GLOBAL);
-        global->type = type;
-        global->flags |= ONYX_AST_FLAG_LVAL;
+        AstNodeGlobal* global = make_node(AstNodeGlobal, AST_NODE_KIND_GLOBAL);
+        global->base.type = type;
+        global->base.flags |= ONYX_AST_FLAG_LVAL;
 
-        foreign->import = (OnyxAstNode *) global;
+        foreign->import = (AstNode *) global;
     }
 
-    return (OnyxAstNode *) foreign;
+    return (AstNode *) foreign;
 }
 
-static OnyxAstNode* parse_top_level_constant_symbol(OnyxParser* parser) {
+static AstNode* parse_top_level_constant_symbol(OnyxParser* parser) {
     if (parser->curr_token->type == TOKEN_TYPE_KEYWORD_PROC) {
-        return (OnyxAstNode *) parse_function_definition(parser);
+        return (AstNode *) parse_function_definition(parser);
 
     } else if (parser->curr_token->type == TOKEN_TYPE_KEYWORD_STRUCT) {
         // Handle struct case
         assert(0);
 
     } else if (parser->curr_token->type == TOKEN_TYPE_KEYWORD_FOREIGN) {
-        return (OnyxAstNode *) parse_foreign(parser);
+        return (AstNode *) parse_foreign(parser);
 
     } else {
         // Global constant with initial value
-        OnyxAstNodeGlobal* global = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_GLOBAL);
+        AstNodeGlobal* global = make_node(AstNodeGlobal, AST_NODE_KIND_GLOBAL);
         global->initial_value = parse_expression(parser);
-        global->type = &builtin_types[ONYX_TYPE_INFO_KIND_UNKNOWN];
-        global->flags |= ONYX_AST_FLAG_CONST;
-        global->flags |= ONYX_AST_FLAG_LVAL;
-        global->flags |= ONYX_AST_FLAG_COMPTIME;
+        global->base.type = &builtin_types[TYPE_INFO_KIND_UNKNOWN];
+        global->base.flags |= ONYX_AST_FLAG_CONST;
+        global->base.flags |= ONYX_AST_FLAG_LVAL;
+        global->base.flags |= ONYX_AST_FLAG_COMPTIME;
 
-        return (OnyxAstNode *) global;
+        return (AstNode *) global;
     }
 }
 
-static OnyxAstNode* parse_top_level_statement(OnyxParser* parser) {
+static AstNode* parse_top_level_statement(OnyxParser* parser) {
     switch (parser->curr_token->type) {
         case TOKEN_TYPE_KEYWORD_USE:
             {
-                OnyxAstNodeUse* use_node = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_USE);
-                use_node->token = expect(parser, TOKEN_TYPE_KEYWORD_USE);
+                AstNodeUse* use_node = make_node(AstNodeUse, AST_NODE_KIND_USE);
+                use_node->base.token = expect(parser, TOKEN_TYPE_KEYWORD_USE);
                 use_node->filename = expect(parser, TOKEN_TYPE_LITERAL_STRING);
 
-                return (OnyxAstNode *) use_node;
+                return (AstNode *) use_node;
             }
 
         case TOKEN_TYPE_KEYWORD_EXPORT:
@@ -781,7 +778,7 @@ static OnyxAstNode* parse_top_level_statement(OnyxParser* parser) {
                     break;
                 }
 
-                OnyxAstNode* top_level_decl = parse_top_level_statement(parser);
+                AstNode* top_level_decl = parse_top_level_statement(parser);
                 top_level_decl->flags |= ONYX_AST_FLAG_EXPORTED;
                 return top_level_decl;
             }
@@ -793,7 +790,7 @@ static OnyxAstNode* parse_top_level_statement(OnyxParser* parser) {
 
                 expect(parser, TOKEN_TYPE_SYM_COLON);
 
-                OnyxTypeInfo* type = &builtin_types[ONYX_TYPE_INFO_KIND_UNKNOWN];
+                TypeInfo* type = &builtin_types[TYPE_INFO_KIND_UNKNOWN];
 
                 if (parser->curr_token->type == TOKEN_TYPE_SYMBOL) {
                     type = parse_type(parser);
@@ -802,14 +799,14 @@ static OnyxAstNode* parse_top_level_statement(OnyxParser* parser) {
                 if (parser->curr_token->type == TOKEN_TYPE_SYM_COLON) {
                     parser_next_token(parser);
 
-                    OnyxAstNode* node = parse_top_level_constant_symbol(parser);
+                    AstNode* node = parse_top_level_constant_symbol(parser);
 
-                    if (node->kind == ONYX_AST_NODE_KIND_GLOBAL) {
-                        node->type = type;
+                    if (node->kind == AST_NODE_KIND_GLOBAL) {
+                        ((AstNodeGlobal *) node)->base.type = type;
                     }
 
-                    if (node->kind == ONYX_AST_NODE_KIND_FOREIGN) {
-                        node->as_foreign.import->token = symbol;
+                    if (node->kind == AST_NODE_KIND_FOREIGN) {
+                        ((AstNodeForeign *) node)->import->token = symbol;
 
                     } else {
                         node->token = symbol;
@@ -820,21 +817,21 @@ static OnyxAstNode* parse_top_level_statement(OnyxParser* parser) {
                 } else if (parser->curr_token->type == TOKEN_TYPE_SYM_EQUALS) {
                     parser_next_token(parser);
 
-                    OnyxAstNodeGlobal* global = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_GLOBAL);
-                    global->token = symbol;
-                    global->flags |= ONYX_AST_FLAG_LVAL;
+                    AstNodeGlobal* global = make_node(AstNodeGlobal, AST_NODE_KIND_GLOBAL);
+                    global->base.token = symbol;
+                    global->base.flags |= ONYX_AST_FLAG_LVAL;
                     global->initial_value = parse_expression(parser);
-                    global->type = type;
+                    global->base.type = type;
 
-                    return (OnyxAstNode *) global;
+                    return (AstNode *) global;
 
                 } else {
-                    onyx_token_null_toggle(*parser->curr_token);
+                    onyx_token_null_toggle(parser->curr_token);
                     onyx_message_add(parser->msgs,
                             ONYX_MESSAGE_TYPE_UNEXPECTED_TOKEN,
                             parser->curr_token->pos,
                             parser->curr_token->token);
-                    onyx_token_null_toggle(*parser->curr_token);
+                    onyx_token_null_toggle(parser->curr_token);
                 }
 
                 return &error_node;
@@ -851,21 +848,16 @@ static OnyxAstNode* parse_top_level_statement(OnyxParser* parser) {
 
 
 
-const char* onyx_ast_node_kind_string(OnyxAstNodeKind kind) {
+const char* onyx_ast_node_kind_string(AstNodeKind kind) {
     return ast_node_names[kind];
 }
 
 // NOTE: This returns a void* so I don't need to cast it everytime I use it
-void* onyx_ast_node_new(bh_allocator alloc, OnyxAstNodeKind kind) {
-    OnyxAstNode* node =  bh_alloc_item(alloc, OnyxAstNode);
-    node->kind = kind;
-    node->flags = 0;
-    node->token = NULL;
-    node->type = NULL;
-    node->data = 0;
-    node->next = NULL;
-    node->left = NULL;
-    node->right = NULL;
+void* onyx_ast_node_new(bh_allocator alloc, i32 size, AstNodeKind kind) {
+    void* node = bh_alloc(alloc, size);
+
+    memset(node, 0, size);
+    *(AstNodeKind *) node = kind;
 
     return node;
 }
@@ -875,11 +867,11 @@ OnyxParser onyx_parser_create(bh_allocator alloc, OnyxTokenizer *tokenizer, Onyx
 
     bh_table_init(bh_heap_allocator(), parser.identifiers, 61);
 
-    OnyxTypeInfo* it = &builtin_types[0];
+    TypeInfo* it = &builtin_types[0];
     while (it->kind != 0xffffffff) {
-        OnyxAstNode* tmp = onyx_ast_node_new(alloc, ONYX_AST_NODE_KIND_TYPE);
+        AstNodeTyped* tmp = onyx_ast_node_new(alloc, sizeof(AstNodeTyped), AST_NODE_KIND_TYPE);
         tmp->type = it;
-        bh_table_put(OnyxAstNode*, parser.identifiers, (char *)it->name, tmp);
+        bh_table_put(AstNode*, parser.identifiers, (char *)it->name, tmp);
         it++;
     }
 
@@ -896,11 +888,11 @@ void onyx_parser_free(OnyxParser* parser) {
     bh_table_free(parser->identifiers);
 }
 
-OnyxAstNode* onyx_parse(OnyxParser *parser) {
-    OnyxAstNode* program = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_PROGRAM);
+AstNode* onyx_parse(OnyxParser *parser) {
+    AstNode* program = make_node(AstNode, AST_NODE_KIND_PROGRAM);
 
-    OnyxAstNode** prev_stmt = &program->next;
-    OnyxAstNode* curr_stmt = NULL;
+    AstNode** prev_stmt = &program->next;
+    AstNode* curr_stmt = NULL;
     while (parser->curr_token->type != TOKEN_TYPE_END_STREAM) {
         curr_stmt = parse_top_level_statement(parser);
 
index 856055f587ce8e8cdc1185e649fec4de0929d448..6bc9553388870235d94ddd86d9724b7e0cebf495 100644 (file)
@@ -13,7 +13,7 @@ OnyxSemPassState onyx_sempass_create(bh_allocator alloc, bh_allocator node_alloc
         .symbols = NULL,
     };
 
-    bh_table_init(bh_heap_allocator(), state.symbols, 61);
+    bh_table_init(global_heap_allocator, state.symbols, 61);
 
     return state;
 }
@@ -24,29 +24,29 @@ OnyxSemPassState onyx_sempass_create(bh_allocator alloc, bh_allocator node_alloc
 // 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(OnyxAstNodeBlock*) traversal_queue = NULL;
+    bh_arr(AstNodeBlock*) traversal_queue = NULL;
     bh_arr_new(global_scratch_allocator, traversal_queue, 4);
     bh_arr_set_length(traversal_queue, 0);
 
-    bh_arr_each(OnyxAstNodeFunction *, func, program->functions) {
-        OnyxAstNodeScope* top_scope = (*func)->body->scope;
+    bh_arr_each(AstNodeFunction *, func, program->functions) {
+        AstNodeScope* top_scope = (*func)->body->scope;
 
         bh_arr_push(traversal_queue, (*func)->body);
         while (!bh_arr_is_empty(traversal_queue)) {
-            OnyxAstNodeBlock* block = traversal_queue[0];
+            AstNodeBlock* block = traversal_queue[0];
 
-            if (block->kind == ONYX_AST_NODE_KIND_IF) {
-                OnyxAstNodeIf* if_node = (OnyxAstNodeIf *) block;
+            if (block->base.kind == AST_NODE_KIND_IF) {
+                AstNodeIf* if_node = (AstNodeIf *) block;
                 if (if_node->true_block)
-                    bh_arr_push(traversal_queue, (OnyxAstNodeBlock *) if_node->true_block);
+                    bh_arr_push(traversal_queue, (AstNodeBlock *) if_node->true_block);
 
                 if (if_node->false_block)
-                    bh_arr_push(traversal_queue, (OnyxAstNodeBlock *) if_node->false_block);
+                    bh_arr_push(traversal_queue, (AstNodeBlock *) if_node->false_block);
 
             } else {
 
                 if (block->scope != top_scope && block->scope->last_local != NULL) {
-                    OnyxAstNodeLocal* last_local = block->scope->last_local;
+                    AstNodeLocal* 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;
@@ -54,20 +54,20 @@ static void collapse_scopes(OnyxProgram* program) {
                     block->scope->last_local = NULL;
                 }
 
-                OnyxAstNode* walker = block->body;
+                AstNode* walker = block->body;
                 while (walker) {
-                    if (walker->kind == ONYX_AST_NODE_KIND_BLOCK) {
-                        bh_arr_push(traversal_queue, (OnyxAstNodeBlock *) walker);
+                    if (walker->kind == AST_NODE_KIND_BLOCK) {
+                        bh_arr_push(traversal_queue, (AstNodeBlock *) walker);
 
-                    } else if (walker->kind == ONYX_AST_NODE_KIND_WHILE) {
-                        bh_arr_push(traversal_queue, walker->as_while.body);
+                    } else if (walker->kind == AST_NODE_KIND_WHILE) {
+                        bh_arr_push(traversal_queue, ((AstNodeWhile *) walker)->body);
 
-                    } 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 == AST_NODE_KIND_IF) {
+                        if (((AstNodeIf *) walker)->true_block)
+                            bh_arr_push(traversal_queue, (AstNodeBlock *) ((AstNodeIf *) walker)->true_block);
 
-                        if (walker->as_if.false_block)
-                            bh_arr_push(traversal_queue, (OnyxAstNodeBlock *) walker->as_if.false_block);
+                        if (((AstNodeIf *) walker)->false_block)
+                            bh_arr_push(traversal_queue, (AstNodeBlock *) ((AstNodeIf *) walker)->false_block);
                     }
 
                     walker = walker->next;
index 37c39aea632baf025b97ebc760b538be14ed5549..32abbbb8a5880f0ef96661174c191a6d1e6c48be 100644 (file)
@@ -1,26 +1,26 @@
 #define BH_DEBUG
 #include "onyxsempass.h"
 
-static void symbol_introduce(OnyxSemPassState* state, OnyxAstNode* symbol);
-static b32 symbol_unique_introduce(OnyxSemPassState* state, OnyxAstNode* symbol);
-static void symbol_remove(OnyxSemPassState* state, OnyxAstNode* symbol);
-static OnyxAstNode* symbol_resolve(OnyxSemPassState* state, OnyxAstNode* symbol);
-static void scope_enter(OnyxSemPassState* state, OnyxAstNodeScope* scope);
-static OnyxAstNodeScope* scope_leave(OnyxSemPassState* state);
-static void symres_local(OnyxSemPassState* state, OnyxAstNodeLocal** local);
-static void symres_call(OnyxSemPassState* state, OnyxAstNode* call);
-static void symres_expression(OnyxSemPassState* state, OnyxAstNode** expr);
-static void symres_assignment(OnyxSemPassState* state, OnyxAstNode* assign);
-static void symres_return(OnyxSemPassState* state, OnyxAstNode* ret);
-static void symres_if(OnyxSemPassState* state, OnyxAstNodeIf* ifnode);
-static void symres_while(OnyxSemPassState* state, OnyxAstNodeWhile* whilenode);
-static void symres_statement_chain(OnyxSemPassState* state, OnyxAstNode* walker, OnyxAstNode** trailer);
-static b32 symres_statement(OnyxSemPassState* state, OnyxAstNode* stmt);
-static void symres_block(OnyxSemPassState* state, OnyxAstNodeBlock* block);
-static void symres_function(OnyxSemPassState* state, OnyxAstNodeFunction* func);
-
-static void symbol_introduce(OnyxSemPassState* state, OnyxAstNode* symbol) {
-    onyx_token_null_toggle(*symbol->token);
+static void symbol_introduce(OnyxSemPassState* state, AstNode* symbol);
+static b32 symbol_unique_introduce(OnyxSemPassState* state, AstNode* symbol);
+static void symbol_remove(OnyxSemPassState* state, AstNode* symbol);
+static AstNode* symbol_resolve(OnyxSemPassState* state, AstNode* symbol);
+static void scope_enter(OnyxSemPassState* state, AstNodeScope* scope);
+static AstNodeScope* scope_leave(OnyxSemPassState* state);
+static void symres_local(OnyxSemPassState* state, AstNodeLocal** local);
+static void symres_call(OnyxSemPassState* state, AstNodeCall* call);
+static void symres_expression(OnyxSemPassState* state, AstNode** expr);
+static void symres_assignment(OnyxSemPassState* state, AstNodeAssign* assign);
+static void symres_return(OnyxSemPassState* state, AstNodeReturn* ret);
+static void symres_if(OnyxSemPassState* state, AstNodeIf* ifnode);
+static void symres_while(OnyxSemPassState* state, AstNodeWhile* whilenode);
+static void symres_statement_chain(OnyxSemPassState* state, AstNode* walker, AstNode** trailer);
+static b32 symres_statement(OnyxSemPassState* state, AstNode* stmt);
+static void symres_block(OnyxSemPassState* state, AstNodeBlock* block);
+static void symres_function(OnyxSemPassState* state, AstNodeFunction* func);
+
+static void symbol_introduce(OnyxSemPassState* state, AstNode* symbol) {
+    onyx_token_null_toggle(symbol->token);
 
     SemPassSymbol* sp_sym = (SemPassSymbol *) bh_alloc_item(state->allocator, SemPassSymbol);
     sp_sym->node = symbol;
@@ -32,17 +32,17 @@ static void symbol_introduce(OnyxSemPassState* state, OnyxAstNode* symbol) {
 
     bh_table_put(SemPassSymbol *, state->symbols, symbol->token->token, sp_sym);
 
-    if (symbol->kind == ONYX_AST_NODE_KIND_LOCAL) {
-        OnyxAstNodeLocal* local = &symbol->as_local;
+    if (symbol->kind == AST_NODE_KIND_LOCAL) {
+        AstNodeLocal* local = (AstNodeLocal *) symbol;
         local->prev_local = state->curr_scope->last_local;
         state->curr_scope->last_local = local;
     }
 
-    onyx_token_null_toggle(*symbol->token);
+    onyx_token_null_toggle(symbol->token);
 }
 
-static void symbol_remove(OnyxSemPassState* state, OnyxAstNode* symbol) {
-    onyx_token_null_toggle(*symbol->token);
+static void symbol_remove(OnyxSemPassState* state, AstNode* symbol) {
+    onyx_token_null_toggle(symbol->token);
 
     SemPassSymbol* sp_sym = bh_table_get(SemPassSymbol *, state->symbols, symbol->token->token);
 
@@ -52,11 +52,11 @@ static void symbol_remove(OnyxSemPassState* state, OnyxAstNode* symbol) {
         bh_table_delete(SemPassSymbol *, state->symbols, symbol->token->token);
     }
 
-    onyx_token_null_toggle(*symbol->token);
+    onyx_token_null_toggle(symbol->token);
 }
 
-static OnyxAstNode* symbol_resolve(OnyxSemPassState* state, OnyxAstNode* symbol) {
-    onyx_token_null_toggle(*symbol->token);
+static AstNode* symbol_resolve(OnyxSemPassState* state, AstNode* symbol) {
+    onyx_token_null_toggle(symbol->token);
 
     if (!bh_table_has(SemPassSymbol *, state->symbols, symbol->token->token)) {
         onyx_message_add(state->msgs,
@@ -64,35 +64,35 @@ static OnyxAstNode* symbol_resolve(OnyxSemPassState* state, OnyxAstNode* symbol)
                 symbol->token->pos,
                 symbol->token->token);
 
-        onyx_token_null_toggle(*symbol->token);
+        onyx_token_null_toggle(symbol->token);
         return symbol;
     }
 
     SemPassSymbol* sp_sym = bh_table_get(SemPassSymbol *, state->symbols, symbol->token->token);
 
-    onyx_token_null_toggle(*symbol->token);
+    onyx_token_null_toggle(symbol->token);
     return sp_sym->node;
 }
 
-static void scope_enter(OnyxSemPassState* state, OnyxAstNodeScope* scope) {
+static void scope_enter(OnyxSemPassState* state, AstNodeScope* scope) {
     scope->prev_scope = state->curr_scope;
     state->curr_scope = scope;
 }
 
-static OnyxAstNodeScope* scope_leave(OnyxSemPassState* state) {
+static AstNodeScope* scope_leave(OnyxSemPassState* state) {
     // NOTE: Can't leave a scope if there is no scope
     assert(state->curr_scope != NULL);
 
-    for (OnyxAstNodeLocal *walker = state->curr_scope->last_local; walker != NULL; walker = walker->prev_local) {
-        symbol_remove(state, (OnyxAstNode *) walker);
+    for (AstNodeLocal *walker = state->curr_scope->last_local; walker != NULL; walker = walker->prev_local) {
+        symbol_remove(state, (AstNode *) walker);
     }
 
     state->curr_scope = state->curr_scope->prev_scope;
     return state->curr_scope;
 }
 
-static b32 symbol_unique_introduce(OnyxSemPassState* state, OnyxAstNode* symbol) {
-    onyx_token_null_toggle(*symbol->token);
+static b32 symbol_unique_introduce(OnyxSemPassState* state, AstNode* symbol) {
+    onyx_token_null_toggle(symbol->token);
 
     // NOTE: If the function hasn't already been defined
     if (!bh_table_has(SemPassSymbol *, state->symbols, symbol->token->token)) {
@@ -107,51 +107,49 @@ static b32 symbol_unique_introduce(OnyxSemPassState* state, OnyxAstNode* symbol)
                 symbol->token->token);
 
         // NOTE: I really wish C had defer...
-        onyx_token_null_toggle(*symbol->token);
+        onyx_token_null_toggle(symbol->token);
         return 0;
     }
 
-    onyx_token_null_toggle(*symbol->token);
+    onyx_token_null_toggle(symbol->token);
     return 1;
 }
 
-static void symres_local(OnyxSemPassState* state, OnyxAstNodeLocal** local) {
-    symbol_introduce(state, (OnyxAstNode *) *local);
+static void symres_local(OnyxSemPassState* state, AstNodeLocal** local) {
+    symbol_introduce(state, (AstNode *) *local);
 }
 
-static void symres_call(OnyxSemPassState* state, OnyxAstNode* stmt) {
-    OnyxAstNodeCall* call = &stmt->as_call;
-
-    OnyxAstNode* callee = symbol_resolve(state, call->callee);
+static void symres_call(OnyxSemPassState* state, AstNodeCall* call) {
+    AstNode* callee = symbol_resolve(state, call->callee);
     if (callee) call->callee = callee;
     else DEBUG_HERE;
 
-    symres_statement_chain(state, call->arguments, &call->arguments);
+    symres_statement_chain(state, (AstNode *) call->arguments, (AstNode **) &call->arguments);
 }
 
-static void symres_expression(OnyxSemPassState* state, OnyxAstNode** expr) {
+static void symres_expression(OnyxSemPassState* state, AstNode** expr) {
     switch ((*expr)->kind) {
-        case ONYX_AST_NODE_KIND_BIN_OP:
-            symres_expression(state, &(*expr)->left);
-            symres_expression(state, &(*expr)->right);
+        case AST_NODE_KIND_BIN_OP:
+            symres_expression(state, (AstNode **) &((AstNodeBinOp *)(*expr))->left);
+            symres_expression(state, (AstNode **) &((AstNodeBinOp *)(*expr))->right);
             break;
 
-        case ONYX_AST_NODE_KIND_UNARY_OP:
-            symres_expression(state, &(*expr)->left);
+        case AST_NODE_KIND_UNARY_OP:
+            symres_expression(state, (AstNode **) &((AstNodeUnaryOp *)(*expr))->expr);
             break;
 
-        case ONYX_AST_NODE_KIND_CALL: symres_call(state, *expr); break;
+        case AST_NODE_KIND_CALL: symres_call(state, (AstNodeCall *) *expr); break;
 
-        case ONYX_AST_NODE_KIND_BLOCK: symres_block(state, &(*expr)->as_block); break;
+        case AST_NODE_KIND_BLOCK: symres_block(state, (AstNodeBlock *) *expr); break;
 
-        case ONYX_AST_NODE_KIND_SYMBOL:
+        case AST_NODE_KIND_SYMBOL:
             *expr = symbol_resolve(state, *expr);
             break;
 
         // NOTE: This is a good case, since it means the symbol is already resolved
-        case ONYX_AST_NODE_KIND_LOCAL: break;
+        case AST_NODE_KIND_LOCAL: break;
 
-        case ONYX_AST_NODE_KIND_LITERAL: break;
+        case AST_NODE_KIND_LITERAL: break;
 
         default:
             DEBUG_HERE;
@@ -159,69 +157,69 @@ static void symres_expression(OnyxSemPassState* state, OnyxAstNode** expr) {
     }
 }
 
-static void symres_assignment(OnyxSemPassState* state, OnyxAstNode* assign) {
-    OnyxAstNode* lval = symbol_resolve(state, assign->left);
+static void symres_assignment(OnyxSemPassState* state, AstNodeAssign* assign) {
+    AstNodeTyped* lval = (AstNodeTyped *) symbol_resolve(state, (AstNode *) assign->lval);
     if (lval == NULL) return;
-    assign->left = lval;
+    assign->lval = lval;
 
-    symres_expression(state, &assign->right);
+    symres_expression(state, (AstNode **) &assign->expr);
 }
 
-static void symres_return(OnyxSemPassState* state, OnyxAstNode* ret) {
-    if (ret->left)
-        symres_expression(state, &ret->left);
+static void symres_return(OnyxSemPassState* state, AstNodeReturn* ret) {
+    if (ret->expr)
+        symres_expression(state, (AstNode **) &ret->expr);
 }
 
-static void symres_if(OnyxSemPassState* state, OnyxAstNodeIf* ifnode) {
-    symres_expression(state, &ifnode->cond);
+static void symres_if(OnyxSemPassState* state, AstNodeIf* ifnode) {
+    symres_expression(state, (AstNode **) &ifnode->cond);
     if (ifnode->true_block) {
-        if (ifnode->true_block->kind == ONYX_AST_NODE_KIND_BLOCK)
-            symres_block(state, &ifnode->true_block->as_block);
+        if (ifnode->true_block->kind == AST_NODE_KIND_BLOCK)
+            symres_block(state, (AstNodeBlock *) ifnode->true_block);
 
-        else if (ifnode->true_block->kind == ONYX_AST_NODE_KIND_IF)
-            symres_if(state, &ifnode->true_block->as_if);
+        else if (ifnode->true_block->kind == AST_NODE_KIND_IF)
+            symres_if(state, (AstNodeIf *) ifnode->true_block);
 
         else DEBUG_HERE;
     }
 
     if (ifnode->false_block) {
-        if (ifnode->false_block->kind == ONYX_AST_NODE_KIND_BLOCK)
-            symres_block(state, &ifnode->false_block->as_block);
+        if (ifnode->false_block->kind == AST_NODE_KIND_BLOCK)
+            symres_block(state, (AstNodeBlock *) ifnode->false_block);
 
-        else if (ifnode->false_block->kind == ONYX_AST_NODE_KIND_IF)
-            symres_if(state, &ifnode->false_block->as_if);
+        else if (ifnode->false_block->kind == AST_NODE_KIND_IF)
+            symres_if(state, (AstNodeIf *) ifnode->false_block);
 
         else DEBUG_HERE;
     }
 }
 
-static void symres_while(OnyxSemPassState* state, OnyxAstNodeWhile* whilenode) {
-    symres_expression(state, &whilenode->cond);
+static void symres_while(OnyxSemPassState* state, AstNodeWhile* whilenode) {
+    symres_expression(state, (AstNode **) &whilenode->cond);
     symres_block(state, whilenode->body);
 }
 
 // NOTE: Returns 1 if the statment should be removed
-static b32 symres_statement(OnyxSemPassState* state, OnyxAstNode* stmt) {
+static b32 symres_statement(OnyxSemPassState* state, AstNode* stmt) {
     switch (stmt->kind) {
-        case ONYX_AST_NODE_KIND_LOCAL:      symres_local(state, (OnyxAstNodeLocal **) &stmt);       return 1;
-        case ONYX_AST_NODE_KIND_ASSIGNMENT: symres_assignment(state, stmt);                         return 0;
-        case ONYX_AST_NODE_KIND_RETURN:     symres_return(state, stmt);                             return 0;
-        case ONYX_AST_NODE_KIND_IF:         symres_if(state, &stmt->as_if);                         return 0;
-        case ONYX_AST_NODE_KIND_WHILE:      symres_while(state, &stmt->as_while);                   return 0;
-        case ONYX_AST_NODE_KIND_CALL:       symres_call(state, stmt);                               return 0;
-        case ONYX_AST_NODE_KIND_ARGUMENT:   symres_expression(state, (OnyxAstNode **) &stmt->left); return 0;
-        case ONYX_AST_NODE_KIND_BLOCK:      symres_block(state, &stmt->as_block);                   return 0;
+        case AST_NODE_KIND_LOCAL:      symres_local(state, (AstNodeLocal **) &stmt);                return 1;
+        case AST_NODE_KIND_ASSIGNMENT: symres_assignment(state, (AstNodeAssign *) stmt);            return 0;
+        case AST_NODE_KIND_RETURN:     symres_return(state, (AstNodeReturn *) stmt);                return 0;
+        case AST_NODE_KIND_IF:         symres_if(state, (AstNodeIf *) stmt);                        return 0;
+        case AST_NODE_KIND_WHILE:      symres_while(state, (AstNodeWhile *) stmt);                 return 0;
+        case AST_NODE_KIND_CALL:       symres_call(state, (AstNodeCall *) stmt);                    return 0;
+        case AST_NODE_KIND_ARGUMENT:   symres_expression(state, (AstNode **) &((AstNodeArgument *)stmt)->value); return 0;
+        case AST_NODE_KIND_BLOCK:      symres_block(state, (AstNodeBlock *) stmt);                  return 0;
 
         default: return 0;
     }
 }
 
-static void symres_statement_chain(OnyxSemPassState* state, OnyxAstNode* walker, OnyxAstNode** trailer) {
+static void symres_statement_chain(OnyxSemPassState* state, AstNode* walker, AstNode** trailer) {
     while (walker) {
         if (symres_statement(state, walker)) {
             *trailer = walker->next;
 
-            OnyxAstNode* tmp = walker->next;
+            AstNode* tmp = walker->next;
             walker->next = NULL;
             walker = tmp;
         } else {
@@ -231,43 +229,43 @@ static void symres_statement_chain(OnyxSemPassState* state, OnyxAstNode* walker,
     }
 }
 
-static void symres_block(OnyxSemPassState* state, OnyxAstNodeBlock* block) {
+static void symres_block(OnyxSemPassState* state, AstNodeBlock* block) {
     scope_enter(state, block->scope);
     if (block->body)
         symres_statement_chain(state, block->body, &block->body);
     scope_leave(state);
 }
 
-static void symres_function(OnyxSemPassState* state, OnyxAstNodeFunction* func) {
-    forll(OnyxAstNodeParam, param, func->params, next) {
-        symbol_introduce(state, (OnyxAstNode *) param);
+static void symres_function(OnyxSemPassState* state, AstNodeFunction* func) {
+    for (AstNodeLocal *param = func->params; param != NULL; param = (AstNodeLocal *) param->base.next) {
+        symbol_introduce(state, (AstNode *) param);
     }
 
     symres_block(state, func->body);
 
-    forll(OnyxAstNodeParam, param, func->params, next) {
-        symbol_remove(state, (OnyxAstNode *) param);
+    for (AstNodeLocal *param = func->params; param != NULL; param = (AstNodeLocal *) param->base.next) {
+        symbol_remove(state, (AstNode *) param);
     }
 }
 
 void onyx_resolve_symbols(OnyxSemPassState* state, OnyxProgram* program) {
 
     // NOTE: First, introduce all global symbols
-    bh_arr_each(OnyxAstNodeGlobal *, global, program->globals)
-        if (!symbol_unique_introduce(state, (OnyxAstNode *) *global)) return;
+    bh_arr_each(AstNodeGlobal *, global, program->globals)
+        if (!symbol_unique_introduce(state, (AstNode *) *global)) return;
 
-    bh_arr_each(OnyxAstNodeFunction *, function, program->functions)
-        if (!symbol_unique_introduce(state, (OnyxAstNode *) *function)) return;
+    bh_arr_each(AstNodeFunction *, function, program->functions)
+        if (!symbol_unique_introduce(state, (AstNode *) *function)) return;
 
-    bh_arr_each(OnyxAstNodeForeign *, foreign, program->foreigns) {
-        OnyxAstNodeKind import_kind = (*foreign)->import->kind;
+    bh_arr_each(AstNodeForeign *, foreign, program->foreigns) {
+        AstNodeKind import_kind = (*foreign)->import->kind;
 
-        if (import_kind == ONYX_AST_NODE_KIND_FUNCTION || import_kind == ONYX_AST_NODE_KIND_GLOBAL)
+        if (import_kind == AST_NODE_KIND_FUNCTION || import_kind == AST_NODE_KIND_GLOBAL)
             if (!symbol_unique_introduce(state, (*foreign)->import)) return;
     }
 
 
     // NOTE: Then, resolve all symbols in all functions
-    bh_arr_each(OnyxAstNodeFunction *, function, program->functions)
+    bh_arr_each(AstNodeFunction *, function, program->functions)
         symres_function(state, *function);
 }
index 9d2f96e339b8ac274273c395b8d565f457105d63..1cc14cde91b378447c47e979a8ed82730f8058aa 100644 (file)
@@ -1,81 +1,81 @@
 #define BH_DEBUG
 #include "onyxsempass.h"
 
-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_assignment(OnyxSemPassState* state, OnyxAstNode* assign);
-static void typecheck_return(OnyxSemPassState* state, OnyxAstNode* retnode);
-static void typecheck_if(OnyxSemPassState* state, OnyxAstNodeIf* ifnode);
-static void typecheck_while(OnyxSemPassState* state, OnyxAstNodeWhile* whilenode);
-static void typecheck_call(OnyxSemPassState* state, OnyxAstNodeCall* call);
-static void typecheck_expression(OnyxSemPassState* state, OnyxAstNode* expr);
-static void typecheck_global(OnyxSemPassState* state, OnyxAstNodeGlobal* global);
-
-static void typecheck_assignment(OnyxSemPassState* state, OnyxAstNode* assign) {
-    if (assign->left->kind == ONYX_AST_NODE_KIND_SYMBOL) {
+static void typecheck_function(OnyxSemPassState* state, AstNodeFunction* func);
+static void typecheck_block(OnyxSemPassState* state, AstNodeBlock* block);
+static void typecheck_statement_chain(OnyxSemPassState* state, AstNode* start);
+static void typecheck_statement(OnyxSemPassState* state, AstNode* stmt);
+static void typecheck_assignment(OnyxSemPassState* state, AstNodeAssign* assign);
+static void typecheck_return(OnyxSemPassState* state, AstNodeReturn* retnode);
+static void typecheck_if(OnyxSemPassState* state, AstNodeIf* ifnode);
+static void typecheck_while(OnyxSemPassState* state, AstNodeWhile* whilenode);
+static void typecheck_call(OnyxSemPassState* state, AstNodeCall* call);
+static void typecheck_expression(OnyxSemPassState* state, AstNodeTyped* expr);
+static void typecheck_global(OnyxSemPassState* state, AstNodeGlobal* global);
+
+static void typecheck_assignment(OnyxSemPassState* state, AstNodeAssign* assign) {
+    if (assign->lval->kind == AST_NODE_KIND_SYMBOL) {
         onyx_message_add(state->msgs,
                 ONYX_MESSAGE_TYPE_UNRESOLVED_SYMBOL,
-                assign->left->token->pos,
-                assign->left->token->token, assign->left->token->length);
+                assign->lval->token->pos,
+                assign->lval->token->token, assign->lval->token->length);
         return;
     }
 
-    if ((assign->left->flags & ONYX_AST_FLAG_CONST) != 0 && assign->left->type->is_known) {
+    if ((assign->lval->flags & ONYX_AST_FLAG_CONST) != 0 && assign->lval->type->is_known) {
         onyx_message_add(state->msgs,
                 ONYX_MESSAGE_TYPE_ASSIGN_CONST,
-                assign->token->pos,
-                assign->left->token->token, assign->left->token->length);
+                assign->base.token->pos,
+                assign->lval->token->token, assign->lval->token->length);
         return;
     }
 
-    if ((assign->left->flags & ONYX_AST_FLAG_LVAL) == 0) {
+    if ((assign->lval->flags & ONYX_AST_FLAG_LVAL) == 0) {
         onyx_message_add(state->msgs,
                 ONYX_MESSAGE_TYPE_NOT_LVAL,
-                assign->token->pos,
-                assign->left->token->token, assign->left->token->length);
+                assign->base.token->pos,
+                assign->lval->token->token, assign->lval->token->length);
         return;
     }
 
-    typecheck_expression(state, assign->right);
+    typecheck_expression(state, assign->expr);
 
-    if (!assign->left->type->is_known) {
-        assign->left->type = assign->right->type;
+    if (!assign->lval->type->is_known) {
+        assign->lval->type = assign->expr->type;
     } else {
-        if (assign->left->type != assign->right->type) {
+        if (assign->lval->type != assign->expr->type) {
             onyx_message_add(state->msgs,
                     ONYX_MESSAGE_TYPE_ASSIGNMENT_TYPE_MISMATCH,
-                    assign->token->pos,
-                    assign->left->type->name, assign->right->type->name);
+                    assign->base.token->pos,
+                    assign->lval->type->name, assign->expr->type->name);
             return;
         }
     }
 }
 
-static void typecheck_return(OnyxSemPassState* state, OnyxAstNode* retnode) {
-    if (retnode->left) {
-        typecheck_expression(state, retnode->left);
+static void typecheck_return(OnyxSemPassState* state, AstNodeReturn* retnode) {
+    if (retnode->expr) {
+        typecheck_expression(state, retnode->expr);
 
-        if (retnode->left->type != state->expected_return_type) {
+        if (retnode->expr->type != state->expected_return_type) {
             onyx_message_add(state->msgs,
                     ONYX_MESSAGE_TYPE_FUNCTION_RETURN_MISMATCH,
-                    retnode->left->token->pos,
-                    retnode->left->type->name, state->expected_return_type->name);
+                    retnode->expr->token->pos,
+                    retnode->expr->type->name, state->expected_return_type->name);
         }
     } else {
         if (state->expected_return_type->size > 0) {
             onyx_message_add(state->msgs,
                     ONYX_MESSAGE_TYPE_LITERAL,
-                    retnode->token->pos,
+                    retnode->base.token->pos,
                     "returning from non-void function without value");
         }
     }
 }
 
-static void typecheck_if(OnyxSemPassState* state, OnyxAstNodeIf* ifnode) {
+static void typecheck_if(OnyxSemPassState* state, AstNodeIf* ifnode) {
     typecheck_expression(state, ifnode->cond);
-    if (ifnode->cond->type != &builtin_types[ONYX_TYPE_INFO_KIND_BOOL]) {
+    if (ifnode->cond->type != &builtin_types[TYPE_INFO_KIND_BOOL]) {
         onyx_message_add(state->msgs,
                 ONYX_MESSAGE_TYPE_LITERAL,
                 ifnode->cond->token->pos,
@@ -87,9 +87,9 @@ static void typecheck_if(OnyxSemPassState* state, OnyxAstNodeIf* ifnode) {
     if (ifnode->false_block) typecheck_statement(state, ifnode->false_block);
 }
 
-static void typecheck_while(OnyxSemPassState* state, OnyxAstNodeWhile* whilenode) {
+static void typecheck_while(OnyxSemPassState* state, AstNodeWhile* whilenode) {
     typecheck_expression(state, whilenode->cond);
-    if (whilenode->cond->type != &builtin_types[ONYX_TYPE_INFO_KIND_BOOL]) {
+    if (whilenode->cond->type != &builtin_types[TYPE_INFO_KIND_BOOL]) {
         onyx_message_add(state->msgs,
                 ONYX_MESSAGE_TYPE_LITERAL,
                 whilenode->cond->token->pos,
@@ -100,53 +100,53 @@ static void typecheck_while(OnyxSemPassState* state, OnyxAstNodeWhile* whilenode
     typecheck_block(state, whilenode->body);
 }
 
-static void typecheck_call(OnyxSemPassState* state, OnyxAstNodeCall* call) {
-    OnyxAstNodeFunction* callee = (OnyxAstNodeFunction *) call->callee;
+static void typecheck_call(OnyxSemPassState* state, AstNodeCall* call) {
+    AstNodeFunction* callee = (AstNodeFunction *) call->callee;
 
-    if (callee->kind == ONYX_AST_NODE_KIND_SYMBOL) {
+    if (callee->base.kind == AST_NODE_KIND_SYMBOL) {
         onyx_message_add(state->msgs,
                 ONYX_MESSAGE_TYPE_UNRESOLVED_SYMBOL,
-                callee->token->pos,
-                callee->token->token, callee->token->length);
+                callee->base.token->pos,
+                callee->base.token->token, callee->base.token->length);
         return;
     }
 
-    if (callee->kind != ONYX_AST_NODE_KIND_FUNCTION) {
+    if (callee->base.kind != AST_NODE_KIND_FUNCTION) {
         onyx_message_add(state->msgs,
                 ONYX_MESSAGE_TYPE_CALL_NON_FUNCTION,
-                call->token->pos,
-                callee->token->token, callee->token->length);
+                call->base.token->pos,
+                callee->base.token->token, callee->base.token->length);
         return;
     }
 
-    call->type = callee->return_type;
+    call->base.type = callee->base.type;
 
-    OnyxAstNodeParam* formal_param = callee->params;
-    OnyxAstNode* actual_param = call->arguments;
+    AstNodeLocal* formal_param = callee->params;
+    AstNodeArgument* actual_param = call->arguments;
 
     i32 arg_pos = 0;
     while (formal_param != NULL && actual_param != NULL) {
-        typecheck_expression(state, actual_param);
+        typecheck_expression(state, (AstNodeTyped *) actual_param);
 
-        if (formal_param->type != actual_param->type) {
+        if (formal_param->base.type != actual_param->base.type) {
             onyx_message_add(state->msgs,
                     ONYX_MESSAGE_TYPE_FUNCTION_PARAM_TYPE_MISMATCH,
-                    call->token->pos,
-                    callee->token->token, callee->token->length,
-                    formal_param->type->name, arg_pos,
-                    actual_param->type->name);
+                    call->base.token->pos,
+                    callee->base.token->token, callee->base.token->length,
+                    formal_param->base.type->name, arg_pos,
+                    actual_param->base.type->name);
             return;
         }
 
         arg_pos++;
-        formal_param = formal_param->next;
-        actual_param = actual_param->next;
+        formal_param = (AstNodeLocal *) formal_param->base.next;
+        actual_param = (AstNodeArgument *) actual_param->base.next;
     }
 
     if (formal_param != NULL && actual_param == NULL) {
         onyx_message_add(state->msgs,
                 ONYX_MESSAGE_TYPE_LITERAL,
-                call->token->pos,
+                call->base.token->pos,
                 "too few arguments to function call");
         return;
     }
@@ -154,21 +154,21 @@ static void typecheck_call(OnyxSemPassState* state, OnyxAstNodeCall* call) {
     if (formal_param == NULL && actual_param != NULL) {
         onyx_message_add(state->msgs,
                 ONYX_MESSAGE_TYPE_LITERAL,
-                call->token->pos,
+                call->base.token->pos,
                 "too many arguments to function call");
         return;
     }
 }
 
-static void typecheck_expression(OnyxSemPassState* state, OnyxAstNode* expr) {
+static void typecheck_expression(OnyxSemPassState* state, AstNodeTyped* expr) {
     switch (expr->kind) {
-        case ONYX_AST_NODE_KIND_BIN_OP:
-            expr->type = &builtin_types[ONYX_TYPE_INFO_KIND_UNKNOWN];
+        case AST_NODE_KIND_BIN_OP:
+            expr->type = &builtin_types[TYPE_INFO_KIND_UNKNOWN];
 
-            typecheck_expression(state, expr->left);
-            typecheck_expression(state, expr->right);
+            typecheck_expression(state, ((AstNodeBinOp *) expr)->left);
+            typecheck_expression(state, ((AstNodeBinOp *) expr)->right);
 
-            if (expr->left->type == NULL) {
+            if (((AstNodeBinOp *) expr)->left->type == NULL) {
                 onyx_message_add(state->msgs,
                         ONYX_MESSAGE_TYPE_UNRESOLVED_TYPE,
                         expr->token->pos,
@@ -176,7 +176,7 @@ static void typecheck_expression(OnyxSemPassState* state, OnyxAstNode* expr) {
                 return;
             }
 
-            if (expr->right->type == NULL) {
+            if (((AstNodeBinOp *) expr)->right->type == NULL) {
                 onyx_message_add(state->msgs,
                         ONYX_MESSAGE_TYPE_UNRESOLVED_TYPE,
                         expr->token->pos,
@@ -184,48 +184,48 @@ static void typecheck_expression(OnyxSemPassState* state, OnyxAstNode* expr) {
                 return;
             }
 
-            if (expr->left->type != expr->right->type) {
+            if (((AstNodeBinOp *) expr)->left->type != ((AstNodeBinOp *) expr)->right->type) {
                 onyx_message_add(state->msgs,
                         ONYX_MESSAGE_TYPE_BINOP_MISMATCH_TYPE,
                         expr->token->pos,
-                        expr->left->type->name,
-                        expr->right->type->name);
+                        ((AstNodeBinOp *) expr)->left->type->name,
+                        ((AstNodeBinOp *) expr)->right->type->name);
                 return;
             }
 
-            if (expr->as_binop.operation >= ONYX_BINARY_OP_EQUAL
-                    && expr->as_binop.operation <= ONYX_BINARY_OP_GREATER_EQUAL) {
-                expr->type = &builtin_types[ONYX_TYPE_INFO_KIND_BOOL];
+            if (((AstNodeBinOp *) expr)->operation >= ONYX_BINARY_OP_EQUAL
+                    && ((AstNodeBinOp *) expr)->operation <= ONYX_BINARY_OP_GREATER_EQUAL) {
+                expr->type = &builtin_types[TYPE_INFO_KIND_BOOL];
             } else {
-                expr->type = expr->left->type;
+                expr->type = ((AstNodeBinOp *) expr)->left->type;
             }
 
             break;
 
-        case ONYX_AST_NODE_KIND_UNARY_OP:
-            if (expr->as_unaryop.operation != ONYX_UNARY_OP_CAST) {
-                typecheck_expression(state, expr->left);
-                expr->type = expr->left->type;
+        case AST_NODE_KIND_UNARY_OP:
+            if (((AstNodeUnaryOp *) expr)->operation != ONYX_UNARY_OP_CAST) {
+                typecheck_expression(state, ((AstNodeUnaryOp *) expr)->expr);
+                expr->type = ((AstNodeUnaryOp *) expr)->expr->type;
             }
             break;
 
-        case ONYX_AST_NODE_KIND_CALL:
-            typecheck_call(state, &expr->as_call);
+        case AST_NODE_KIND_CALL:
+            typecheck_call(state, (AstNodeCall *) expr);
             break;
 
-        case ONYX_AST_NODE_KIND_BLOCK:
-            typecheck_block(state, &expr->as_block);
+        case AST_NODE_KIND_BLOCK:
+            typecheck_block(state, (AstNodeBlock *) expr);
             break;
 
-        case ONYX_AST_NODE_KIND_SYMBOL:
+        case AST_NODE_KIND_SYMBOL:
             onyx_message_add(state->msgs,
                     ONYX_MESSAGE_TYPE_UNRESOLVED_SYMBOL,
                     expr->token->pos,
                     expr->token->token, expr->token->length);
             break;
 
-        case ONYX_AST_NODE_KIND_LOCAL:
-        case ONYX_AST_NODE_KIND_PARAM:
+        case AST_NODE_KIND_LOCAL:
+        case AST_NODE_KIND_PARAM:
             if (!expr->type->is_known) {
                 onyx_message_add(state->msgs,
                         ONYX_MESSAGE_TYPE_LITERAL,
@@ -234,7 +234,7 @@ static void typecheck_expression(OnyxSemPassState* state, OnyxAstNode* expr) {
             }
             break;
 
-        case ONYX_AST_NODE_KIND_GLOBAL:
+        case AST_NODE_KIND_GLOBAL:
             if (!expr->type->is_known) {
                 onyx_message_add(state->msgs,
                         ONYX_MESSAGE_TYPE_LITERAL,
@@ -243,12 +243,12 @@ static void typecheck_expression(OnyxSemPassState* state, OnyxAstNode* expr) {
             }
             break;
 
-        case ONYX_AST_NODE_KIND_ARGUMENT:
-            typecheck_expression(state, expr->left);
-            expr->type = expr->left->type;
+        case AST_NODE_KIND_ARGUMENT:
+            typecheck_expression(state, ((AstNodeArgument *) expr)->value);
+            expr->type = ((AstNodeArgument *) expr)->value->type;
             break;
 
-        case ONYX_AST_NODE_KIND_LITERAL:
+        case AST_NODE_KIND_LITERAL:
             // NOTE: Literal types should have been decided
             // in the parser (for now).
             assert(expr->type->is_known);
@@ -260,88 +260,88 @@ static void typecheck_expression(OnyxSemPassState* state, OnyxAstNode* expr) {
     }
 }
 
-static void typecheck_global(OnyxSemPassState* state, OnyxAstNodeGlobal* global) {
+static void typecheck_global(OnyxSemPassState* state, AstNodeGlobal* global) {
     if (global->initial_value) {
         typecheck_expression(state, global->initial_value);
 
-        if (global->type->is_known) {
-            if (global->type != global->initial_value->type) {
+        if (global->base.type->is_known) {
+            if (global->base.type != global->initial_value->type) {
                 onyx_message_add(state->msgs,
                         ONYX_MESSAGE_TYPE_GLOBAL_TYPE_MISMATCH,
-                        global->token->pos,
-                        global->token->token, global->token->length,
-                        global->type->name, global->initial_value->type->name);
+                        global->base.token->pos,
+                        global->base.token->token, global->base.token->length,
+                        global->base.type->name, global->initial_value->type->name);
                 return;
             }
         } else {
             if (global->initial_value->type)
-                global->type = global->initial_value->type;
+                global->base.type = global->initial_value->type;
         }
 
     } else {
-        if (!global->type || !global->type->is_known) {
+        if (!global->base.type || !global->base.type->is_known) {
             onyx_message_add(state->msgs,
                     ONYX_MESSAGE_TYPE_LITERAL,
-                    global->token->pos,
+                    global->base.token->pos,
                     "global variable with unknown type");
         }
     }
 }
 
-static void typecheck_statement(OnyxSemPassState* state, OnyxAstNode* stmt) {
+static void typecheck_statement(OnyxSemPassState* state, AstNode* stmt) {
     switch (stmt->kind) {
-        case ONYX_AST_NODE_KIND_ASSIGNMENT: typecheck_assignment(state, stmt); break;
-        case ONYX_AST_NODE_KIND_RETURN:     typecheck_return(state, stmt); break;
-        case ONYX_AST_NODE_KIND_IF:         typecheck_if(state, &stmt->as_if); break;
-        case ONYX_AST_NODE_KIND_WHILE:      typecheck_while(state, &stmt->as_while); break;
-        case ONYX_AST_NODE_KIND_CALL:       typecheck_call(state, &stmt->as_call); break;
-        case ONYX_AST_NODE_KIND_BLOCK:      typecheck_block(state, &stmt->as_block); break;
+        case AST_NODE_KIND_ASSIGNMENT: typecheck_assignment(state, (AstNodeAssign *) stmt); break;
+        case AST_NODE_KIND_RETURN:     typecheck_return(state, (AstNodeReturn *) stmt); break;
+        case AST_NODE_KIND_IF:         typecheck_if(state, (AstNodeIf *) stmt); break;
+        case AST_NODE_KIND_WHILE:      typecheck_while(state, (AstNodeWhile *) stmt); break;
+        case AST_NODE_KIND_CALL:       typecheck_call(state, (AstNodeCall *) stmt); break;
+        case AST_NODE_KIND_BLOCK:      typecheck_block(state, (AstNodeBlock *) stmt); break;
 
         default: break;
     }
 }
 
-static void typecheck_statement_chain(OnyxSemPassState* state, OnyxAstNode* start) {
+static void typecheck_statement_chain(OnyxSemPassState* state, AstNode* start) {
     while (start) {
         typecheck_statement(state, start);
         start = start->next;
     }
 }
 
-static void typecheck_block(OnyxSemPassState* state, OnyxAstNodeBlock* block) {
+static void typecheck_block(OnyxSemPassState* state, AstNodeBlock* block) {
     typecheck_statement_chain(state, block->body);
 
-    forll(OnyxAstNodeLocal, local, block->scope->last_local, prev_local) {
-        if (!local->type->is_known) {
+    forll(AstNodeLocal, local, block->scope->last_local, prev_local) {
+        if (!local->base.type->is_known) {
             onyx_message_add(state->msgs,
                     ONYX_MESSAGE_TYPE_UNRESOLVED_TYPE,
-                    local->token->pos,
-                    local->token->token, local->token->length);
+                    local->base.token->pos,
+                    local->base.token->token, local->base.token->length);
             return;
         }
     }
 }
 
-static void typecheck_function(OnyxSemPassState* state, OnyxAstNodeFunction* func) {
-    forll(OnyxAstNodeParam, param, func->params, next) {
-        if (!param->type->is_known) {
+static void typecheck_function(OnyxSemPassState* state, AstNodeFunction* func) {
+    for (AstNodeLocal *param = func->params; param != NULL; param = (AstNodeLocal *) param->base.next) {
+        if (!param->base.type->is_known) {
             onyx_message_add(state->msgs,
                     ONYX_MESSAGE_TYPE_LITERAL,
-                    param->token->pos,
+                    param->base.token->pos,
                     "function parameter types must be known");
             return;
         }
 
-        if (param->type->size == 0) {
+        if (param->base.type->size == 0) {
             onyx_message_add(state->msgs,
                     ONYX_MESSAGE_TYPE_LITERAL,
-                    param->token->pos,
+                    param->base.token->pos,
                     "function parameters must have non-void types");
             return;
         }
     }
 
-    state->expected_return_type = func->return_type;
+    state->expected_return_type = func->base.type;
     if (func->body) {
         typecheck_block(state, func->body);
     }
@@ -349,9 +349,9 @@ static void typecheck_function(OnyxSemPassState* state, OnyxAstNodeFunction* fun
 
 void onyx_type_check(OnyxSemPassState* state, OnyxProgram* program) {
 
-    bh_arr_each(OnyxAstNodeGlobal *, global, program->globals)
+    bh_arr_each(AstNodeGlobal *, global, program->globals)
         typecheck_global(state, *global);
 
-    bh_arr_each(OnyxAstNodeFunction *, function, program->functions)
+    bh_arr_each(AstNodeFunction *, function, program->functions)
         typecheck_function(state, *function);
 }
index 207260262a955453a4923ec7397546899ebead97..b5537cb4d2ea605365f7cad33a5021255af1e9ed 100644 (file)
@@ -10,208 +10,182 @@ bh_allocator global_heap_allocator;
 
 #define print_indent { if (indent > 0) bh_printf("\n"); for (int i = 0; i < indent; i++) bh_printf("  "); }
 
-void onyx_ast_print(OnyxAstNode* node, i32 indent) {
-    if (node == NULL) return;
-
-    print_indent;
-    bh_printf("(%d) %s ", node->flags, onyx_ast_node_kind_string(node->kind));
-
-    switch (node->kind) {
-    case ONYX_AST_NODE_KIND_USE: {
-         OnyxAstNodeUse* use_node = &node->as_use;
-         bh_printf("%b", use_node->filename->token, use_node->filename->length);
-
-         if (use_node->next)
-             onyx_ast_print(use_node->next, indent);
-
-         break;
-     }
-
-    case ONYX_AST_NODE_KIND_FUNCTION: {
-        if (node->token)
-            bh_printf("(%b) ", node->token->token, node->token->length);
-        OnyxAstNodeFunction* fd = &node->as_function;
-
+void onyx_ast_print(AstNode* node, i32 indent) {
+    while (node) {
         print_indent;
-        bh_printf("Params ");
-        if (fd->params)
-            onyx_ast_print((OnyxAstNode *) fd->params, 0);
+        bh_printf("(%d) %s ", node->flags, onyx_ast_node_kind_string(node->kind));
 
-        print_indent;
-        bh_printf("Returns %s", fd->return_type->name);
+        switch (node->kind) {
+        case AST_NODE_KIND_USE: {
+             AstNodeUse* use_node = (AstNodeUse *) node;
+             bh_printf("%b", use_node->filename->token, use_node->filename->length);
 
-        print_indent;
-        bh_printf("Body");
-        if (fd->body)
-            onyx_ast_print((OnyxAstNode *) fd->body, indent + 1);
+             break;
+         }
 
-        if (fd->next)
-            onyx_ast_print((OnyxAstNode *) fd->next, indent);
+        case AST_NODE_KIND_FUNCTION: {
+            if (node->token)
+                bh_printf("(%b) ", node->token->token, node->token->length);
+            AstNodeFunction* fd = (AstNodeFunction *) node;
 
-        break;
-    }
+            print_indent;
+            bh_printf("Params ");
+            if (fd->params)
+                onyx_ast_print((AstNode *) fd->params, 0);
 
-    case ONYX_AST_NODE_KIND_PARAM: {
-        OnyxAstNodeParam* param = &node->as_param;
-        bh_printf("%b %s", param->token->token, param->token->length, param->type->name);
-        if (param->next && indent == 0) {
-            bh_printf(", ");
-            onyx_ast_print((OnyxAstNode *) param->next, 0);
-        }
+            print_indent;
+            bh_printf("Returns %s", fd->base.type->name);
 
-        break;
-    }
+            print_indent;
+            bh_printf("Body");
+            if (fd->body)
+                onyx_ast_print((AstNode *) fd->body, indent + 1);
 
-    case ONYX_AST_NODE_KIND_BLOCK: {
-        OnyxAstNodeBlock* block = &node->as_block;
-        if (block->scope) {
-            onyx_ast_print((OnyxAstNode *) block->scope, indent + 1);
+            break;
         }
 
-        if (block->body) {
-            onyx_ast_print((OnyxAstNode *) block->body, indent + 1);
-        }
+        case AST_NODE_KIND_PARAM: {
+            AstNodeLocal* param = (AstNodeLocal *) node;
+            bh_printf("%b %s", param->base.token->token, param->base.token->length, param->base.type->name);
+            if (param->base.next && indent == 0) {
+                bh_printf(", ");
+                onyx_ast_print((AstNode *) param->base.next, 0);
+            }
 
-        if (block->next) {
-            onyx_ast_print(block->next, indent);
+            return;
         }
 
-        break;
-    }
+        case AST_NODE_KIND_BLOCK: {
+            AstNodeBlock* block = (AstNodeBlock *) node;
+            if (block->scope) {
+                onyx_ast_print((AstNode *) block->scope, indent + 1);
+            }
 
-    case ONYX_AST_NODE_KIND_SCOPE: {
-        OnyxAstNodeScope* scope = &node->as_scope;
-        if (scope->last_local) {
-            onyx_ast_print((OnyxAstNode *) scope->last_local, 0);
+            if (block->body) {
+                onyx_ast_print((AstNode *) block->body, indent + 1);
+            }
+
+            break;
         }
 
-        break;
-    }
+        case AST_NODE_KIND_SCOPE: {
+            AstNodeScope* scope = (AstNodeScope *) scope;
+            if (scope->last_local) {
+                onyx_ast_print((AstNode *) scope->last_local, 0);
+            }
 
-    case ONYX_AST_NODE_KIND_LOCAL: {
-        OnyxAstNodeLocal* local = &node->as_local;
-        bh_printf("%b %s", local->token->token, local->token->length, local->type->name);
-        if (local->prev_local && indent == 0) {
-            bh_printf(", ");
-            onyx_ast_print((OnyxAstNode *) local->prev_local, 0);
-        } else if (local->next && indent != 0) {
-            onyx_ast_print(local->next, indent);
+            break;
         }
-        break;
-    }
 
-    case ONYX_AST_NODE_KIND_GLOBAL: {
-        OnyxAstNodeGlobal* global = &node->as_global;
-        bh_printf("%b %s", global->token->token, global->token->length, global->type->name);
-        if (global->initial_value) {
-            onyx_ast_print(global->initial_value, indent + 1);
+        case AST_NODE_KIND_LOCAL: {
+            AstNodeLocal* local = (AstNodeLocal *) node;
+            bh_printf("%b %s", local->base.token->token, local->base.token->length, local->base.type->name);
+            if (local->prev_local && indent == 0) {
+                bh_printf(", ");
+                onyx_ast_print((AstNode *) local->prev_local, 0);
+            }
+            break;
         }
 
-        if (node->next) {
-            onyx_ast_print(node->next, indent);
+        case AST_NODE_KIND_GLOBAL: {
+            AstNodeGlobal* global = (AstNodeGlobal *) node;
+            bh_printf("%b %s", global->base.token->token, global->base.token->length, global->base.type->name);
+            if (global->initial_value) {
+                onyx_ast_print((AstNode *) global->initial_value, indent + 1);
+            }
+
+            if (node->next) {
+                onyx_ast_print(node->next, indent);
+            }
+            break;
         }
-        break;
-    }
 
-    case ONYX_AST_NODE_KIND_SYMBOL: {
-        bh_printf("%b", node->token->token, node->token->length);
-        if (node->next) {
-            onyx_ast_print(node->next, indent);
+        case AST_NODE_KIND_SYMBOL: {
+            bh_printf("%b", node->token->token, node->token->length);
+            if (node->next) {
+                onyx_ast_print(node->next, indent);
+            }
+            break;
         }
-        break;
-    }
 
-    case ONYX_AST_NODE_KIND_RETURN: {
-        if (node->left) {
-            onyx_ast_print(node->left, indent + 1);
+        case AST_NODE_KIND_RETURN: {
+            AstNodeReturn* ret = (AstNodeReturn *) node;
+            if (ret->expr) {
+                onyx_ast_print((AstNode *) ret->expr, indent + 1);
+            }
+
+            break;
         }
 
-        break;
-    }
+        case AST_NODE_KIND_LITERAL: {
+            AstNodeNumLit* lit = (AstNodeNumLit *) node;
+            bh_printf("(%s) %b", lit->base.type->name, lit->base.token->token, lit->base.token->length);
 
-    case ONYX_AST_NODE_KIND_LITERAL: {
-        bh_printf("(%s) %b", node->type->name, node->token->token, node->token->length);
-        if (node->next) {
-            onyx_ast_print(node->next, indent);
+            break;
         }
-        break;
-    }
 
-    case ONYX_AST_NODE_KIND_CALL: {
-        OnyxAstNodeCall* call = &node->as_call;
-        if (call->callee) {
-            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);
+        case AST_NODE_KIND_CALL: {
+            AstNodeCall* call = (AstNodeCall *) node;
+            if (call->callee) {
+                if (call->callee->kind == AST_NODE_KIND_FUNCTION) {
+                    bh_printf("function: %b", call->callee->token->token, call->callee->token->length);
+                } else {
+                    onyx_ast_print(call->callee, indent + 1);
+                }
             }
+            onyx_ast_print((AstNode *) call->arguments, indent + 1);
+
+            break;
         }
-        onyx_ast_print(call->arguments, indent + 1);
-        if (call->next) {
-            onyx_ast_print(call->next, indent);
-        }
-        break;
-    }
 
-    case ONYX_AST_NODE_KIND_FOREIGN: {
-        OnyxAstNodeForeign* foreign = &node->as_foreign;
-        bh_printf("%b:%b",
-                foreign->mod_token->token, foreign->mod_token->length,
-                foreign->name_token->token, foreign->name_token->length);
+        case AST_NODE_KIND_FOREIGN: {
+            AstNodeForeign* foreign = (AstNodeForeign *) node;
+            bh_printf("%b:%b",
+                    foreign->mod_token->token, foreign->mod_token->length,
+                    foreign->name_token->token, foreign->name_token->length);
 
-        if (foreign->import) {
-            onyx_ast_print(foreign->import, indent + 1);
-        }
+            if (foreign->import) {
+                onyx_ast_print(foreign->import, indent + 1);
+            }
 
-        if (foreign->next) {
-            onyx_ast_print(foreign->next, indent);
+            break;
         }
-        break;
-    }
 
-    case ONYX_AST_NODE_KIND_IF: {
-        OnyxAstNodeIf* if_node = &node->as_if;
-        if (if_node->cond) {
-            print_indent;
-            bh_printf("Condition:");
-            onyx_ast_print(if_node->cond, indent + 1);
-        }
-        if (if_node->true_block) {
-            print_indent;
-            bh_printf("True block:");
-            onyx_ast_print(if_node->true_block, indent + 1);
-        }
-        if (if_node->false_block) {
-            print_indent;
-            bh_printf("False block:");
-            onyx_ast_print(if_node->false_block, indent + 1);
-        }
-        if (if_node->next) {
-            onyx_ast_print(if_node->next, indent);
+        case AST_NODE_KIND_IF: {
+            AstNodeIf* if_node = (AstNodeIf *) node;
+            if (if_node->cond) {
+                print_indent;
+                bh_printf("Condition:");
+                onyx_ast_print((AstNode *) if_node->cond, indent + 1);
+            }
+            if (if_node->true_block) {
+                print_indent;
+                bh_printf("True block:");
+                onyx_ast_print(if_node->true_block, indent + 1);
+            }
+            if (if_node->false_block) {
+                print_indent;
+                bh_printf("False block:");
+                onyx_ast_print(if_node->false_block, indent + 1);
+            }
+
+            break;
         }
-        break;
-    }
 
-    case ONYX_AST_NODE_KIND_BIN_OP: {
-        OnyxAstNodeBinOp* binop = &node->as_binop;
-        bh_printf("%b", binop->token->token, binop->token->length);
+        case AST_NODE_KIND_BIN_OP: {
+            AstNodeBinOp* binop = (AstNodeBinOp *) node;
+            bh_printf("%b", binop->base.token->token, binop->base.token->length);
 
-        onyx_ast_print(node->left, indent + 1);
-        onyx_ast_print(node->right, indent + 1);
-        if (node->next) {
-            onyx_ast_print(node->next, indent);
-        }
+            onyx_ast_print((AstNode *) binop->left, indent + 1);
+            onyx_ast_print((AstNode *) binop->right, indent + 1);
 
-        break;
-    }
+            break;
+        }
 
-    default: {
-        onyx_ast_print(node->left, indent + 1);
-        onyx_ast_print(node->right, indent + 1);
-        if (node->next) {
-            onyx_ast_print(node->next, indent);
+        default:
+            break;
         }
-        break;
-    }
+
+        node = node->next;
     }
 }
index 206883f2e2fc75186cb96956d3eef6f8cad674b5..f87965568b0f2a8f225151dd47d841583c7faa6b 100644 (file)
@@ -195,7 +195,7 @@ static const char* wi_string(WasmInstructionType wit) {
     }
 }
 
-static WasmType onyx_type_to_wasm_type(OnyxTypeInfo* type) {
+static WasmType onyx_type_to_wasm_type(TypeInfo* type) {
     if (type->is_bool) return WASM_TYPE_INT32;
     else if (type->is_int) {
         if (type->size == 4) return WASM_TYPE_INT32;
@@ -209,25 +209,25 @@ static WasmType onyx_type_to_wasm_type(OnyxTypeInfo* type) {
     return WASM_TYPE_VOID;
 }
 
-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_assignment(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNode* assign);
-static void compile_if(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNodeIf* if_node);
-static void compile_while(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNodeWhile* while_node);
-static void compile_binop(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNodeBinOp* binop);
-static void compile_unaryop(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNodeUnaryOp* unop);
-static void compile_expression(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNode* expr);
-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, OnyxAstNodeFunction* fd) {
+static void compile_function_body(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeFunction* fd);
+static void compile_block(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeBlock* block);
+static void compile_statement(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNode* stmt);
+static void compile_assign_lval(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeTyped* lval);
+static void compile_assignment(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeAssign* assign);
+static void compile_if(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeIf* if_node);
+static void compile_while(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeWhile* while_node);
+static void compile_binop(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeBinOp* binop);
+static void compile_unaryop(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeUnaryOp* unop);
+static void compile_expression(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeTyped* expr);
+static void compile_cast(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeUnaryOp* cast);
+static void compile_return(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeReturn* ret);
+
+static void compile_function_body(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeFunction* fd) {
     if (fd->body == NULL) return;
 
     bh_arr(WasmInstruction) code = *pcode;
 
-    forll (OnyxAstNode, stmt, fd->body->body, next) {
+    forll (AstNode, stmt, fd->body->body, next) {
         compile_statement(mod, &code, stmt);
     }
 
@@ -236,12 +236,12 @@ static void compile_function_body(OnyxWasmModule* mod, bh_arr(WasmInstruction)*
     *pcode = code;
 }
 
-static void compile_block(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNodeBlock* block) {
+static void compile_block(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeBlock* block) {
     bh_arr(WasmInstruction) code = *pcode;
 
     bh_arr_push(code, ((WasmInstruction){ WI_BLOCK_START, 0x40 }));
 
-    forll (OnyxAstNode, stmt, block->body, next) {
+    forll (AstNode, stmt, block->body, next) {
         compile_statement(mod, &code, stmt);
     }
 
@@ -276,19 +276,19 @@ static void compile_structured_jump(OnyxWasmModule* mod, bh_arr(WasmInstruction)
     *pcode = code;
 }
 
-static void compile_statement(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNode* stmt) {
+static void compile_statement(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNode* stmt) {
     bh_arr(WasmInstruction) code = *pcode;
 
     switch (stmt->kind) {
-        case ONYX_AST_NODE_KIND_SCOPE: break;
-        case ONYX_AST_NODE_KIND_RETURN: compile_return(mod, &code, stmt); break;
-        case ONYX_AST_NODE_KIND_ASSIGNMENT: compile_assignment(mod, &code, stmt); break;
-        case ONYX_AST_NODE_KIND_IF: compile_if(mod, &code, (OnyxAstNodeIf *) stmt); break;
-        case ONYX_AST_NODE_KIND_WHILE: compile_while(mod, &code, (OnyxAstNodeWhile *) stmt); break;
-        case ONYX_AST_NODE_KIND_BREAK: compile_structured_jump(mod, &code, 0); break;
-        case ONYX_AST_NODE_KIND_CONTINUE: compile_structured_jump(mod, &code, 1); break;
-        case ONYX_AST_NODE_KIND_CALL: compile_expression(mod, &code, stmt); break;
-        case ONYX_AST_NODE_KIND_BLOCK: compile_block(mod, &code, (OnyxAstNodeBlock *) stmt); break;
+        case AST_NODE_KIND_SCOPE: break;
+        case AST_NODE_KIND_RETURN: compile_return(mod, &code, (AstNodeReturn *) stmt); break;
+        case AST_NODE_KIND_ASSIGNMENT: compile_assignment(mod, &code, (AstNodeAssign *) stmt); break;
+        case AST_NODE_KIND_IF: compile_if(mod, &code, (AstNodeIf *) stmt); break;
+        case AST_NODE_KIND_WHILE: compile_while(mod, &code, (AstNodeWhile *) stmt); break;
+        case AST_NODE_KIND_BREAK: compile_structured_jump(mod, &code, 0); break;
+        case AST_NODE_KIND_CONTINUE: compile_structured_jump(mod, &code, 1); break;
+        case AST_NODE_KIND_CALL: compile_expression(mod, &code, (AstNodeTyped *) stmt); break;
+        case AST_NODE_KIND_BLOCK: compile_block(mod, &code, (AstNodeBlock *) stmt); break;
 
         default: break;
     }
@@ -296,15 +296,15 @@ static void compile_statement(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcod
     *pcode = code;
 }
 
-static void compile_assign_lval(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNode* lval) {
+static void compile_assign_lval(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeTyped* lval) {
     bh_arr(WasmInstruction) code = *pcode;
 
-    if (lval->kind == ONYX_AST_NODE_KIND_LOCAL || lval->kind == ONYX_AST_NODE_KIND_PARAM) {
+    if (lval->kind == AST_NODE_KIND_LOCAL || lval->kind == AST_NODE_KIND_PARAM) {
         i32 localidx = (i32) bh_imap_get(&mod->local_map, (u64) lval);
 
         bh_arr_push(code, ((WasmInstruction){ WI_LOCAL_SET, localidx }));
 
-    } else if (lval->kind == ONYX_AST_NODE_KIND_GLOBAL) {
+    } else if (lval->kind == AST_NODE_KIND_GLOBAL) {
         i32 globalidx = (i32) bh_imap_get(&mod->global_map, (u64) lval);
 
         bh_arr_push(code, ((WasmInstruction){ WI_GLOBAL_SET, globalidx }));
@@ -316,7 +316,7 @@ static void compile_assign_lval(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pc
     *pcode = code;
 }
 
-static void compile_if(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNodeIf* if_node) {
+static void compile_if(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeIf* if_node) {
     bh_arr(WasmInstruction) code = *pcode;
 
     compile_expression(mod, &code, if_node->cond);
@@ -327,12 +327,12 @@ static void compile_if(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, Onyx
     if (if_node->true_block) {
         // NOTE: This is kind of gross, but making a function for this doesn't feel right
 
-        if (if_node->true_block->kind == ONYX_AST_NODE_KIND_IF) {
-            forll (OnyxAstNode, stmt, if_node->true_block, next) {
+        if (if_node->true_block->kind == AST_NODE_KIND_IF) {
+            forll (AstNode, stmt, if_node->true_block, next) {
                 compile_statement(mod, &code, stmt);
             }
-        } else if (if_node->true_block->kind == ONYX_AST_NODE_KIND_BLOCK) {
-            forll (OnyxAstNode, stmt, if_node->true_block->as_block.body, next) {
+        } else if (if_node->true_block->kind == AST_NODE_KIND_BLOCK) {
+            forll (AstNode, stmt, ((AstNodeBlock *) if_node->true_block)->body, next) {
                 compile_statement(mod, &code, stmt);
             }
         }
@@ -341,12 +341,12 @@ static void compile_if(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, Onyx
     if (if_node->false_block) {
         bh_arr_push(code, ((WasmInstruction){ WI_ELSE, 0x00 }));
 
-        if (if_node->false_block->kind == ONYX_AST_NODE_KIND_IF) {
-            forll (OnyxAstNode, stmt, if_node->false_block, next) {
+        if (if_node->false_block->kind == AST_NODE_KIND_IF) {
+            forll (AstNode, stmt, if_node->false_block, next) {
                 compile_statement(mod, &code, stmt);
             }
-        } else if (if_node->false_block->kind == ONYX_AST_NODE_KIND_BLOCK) {
-            forll (OnyxAstNode, stmt, if_node->false_block->as_block.body, next) {
+        } else if (if_node->false_block->kind == AST_NODE_KIND_BLOCK) {
+            forll (AstNode, stmt, ((AstNodeBlock *) if_node->false_block)->body, next) {
                 compile_statement(mod, &code, stmt);
             }
         }
@@ -359,7 +359,7 @@ static void compile_if(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, Onyx
     *pcode = code;
 }
 
-static void compile_while(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNodeWhile* while_node) {
+static void compile_while(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeWhile* while_node) {
     bh_arr(WasmInstruction) code = *pcode;
 
     bh_arr_push(code, ((WasmInstruction){ WI_BLOCK_START, 0x40 }));
@@ -372,7 +372,7 @@ static void compile_while(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, O
     bh_arr_push(mod->structured_jump_target, 1);
     bh_arr_push(mod->structured_jump_target, 2);
 
-    forll (OnyxAstNode, stmt, while_node->body->body, next) {
+    forll (AstNode, stmt, while_node->body->body, next) {
         compile_statement(mod, &code, stmt);
     }
 
@@ -387,11 +387,11 @@ static void compile_while(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, O
     *pcode = code;
 }
 
-static void compile_assignment(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNode* assign) {
+static void compile_assignment(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeAssign* assign) {
     bh_arr(WasmInstruction) code = *pcode;
 
-    compile_expression(mod, &code, assign->right);
-    compile_assign_lval(mod, &code, assign->left);
+    compile_expression(mod, &code, assign->expr);
+    compile_assign_lval(mod, &code, assign->lval);
 
     *pcode = code;
 }
@@ -414,7 +414,7 @@ static const WasmInstructionType binop_map[][4] = {
     /* GTE */ { WI_I32_GE_S,  WI_I64_GE_S,  WI_F32_GE,  WI_F64_GE },
 };
 
-static void compile_binop(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNodeBinOp* binop) {
+static void compile_binop(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeBinOp* binop) {
     bh_arr(WasmInstruction) code = *pcode;
 
     b32 is_sign_significant = 0;
@@ -461,31 +461,31 @@ static void compile_binop(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, O
     *pcode = code;
 }
 
-static void compile_unaryop(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNodeUnaryOp* unop) {
+static void compile_unaryop(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeUnaryOp* unop) {
     bh_arr(WasmInstruction) code = *pcode;
 
     switch (unop->operation) {
         case ONYX_UNARY_OP_NEGATE:
             {
-                OnyxTypeInfoKind type_kind = unop->type->kind;
+                TypeInfoKind type_kind = unop->base.type->kind;
 
-                if (type_kind == ONYX_TYPE_INFO_KIND_INT32) {
+                if (type_kind == TYPE_INFO_KIND_INT32) {
                     bh_arr_push(code, ((WasmInstruction){ WI_I32_CONST, 0x00 }));
-                    compile_expression(mod, &code, unop->left);
+                    compile_expression(mod, &code, unop->expr);
                     bh_arr_push(code, ((WasmInstruction){ WI_I32_SUB, 0x00 }));
 
-                } else if (type_kind == ONYX_TYPE_INFO_KIND_INT64) {
+                } else if (type_kind == TYPE_INFO_KIND_INT64) {
                     bh_arr_push(code, ((WasmInstruction){ WI_I64_CONST, 0x00 }));
-                    compile_expression(mod, &code, unop->left);
+                    compile_expression(mod, &code, unop->expr);
                     bh_arr_push(code, ((WasmInstruction){ WI_I64_SUB, 0x00 }));
 
                 } else {
-                    compile_expression(mod, &code, unop->left);
+                    compile_expression(mod, &code, unop->expr);
 
-                    if (type_kind == ONYX_TYPE_INFO_KIND_FLOAT32)
+                    if (type_kind == TYPE_INFO_KIND_FLOAT32)
                         bh_arr_push(code, ((WasmInstruction){ WI_F32_NEG, 0x00 }));
 
-                    if (type_kind == ONYX_TYPE_INFO_KIND_FLOAT64)
+                    if (type_kind == TYPE_INFO_KIND_FLOAT64)
                         bh_arr_push(code, ((WasmInstruction){ WI_F32_NEG, 0x00 }));
                 }
 
@@ -493,7 +493,7 @@ static void compile_unaryop(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode,
             }
 
         case ONYX_UNARY_OP_NOT:
-            compile_expression(mod, &code, unop->left);
+            compile_expression(mod, &code, unop->expr);
             bh_arr_push(code, ((WasmInstruction){ WI_I32_EQZ, 0x00 }));
             break;
 
@@ -503,20 +503,20 @@ static void compile_unaryop(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode,
     *pcode = code;
 }
 
-static void compile_expression(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNode* expr) {
+static void compile_expression(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeTyped* expr) {
     bh_arr(WasmInstruction) code = *pcode;
 
     switch (expr->kind) {
-        case ONYX_AST_NODE_KIND_BIN_OP:
-            compile_binop(mod, &code, &expr->as_binop);
+        case AST_NODE_KIND_BIN_OP:
+            compile_binop(mod, &code, (AstNodeBinOp *) expr);
             break;
 
-        case ONYX_AST_NODE_KIND_UNARY_OP:
-            compile_unaryop(mod, &code, &expr->as_unaryop);
+        case AST_NODE_KIND_UNARY_OP:
+            compile_unaryop(mod, &code, (AstNodeUnaryOp *) expr);
             break;
 
-        case ONYX_AST_NODE_KIND_LOCAL:
-        case ONYX_AST_NODE_KIND_PARAM:
+        case AST_NODE_KIND_LOCAL:
+        case AST_NODE_KIND_PARAM:
             {
                 i32 localidx = (i32) bh_imap_get(&mod->local_map, (u64) expr);
 
@@ -524,7 +524,7 @@ static void compile_expression(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pco
                 break;
             }
 
-        case ONYX_AST_NODE_KIND_GLOBAL:
+        case AST_NODE_KIND_GLOBAL:
             {
                 i32 globalidx = (i32) bh_imap_get(&mod->global_map, (u64) expr);
 
@@ -532,10 +532,10 @@ static void compile_expression(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pco
                 break;
             }
 
-        case ONYX_AST_NODE_KIND_LITERAL:
+        case AST_NODE_KIND_LITERAL:
             {
-                OnyxAstNodeNumLit* lit = &expr->as_numlit;
-                WasmType lit_type = onyx_type_to_wasm_type(lit->type);
+                AstNodeNumLit* lit = (AstNodeNumLit *) expr;
+                WasmType lit_type = onyx_type_to_wasm_type(lit->base.type);
                 WasmInstruction instr = { WI_NOP, 0 };
 
                 if (lit_type == WASM_TYPE_INT32) {
@@ -556,13 +556,15 @@ static void compile_expression(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pco
                 break;
             }
 
-        case ONYX_AST_NODE_KIND_BLOCK: compile_block(mod, &code, (OnyxAstNodeBlock *) expr); break;
+        case AST_NODE_KIND_BLOCK: compile_block(mod, &code, (AstNodeBlock *) expr); break;
 
-        case ONYX_AST_NODE_KIND_CALL:
+        case AST_NODE_KIND_CALL:
             {
-                OnyxAstNodeCall* call = &expr->as_call;
-                forll (OnyxAstNode, arg, call->arguments, next) {
-                    compile_expression(mod, &code, arg->left);
+                AstNodeCall* call = (AstNodeCall *) expr;
+                for (AstNodeArgument *arg = call->arguments;
+                        arg != NULL;
+                        arg = (AstNodeArgument *) arg->base.next) {
+                    compile_expression(mod, &code, arg->value);
                 }
 
                 i32 func_idx = (i32) bh_imap_get(&mod->func_map, (u64) call->callee);
@@ -590,13 +592,13 @@ 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 compile_cast(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNodeUnaryOp* cast) {
+static void compile_cast(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeUnaryOp* cast) {
     bh_arr(WasmInstruction) code = *pcode;
 
-    compile_expression(mod, &code, cast->left);
+    compile_expression(mod, &code, cast->expr);
 
-    OnyxTypeInfo* from = cast->left->type;
-    OnyxTypeInfo* to = cast->type;
+    TypeInfo* from = cast->expr->type;
+    TypeInfo* to = cast->base.type;
 
     i32 fromidx = 0, toidx = 0;
     if (from->is_int) {
@@ -627,11 +629,11 @@ static void compile_cast(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, On
     *pcode = code;
 }
 
-static void compile_return(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, OnyxAstNode* ret) {
+static void compile_return(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode, AstNodeReturn* ret) {
     bh_arr(WasmInstruction) code = *pcode;
 
-    if (ret->left) {
-        compile_expression(mod, &code, ret->left);
+    if (ret->expr) {
+        compile_expression(mod, &code, ret->expr);
     }
 
     bh_arr_push(code, ((WasmInstruction){ WI_RETURN, 0x00 }));
@@ -639,22 +641,22 @@ static void compile_return(OnyxWasmModule* mod, bh_arr(WasmInstruction)* pcode,
     *pcode = code;
 }
 
-static i32 generate_type_idx(OnyxWasmModule* mod, OnyxAstNodeFunction* fd) {
+static i32 generate_type_idx(OnyxWasmModule* mod, AstNodeFunction* fd) {
     static char type_repr_buf[128];
 
     char* t = type_repr_buf;
-    OnyxAstNodeParam* param = fd->params;
+    AstNodeLocal* param = fd->params;
     i32 param_count = 0;
     while (param) {
         // HACK: Using these directly as part of a string feels weird but they are
         // valid characters so I don't think it is going to be much of an issue
-        *(t++) = (char) onyx_type_to_wasm_type(param->type);
+        *(t++) = (char) onyx_type_to_wasm_type(param->base.type);
         param_count++;
-        param = param->next;
+        param = (AstNodeLocal *) param->base.next;
     }
     *(t++) = ':';
 
-    WasmType return_type = onyx_type_to_wasm_type(fd->return_type);
+    WasmType return_type = onyx_type_to_wasm_type(fd->base.type);
     *(t++) = (char) return_type;
     *t = '\0';
 
@@ -681,7 +683,7 @@ static i32 generate_type_idx(OnyxWasmModule* mod, OnyxAstNodeFunction* fd) {
     return type_idx;
 }
 
-static void compile_function(OnyxWasmModule* mod, OnyxAstNodeFunction* fd) {
+static void compile_function(OnyxWasmModule* mod, AstNodeFunction* fd) {
     i32 type_idx = generate_type_idx(mod, fd);
 
     WasmFunc wasm_func = {
@@ -697,8 +699,8 @@ static void compile_function(OnyxWasmModule* mod, OnyxAstNodeFunction* fd) {
 
     bh_arr_new(mod->allocator, wasm_func.code, 4);
 
-    if (fd->flags & ONYX_AST_FLAG_EXPORTED) {
-        onyx_token_null_toggle(*fd->token);
+    if (fd->base.flags & ONYX_AST_FLAG_EXPORTED) {
+        onyx_token_null_toggle(fd->base.token);
 
         i32 func_idx = (i32) bh_imap_get(&mod->func_map, (u64) fd);
 
@@ -706,17 +708,17 @@ static void compile_function(OnyxWasmModule* mod, OnyxAstNodeFunction* fd) {
             .kind = WASM_FOREIGN_FUNCTION,
             .idx = func_idx,
         };
-        bh_table_put(WasmExport, mod->exports, fd->token->token, wasm_export);
+        bh_table_put(WasmExport, mod->exports, fd->base.token->token, wasm_export);
         mod->export_count++;
 
-        onyx_token_null_toggle(*fd->token);
+        onyx_token_null_toggle(fd->base.token);
     }
 
     // If there is no body then don't process the code
     if (fd->body != NULL) {
         // NOTE: Generate the local map
         i32 localidx = 0;
-        forll (OnyxAstNodeParam, param, fd->params, next) {
+        for (AstNodeLocal *param = fd->params; param != NULL; param = (AstNodeLocal *) param->base.next) {
             bh_imap_put(&mod->local_map, (u64) param, localidx++);
         }
 
@@ -726,8 +728,8 @@ static void compile_function(OnyxWasmModule* mod, OnyxAstNodeFunction* fd) {
         // is the same as the order of the local_types above
         u8* count = &wasm_func.locals.i32_count;
         fori (ti, 0, 3) {
-            forll (OnyxAstNodeLocal, local, fd->body->scope->last_local, prev_local) {
-                if (onyx_type_to_wasm_type(local->type) == local_types[ti]) {
+            forll (AstNodeLocal, local, fd->body->scope->last_local, prev_local) {
+                if (onyx_type_to_wasm_type(local->base.type) == local_types[ti]) {
                     bh_imap_put(&mod->local_map, (u64) local, localidx++);
 
                     (*count)++;
@@ -751,23 +753,23 @@ static void compile_function(OnyxWasmModule* mod, OnyxAstNodeFunction* fd) {
     bh_imap_clear(&mod->local_map);
 }
 
-static void compile_global_declaration(OnyxWasmModule* module, OnyxAstNodeGlobal* global) {
+static void compile_global_declaration(OnyxWasmModule* module, AstNodeGlobal* global) {
     WasmGlobal glob = {
-        .type = onyx_type_to_wasm_type(global->type),
-        .mutable = (global->flags & ONYX_AST_FLAG_CONST) == 0,
+        .type = onyx_type_to_wasm_type(global->base.type),
+        .mutable = (global->base.flags & ONYX_AST_FLAG_CONST) == 0,
         .initial_value = NULL,
     };
 
     if (!global->initial_value) {
         onyx_message_add(module->msgs,
                 ONYX_MESSAGE_TYPE_LITERAL,
-                global->token->pos,
+                global->base.token->pos,
                 "global without initial value");
         return;
     }
 
-    if ((global->flags & ONYX_AST_FLAG_EXPORTED) != 0) {
-        onyx_token_null_toggle(*global->token);
+    if ((global->base.flags & ONYX_AST_FLAG_EXPORTED) != 0) {
+        onyx_token_null_toggle(global->base.token);
 
         i32 global_idx = (i32) bh_imap_get(&module->func_map, (u64) global);
 
@@ -775,19 +777,19 @@ static void compile_global_declaration(OnyxWasmModule* module, OnyxAstNodeGlobal
             .kind = WASM_FOREIGN_GLOBAL,
             .idx = global_idx,
         };
-        bh_table_put(WasmExport, module->exports, global->token->token, wasm_export);
+        bh_table_put(WasmExport, module->exports, global->base.token->token, wasm_export);
         module->export_count++;
 
-        onyx_token_null_toggle(*global->token);
+        onyx_token_null_toggle(global->base.token);
     }
 
     compile_expression(module, &glob.initial_value, global->initial_value);
     bh_arr_push(module->globals, glob);
 }
 
-static void compile_foreign(OnyxWasmModule* module, OnyxAstNodeForeign* foreign) {
-    if (foreign->import->kind == ONYX_AST_NODE_KIND_FUNCTION) {
-        i32 type_idx = generate_type_idx(module, &foreign->import->as_function);
+static void compile_foreign(OnyxWasmModule* module, AstNodeForeign* foreign) {
+    if (foreign->import->kind == AST_NODE_KIND_FUNCTION) {
+        i32 type_idx = generate_type_idx(module, (AstNodeFunction *) foreign->import);
 
         WasmImport import = {
             .kind = WASM_FOREIGN_FUNCTION,
@@ -798,8 +800,8 @@ static void compile_foreign(OnyxWasmModule* module, OnyxAstNodeForeign* foreign)
 
         bh_arr_push(module->imports, import);
 
-    } else if (foreign->import->kind == ONYX_AST_NODE_KIND_GLOBAL) {
-        WasmType global_type = onyx_type_to_wasm_type(foreign->import->type);
+    } else if (foreign->import->kind == AST_NODE_KIND_GLOBAL) {
+        WasmType global_type = onyx_type_to_wasm_type(((AstNodeGlobal *) foreign->import)->base.type);
 
         WasmImport import = {
             .kind = WASM_FOREIGN_GLOBAL,
@@ -864,14 +866,14 @@ OnyxWasmModule onyx_wasm_module_create(bh_allocator alloc, OnyxMessages* msgs) {
 void onyx_wasm_module_compile(OnyxWasmModule* module, OnyxProgram* program) {
 
     // NOTE: First, introduce all indicies for globals and functions
-    bh_arr_each(OnyxAstNodeForeign *, foreign, program->foreigns) {
-        OnyxAstNodeKind import_kind = (*foreign)->import->kind;
+    bh_arr_each(AstNodeForeign *, foreign, program->foreigns) {
+        AstNodeKind import_kind = (*foreign)->import->kind;
 
-        if (import_kind == ONYX_AST_NODE_KIND_FUNCTION) {
+        if (import_kind == AST_NODE_KIND_FUNCTION) {
             module->next_func_idx++;
             bh_imap_put(&module->func_map, (u64) (*foreign)->import, module->next_import_func_idx++);
         }
-        else if (import_kind == ONYX_AST_NODE_KIND_GLOBAL) {
+        else if (import_kind == AST_NODE_KIND_GLOBAL) {
             module->next_global_idx++;
             bh_imap_put(&module->global_map, (u64) (*foreign)->import, module->next_import_func_idx++);
         }
@@ -879,18 +881,18 @@ void onyx_wasm_module_compile(OnyxWasmModule* module, OnyxProgram* program) {
         compile_foreign(module, *foreign);
     }
 
-    bh_arr_each(OnyxAstNodeFunction *, function, program->functions)
+    bh_arr_each(AstNodeFunction *, function, program->functions)
         bh_imap_put(&module->func_map, (u64) *function, module->next_func_idx++);
 
-    bh_arr_each(OnyxAstNodeGlobal *, global, program->globals)
+    bh_arr_each(AstNodeGlobal *, global, program->globals)
         bh_imap_put(&module->global_map, (u64) *global, module->next_global_idx++);
 
 
     // NOTE: Then, compile everything
-    bh_arr_each(OnyxAstNodeFunction *, function, program->functions)
+    bh_arr_each(AstNodeFunction *, function, program->functions)
         compile_function(module, *function);
 
-    bh_arr_each(OnyxAstNodeGlobal *, global, program->globals)
+    bh_arr_each(AstNodeGlobal *, global, program->globals)
         compile_global_declaration(module, *global);
 }