code cleanup; grouped all binary ops together
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 26 Jun 2020 15:26:25 +0000 (10:26 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Fri, 26 Jun 2020 15:26:25 +0000 (10:26 -0500)
13 files changed:
.vimspector.json
Makefile
docs/plan
include/onyxlex.h
include/onyxparser.h
onyx
progs/test.onyx
src/onyx.c
src/onyxlex.c
src/onyxparser.c
src/onyxsymres.c
src/onyxtypecheck.c
src/onyxwasm.c

index e309f7f9bf9838e0c2649137abd51c35f11dd304..1ecdcd93858baf22615289e2dc78a90229f0d7c4 100644 (file)
@@ -6,7 +6,7 @@
                 "type": "cppdbg",
                 "request": "launch",
                 "program": "${workspaceFolder}/onyx",
-                "args": ["progs/test.onyx"],
+                "args": ["progs/other.onyx", "progs/test.onyx"],
                 "stopAtEntry": true,
                 "cwd": "${workspaceFolder}",
                 "environment": [],
index b300bbaf6197c5211ddffdcb6e023e770e451450..aa3056ccfb81633c46b5d372d34aed24f932f32f 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -13,13 +13,17 @@ CC=gcc
 INCLUDES=-I./include
 LIBS=
 FLAGS=-g
+TARGET=./onyx
 
 build/%.o: src/%.c include/bh.h
        $(CC) $(FLAGS) -c $< -o $@ $(INCLUDES)
 
-onyx: $(OBJ_FILES)
+$(TARGET): $(OBJ_FILES)
        $(CC) $(FLAGS) $(OBJ_FILES) -o $@ $(LIBS)
 
+install: $(TARGET)
+       cp $(TARGET) /usr/bin/
+
 clean:
        rm -f $(OBJ_FILES) 2>&1 >/dev/null
 
index c7f8e80364a64d2ec9f8c49c2221d5f2ba6f8cbb..bdc275087521f3a31faff56438b193c42d68aad4 100644 (file)
--- a/docs/plan
+++ b/docs/plan
@@ -59,7 +59,7 @@ HOW:
                [X] Comparison operators
                [X] Proper boolean type
                [X] Conditional branching works as expected
-               ] Simple while loop is functioning as expected
+               XX] Simple while loop is functioning as expected
                [ ] break and continue semantics
                [X] Function calling works for the builtin types
                [X] Function return values are type checked
index 29c1c73a8eed42b4574c2eb2df45dc7d2ae39d29..6a2c75508f9a8fce408130717ca9d8c3ba0195b5 100644 (file)
@@ -15,14 +15,13 @@ typedef enum OnyxTokenType {
        TOKEN_TYPE_KEYWORD_IF,
        TOKEN_TYPE_KEYWORD_ELSE,
        TOKEN_TYPE_KEYWORD_ELSEIF,
-       TOKEN_TYPE_KEYWORD_FOR,
-       TOKEN_TYPE_KEYWORD_DO,
        TOKEN_TYPE_KEYWORD_RETURN,
        TOKEN_TYPE_KEYWORD_FOREIGN,
        TOKEN_TYPE_KEYWORD_PROC,
-       TOKEN_TYPE_KEYWORD_GLOBAL,
        TOKEN_TYPE_KEYWORD_CAST,
     TOKEN_TYPE_KEYWORD_WHILE,
+    TOKEN_TYPE_KEYWORD_BREAK,
+    TOKEN_TYPE_KEYWORD_CONTINUE,
 
        TOKEN_TYPE_RIGHT_ARROW,
        TOKEN_TYPE_LEFT_ARROW,
index f9dceade48828efa150e6134f55d95cff3d404a6..1e2379127b5302b9d9ef0765d9ea22de6d73acd2 100644 (file)
@@ -7,6 +7,8 @@
 #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;
@@ -43,32 +45,21 @@ typedef enum OnyxAstNodeKind {
        ONYX_AST_NODE_KIND_LOCAL,
     ONYX_AST_NODE_KIND_SYMBOL,
 
-       ONYX_AST_NODE_KIND_ADD,
-       ONYX_AST_NODE_KIND_MINUS,
-       ONYX_AST_NODE_KIND_MULTIPLY,
-       ONYX_AST_NODE_KIND_DIVIDE,
-       ONYX_AST_NODE_KIND_MODULUS,
-       ONYX_AST_NODE_KIND_NEGATE,
+    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_CAST,
        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_EQUAL,
-       ONYX_AST_NODE_KIND_NOT_EQUAL,
-       ONYX_AST_NODE_KIND_LESS,
-       ONYX_AST_NODE_KIND_LESS_EQUAL,
-       ONYX_AST_NODE_KIND_GREATER,
-       ONYX_AST_NODE_KIND_GREATER_EQUAL,
-       ONYX_AST_NODE_KIND_NOT,
-
        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;
@@ -112,6 +103,48 @@ typedef enum OnyxAstFlags {
        ONYX_AST_FLAG_COMPTIME          = BH_BIT(3),
 } OnyxAstFlags;
 
+typedef enum OnyxUnaryOp {
+    ONYX_UNARY_OP_NEGATE,
+    ONYX_UNARY_OP_NOT,
+    ONYX_UNARY_OP_CAST,
+} OnyxUnaryOp;
+
+typedef enum OnyxBinaryOp {
+    ONYX_BINARY_OP_ADD,
+    ONYX_BINARY_OP_MINUS,
+    ONYX_BINARY_OP_MULTIPLY,
+    ONYX_BINARY_OP_DIVIDE,
+    ONYX_BINARY_OP_MODULUS,
+
+       ONYX_BINARY_OP_EQUAL,
+       ONYX_BINARY_OP_NOT_EQUAL,
+       ONYX_BINARY_OP_LESS,
+       ONYX_BINARY_OP_LESS_EQUAL,
+       ONYX_BINARY_OP_GREATER,
+       ONYX_BINARY_OP_GREATER_EQUAL,
+} OnyxBinaryOp;
+
+struct OnyxAstNodeBinOp {
+    OnyxAstNodeKind kind;
+    u32 flags;
+    OnyxToken *token;
+    OnyxTypeInfo *type;
+    OnyxBinaryOp operation;
+    OnyxAstNode *next;
+    OnyxAstNode *left;
+    OnyxAstNode *right;
+};
+
+struct OnyxAstNodeUnaryOp {
+    OnyxAstNodeKind kind;
+    u32 flags;
+    OnyxToken *token;
+    OnyxTypeInfo *type;
+    OnyxUnaryOp operation;
+    OnyxAstNode *next;
+    OnyxAstNode *left;
+};
+
 struct OnyxAstNodeNumLit {
        OnyxAstNodeKind kind;
        u32 flags;
@@ -126,6 +159,7 @@ struct OnyxAstNodeLocal {
        u32 flags;
        OnyxToken *token;
        OnyxTypeInfo *type;
+    u64 data;                   // NOTE: Unused
        OnyxAstNode *next;
        OnyxAstNodeLocal *prev_local;
 };
@@ -133,8 +167,9 @@ struct OnyxAstNodeLocal {
 struct OnyxAstNodeParam {
        OnyxAstNodeKind kind;
        u32 flags;
-       OnyxToken *token;                       // Symbol name i.e. 'a', 'b'
+       OnyxToken *token;                       // NOTE: Symbol name i.e. 'a', 'b'
        OnyxTypeInfo *type;
+    u64 data;                   // NOTE: UNUSED
        OnyxAstNodeParam *next;
        OnyxAstNodeLocal *prev_local;
 };
@@ -144,6 +179,7 @@ struct OnyxAstNodeScope {
        u32 flags;
        OnyxToken *token;       // NOTE: UNUSED
        OnyxTypeInfo *type; // NOTE: UNUSED
+    u64 data;           // NOTE: UNUSED
        OnyxAstNodeScope *prev_scope;
        OnyxAstNodeLocal *last_local;
 };
@@ -153,6 +189,7 @@ struct OnyxAstNodeBlock {
        u32 flags;
        OnyxToken *token;
        OnyxTypeInfo *return_type;
+    u64 data;                       // NOTE: UNUSED
        OnyxAstNode *next;
        OnyxAstNode *body;
        OnyxAstNodeScope *scope;
@@ -162,6 +199,7 @@ struct OnyxAstNodeIf {
     OnyxAstNodeKind kind;
     u32 flags;
     OnyxToken *token;    // NOTE: UNUSED
+    u64 data;            // NOTE: UNUSED
     OnyxAstNode *false_block;
     OnyxAstNode *next;
     OnyxAstNode *cond;
@@ -173,6 +211,7 @@ struct OnyxAstNodeWhile {
     u32 flags;
     OnyxToken *token;   // NOTE: UNUSED
     OnyxTypeInfo *type;
+    u64 data;
     OnyxAstNode *next;
     OnyxAstNode *cond;
     OnyxAstNodeBlock *body;
@@ -183,6 +222,7 @@ struct OnyxAstNodeFuncDef {
        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;
@@ -193,6 +233,7 @@ struct OnyxAstNodeForeign {
        u32 flags;
        OnyxToken *mod_token;
        OnyxTypeInfo *type;
+    u64 data;
        OnyxAstNode *next;
     OnyxToken *name_token;
        OnyxAstNode *import;
@@ -201,8 +242,9 @@ struct OnyxAstNodeForeign {
 struct OnyxAstNodeCall {
        OnyxAstNodeKind kind;
        u32 flags;
-       OnyxToken *token;                       // NOTE: Not specified (undefined)
+       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
@@ -215,6 +257,7 @@ struct OnyxAstNodeFile {
     u32 flags;
     OnyxToken *token;           // NOTE: unused
     OnyxTypeInfo *type;         // NOTE: unused
+    u64 data;
     OnyxAstNodeFile *next;      // NOTE: next file
     OnyxAstNode *contents;      // NOTE: the first top-level element
 };
@@ -227,6 +270,7 @@ union OnyxAstNode {
                u32 flags;
                OnyxToken *token;
                OnyxTypeInfo *type;
+        u64 data;
                OnyxAstNode *next;
                OnyxAstNode *left;
                OnyxAstNode *right;
@@ -239,6 +283,8 @@ union OnyxAstNode {
        OnyxAstNodeScope as_scope;
        OnyxAstNodeCall as_call;
     OnyxAstNodeNumLit as_numlit;
+    OnyxAstNodeBinOp as_binop;
+    OnyxAstNodeUnaryOp as_unaryop;
     OnyxAstNodeForeign as_foreign;
     OnyxAstNodeIf as_if;
     OnyxAstNodeWhile as_while;
@@ -246,7 +292,7 @@ union OnyxAstNode {
 };
 
 const char* onyx_ast_node_kind_string(OnyxAstNodeKind kind);
-OnyxAstNode* onyx_ast_node_new(bh_allocator alloc, OnyxAstNodeKind kind);
+void* onyx_ast_node_new(bh_allocator alloc, OnyxAstNodeKind kind);
 OnyxParser onyx_parser_create(bh_allocator alloc, OnyxTokenizer *tokenizer, OnyxMessages* msgs);
 void onyx_parser_free(OnyxParser* parser);
 OnyxAstNodeFile* onyx_parse(OnyxParser *parser);
diff --git a/onyx b/onyx
index 5c15d2c20b759bd57e4503abac3e67f971a98151..0245333ad254d02ae277adfb705874793fe6f10c 100755 (executable)
Binary files a/onyx and b/onyx differ
index 7b492349d9a6dc07b10362d39b290814a4cfcace..c26301396f9a570dcc886bc11521a2d4e3c8d416 100644 (file)
@@ -18,13 +18,15 @@ something_else :: proc (n i32) -> i32 {
 export main :: proc {
     i := 0;
     while i < 10 {
-        print_i32(fib(i));
+        res :: fib(i);
+        print_i32(res);
         i = i + 1;
     }
 
     i = 0;
     while i < 10 {
-        print_i32(factorial(i));
+        res :: factorial(i);
+        print_i32(res);
         i = i + 1;
     }
 
index a46145285c363688eec9061ce3bd7fc8b95ddd14..3d8912ef8089e3038934b30c022efb2ec1904f73 100644 (file)
@@ -238,7 +238,7 @@ int main(int argc, char *argv[]) {
 
     compiler_state_free(&compile_state);
 
-       return compiler_progress == ONYX_COMPILER_PROGRESS_SUCCESS;
+       return compiler_progress != ONYX_COMPILER_PROGRESS_SUCCESS;
 }
 
 // NOTE: Old bits of code that may be useful again at some point.
index 9b0c68f9de88541fcca447f7dd62eb208c259e59..925d3b0339f2ca70fb84322f57f8d2f1445ca375 100644 (file)
@@ -13,14 +13,13 @@ static const char* onyx_token_type_names[] = {
        "if",                   //"TOKEN_TYPE_KEYWORD_IF",
        "else",                 //"TOKEN_TYPE_KEYWORD_ELSE",
        "elseif",               //"TOKEN_TYPE_KEYWORD_ELSEIF",
-       "for",                  //"TOKEN_TYPE_KEYWORD_FOR",
-       "do",                   //"TOKEN_TYPE_KEYWORD_DO",
        "return",               //"TOKEN_TYPE_KEYWORD_RETURN",
        "foreign",              //"TOKEN_TYPE_KEYWORD_FOREIGN",
        "proc",                 //"TOKEN_TYPE_KEYWORD_PROC",
-       "global",               //"TOKEN_TYPE_KEYWORD_GLOBAL",
        "as",                   //"TOKEN_TYPE_KEYWORD_CAST",
     "while",        //"TOKEN_TYPE_KEYWORD_WHILE",
+    "break",        //"TOKEN_TYPE_KEYWORD_BREAK",
+    "continue",     //"TOKEN_TYPE_KEYWORD_CONTINUE,
 
        "->", //"TOKEN_TYPE_RIGHT_ARROW",
        "<-", //"TOKEN_TYPE_LEFT_ARROW",
@@ -140,51 +139,50 @@ OnyxToken* onyx_get_token(OnyxTokenizer* tokenizer) {
                goto token_parsed;
        }
 
-       LITERAL_TOKEN("struct",  1, TOKEN_TYPE_KEYWORD_STRUCT);
-       LITERAL_TOKEN("export",  1, TOKEN_TYPE_KEYWORD_EXPORT);
-       LITERAL_TOKEN("use",     1, TOKEN_TYPE_KEYWORD_USE);
-       LITERAL_TOKEN("if",      1, TOKEN_TYPE_KEYWORD_IF);
-       LITERAL_TOKEN("elseif",  1, TOKEN_TYPE_KEYWORD_ELSEIF);
-       LITERAL_TOKEN("else",    1, TOKEN_TYPE_KEYWORD_ELSE);
-       LITERAL_TOKEN("foreign", 1, TOKEN_TYPE_KEYWORD_FOREIGN);
-       LITERAL_TOKEN("for",     1, TOKEN_TYPE_KEYWORD_FOR);
-       LITERAL_TOKEN("return",  1, TOKEN_TYPE_KEYWORD_RETURN);
-       LITERAL_TOKEN("do",      1, TOKEN_TYPE_KEYWORD_DO);
-       LITERAL_TOKEN("proc",    1, TOKEN_TYPE_KEYWORD_PROC);
-       LITERAL_TOKEN("global",  1, TOKEN_TYPE_KEYWORD_GLOBAL);
-       LITERAL_TOKEN("as",      1, TOKEN_TYPE_KEYWORD_CAST);
-    LITERAL_TOKEN("while",   1, TOKEN_TYPE_KEYWORD_WHILE);
-    LITERAL_TOKEN("true",    1, TOKEN_TYPE_LITERAL_BOOL_TRUE);
-    LITERAL_TOKEN("false",   1, TOKEN_TYPE_LITERAL_BOOL_FALSE);
-       LITERAL_TOKEN("->",      0, TOKEN_TYPE_RIGHT_ARROW);
-       LITERAL_TOKEN("<-",      0, TOKEN_TYPE_RIGHT_ARROW);
-       LITERAL_TOKEN("<=",      0, TOKEN_TYPE_SYM_LESS_EQUAL);
-       LITERAL_TOKEN(">=",      0, TOKEN_TYPE_SYM_GREATER_EQUAL);
-       LITERAL_TOKEN("==",      0, TOKEN_TYPE_SYM_EQUAL_EQUAL);
-       LITERAL_TOKEN("!=",      0, TOKEN_TYPE_SYM_NOT_EQUAL);
-       LITERAL_TOKEN("(",       0, TOKEN_TYPE_OPEN_PAREN);
-       LITERAL_TOKEN(")",       0, TOKEN_TYPE_CLOSE_PAREN);
-       LITERAL_TOKEN("{",       0, TOKEN_TYPE_OPEN_BRACE);
-       LITERAL_TOKEN("}",       0, TOKEN_TYPE_CLOSE_BRACE);
-       LITERAL_TOKEN("[",       0, TOKEN_TYPE_OPEN_BRACKET);
-       LITERAL_TOKEN("]",       0, TOKEN_TYPE_CLOSE_BRACKET);
-       LITERAL_TOKEN("+",       0, TOKEN_TYPE_SYM_PLUS);
-       LITERAL_TOKEN("-",       0, TOKEN_TYPE_SYM_MINUS);
-       LITERAL_TOKEN("*",       0, TOKEN_TYPE_SYM_STAR);
-       LITERAL_TOKEN(".",       0, TOKEN_TYPE_SYM_DOT);
-       LITERAL_TOKEN("%",       0, TOKEN_TYPE_SYM_PERCENT);
-       LITERAL_TOKEN("/",       0, TOKEN_TYPE_SYM_FSLASH);
-       LITERAL_TOKEN("\\",      0, TOKEN_TYPE_SYM_BSLASH);
-       LITERAL_TOKEN(":",       0, TOKEN_TYPE_SYM_COLON);
-       LITERAL_TOKEN(";",       0, TOKEN_TYPE_SYM_SEMICOLON);
-       LITERAL_TOKEN(",",       0, TOKEN_TYPE_SYM_COMMA);
-       LITERAL_TOKEN(">",       0, TOKEN_TYPE_SYM_GREATER);
-       LITERAL_TOKEN("<",       0, TOKEN_TYPE_SYM_LESS);
-       LITERAL_TOKEN("=",       0, TOKEN_TYPE_SYM_EQUALS);
-       LITERAL_TOKEN("~",       0, TOKEN_TYPE_SYM_TILDE);
-       LITERAL_TOKEN("!",       0, TOKEN_TYPE_SYM_BANG);
-       LITERAL_TOKEN("^",       0, TOKEN_TYPE_SYM_CARET);
-       LITERAL_TOKEN("&",       0, TOKEN_TYPE_SYM_AMPERSAND);
+       LITERAL_TOKEN("struct",     1, TOKEN_TYPE_KEYWORD_STRUCT);
+       LITERAL_TOKEN("export",     1, TOKEN_TYPE_KEYWORD_EXPORT);
+       LITERAL_TOKEN("use",        1, TOKEN_TYPE_KEYWORD_USE);
+       LITERAL_TOKEN("if",         1, TOKEN_TYPE_KEYWORD_IF);
+       LITERAL_TOKEN("elseif",     1, TOKEN_TYPE_KEYWORD_ELSEIF);
+       LITERAL_TOKEN("else",       1, TOKEN_TYPE_KEYWORD_ELSE);
+       LITERAL_TOKEN("foreign",    1, TOKEN_TYPE_KEYWORD_FOREIGN);
+       LITERAL_TOKEN("return",     1, TOKEN_TYPE_KEYWORD_RETURN);
+       LITERAL_TOKEN("proc",       1, TOKEN_TYPE_KEYWORD_PROC);
+       LITERAL_TOKEN("as",         1, TOKEN_TYPE_KEYWORD_CAST);
+    LITERAL_TOKEN("while",      1, TOKEN_TYPE_KEYWORD_WHILE);
+    LITERAL_TOKEN("break",      1, TOKEN_TYPE_KEYWORD_BREAK);
+    LITERAL_TOKEN("continue",   1, TOKEN_TYPE_KEYWORD_CONTINUE);
+    LITERAL_TOKEN("true",       1, TOKEN_TYPE_LITERAL_BOOL_TRUE);
+    LITERAL_TOKEN("false",      1, TOKEN_TYPE_LITERAL_BOOL_FALSE);
+       LITERAL_TOKEN("->",         0, TOKEN_TYPE_RIGHT_ARROW);
+       LITERAL_TOKEN("<-",         0, TOKEN_TYPE_RIGHT_ARROW);
+       LITERAL_TOKEN("<=",         0, TOKEN_TYPE_SYM_LESS_EQUAL);
+       LITERAL_TOKEN(">=",         0, TOKEN_TYPE_SYM_GREATER_EQUAL);
+       LITERAL_TOKEN("==",         0, TOKEN_TYPE_SYM_EQUAL_EQUAL);
+       LITERAL_TOKEN("!=",         0, TOKEN_TYPE_SYM_NOT_EQUAL);
+       LITERAL_TOKEN("(",          0, TOKEN_TYPE_OPEN_PAREN);
+       LITERAL_TOKEN(")",          0, TOKEN_TYPE_CLOSE_PAREN);
+       LITERAL_TOKEN("{",          0, TOKEN_TYPE_OPEN_BRACE);
+       LITERAL_TOKEN("}",          0, TOKEN_TYPE_CLOSE_BRACE);
+       LITERAL_TOKEN("[",          0, TOKEN_TYPE_OPEN_BRACKET);
+       LITERAL_TOKEN("]",          0, TOKEN_TYPE_CLOSE_BRACKET);
+       LITERAL_TOKEN("+",          0, TOKEN_TYPE_SYM_PLUS);
+       LITERAL_TOKEN("-",          0, TOKEN_TYPE_SYM_MINUS);
+       LITERAL_TOKEN("*",          0, TOKEN_TYPE_SYM_STAR);
+       LITERAL_TOKEN(".",          0, TOKEN_TYPE_SYM_DOT);
+       LITERAL_TOKEN("%",          0, TOKEN_TYPE_SYM_PERCENT);
+       LITERAL_TOKEN("/",          0, TOKEN_TYPE_SYM_FSLASH);
+       LITERAL_TOKEN("\\",         0, TOKEN_TYPE_SYM_BSLASH);
+       LITERAL_TOKEN(":",          0, TOKEN_TYPE_SYM_COLON);
+       LITERAL_TOKEN(";",          0, TOKEN_TYPE_SYM_SEMICOLON);
+       LITERAL_TOKEN(",",          0, TOKEN_TYPE_SYM_COMMA);
+       LITERAL_TOKEN(">",          0, TOKEN_TYPE_SYM_GREATER);
+       LITERAL_TOKEN("<",          0, TOKEN_TYPE_SYM_LESS);
+       LITERAL_TOKEN("=",          0, TOKEN_TYPE_SYM_EQUALS);
+       LITERAL_TOKEN("~",          0, TOKEN_TYPE_SYM_TILDE);
+       LITERAL_TOKEN("!",          0, TOKEN_TYPE_SYM_BANG);
+       LITERAL_TOKEN("^",          0, TOKEN_TYPE_SYM_CARET);
+       LITERAL_TOKEN("&",          0, TOKEN_TYPE_SYM_AMPERSAND);
 
        // Symbols
        if (char_is_alpha(*tk.token)) {
index 9a7dbd51f557a0e7b31c7c3a784ecd3cfe949152..8cf4a513be025812fd4286d33b69f3b5af251116 100644 (file)
@@ -14,12 +14,8 @@ static const char* ast_node_names[] = {
        "LOCAL",
     "SYMBOL",
 
-       "ADD",
-       "MINUS",
-       "MULTIPLY",
-       "DIVIDE",
-       "MODULUS",
-       "NEGATE",
+    "UN_OP",
+    "BIN_OP",
 
        "TYPE",
        "LITERAL",
@@ -30,14 +26,6 @@ static const char* ast_node_names[] = {
        "ASSIGN",
        "RETURN",
 
-       "EQUAL",
-       "NOT_EQUAL",
-       "GREATER",
-       "GREATER_EQUAL",
-       "LESS",
-       "LESS_EQUAL",
-       "NOT",
-
        "IF",
        "WHILE",
 
@@ -63,7 +51,7 @@ struct OnyxTypeInfo builtin_types[] = {
        { 0xffffffff } // Sentinel
 };
 
-static OnyxAstNode error_node = { { ONYX_AST_NODE_KIND_ERROR, 0, NULL, &builtin_types[0], NULL, NULL, NULL } };
+static OnyxAstNode error_node = { { ONYX_AST_NODE_KIND_ERROR, 0, NULL, &builtin_types[0], 0, NULL, NULL, NULL } };
 
 // NOTE: Forward declarations
 static void parser_next_token(OnyxParser* parser);
@@ -174,13 +162,16 @@ static OnyxAstNodeNumLit* parse_numeric_literal(OnyxParser* parser) {
 }
 
 static OnyxAstNode* parse_factor(OnyxParser* parser) {
+    OnyxAstNode* retval = NULL;
+
        switch (parser->curr_token->type) {
                case TOKEN_TYPE_OPEN_PAREN:
                        {
                                parser_next_token(parser);
                                OnyxAstNode* expr = parse_expression(parser);
                                expect(parser, TOKEN_TYPE_CLOSE_PAREN);
-                               return expr;
+                               retval = expr;
+                break;
                        }
 
         case TOKEN_TYPE_SYM_MINUS:
@@ -188,7 +179,8 @@ static OnyxAstNode* parse_factor(OnyxParser* parser) {
                 parser_next_token(parser);
                 OnyxAstNode* factor = parse_factor(parser);
 
-                OnyxAstNode* negate_node = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_NEGATE);
+                OnyxAstNodeUnaryOp* negate_node = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_UNARY_OP);
+                negate_node->operation = ONYX_UNARY_OP_NEGATE;
                 negate_node->left = factor;
                 negate_node->type = factor->type;
 
@@ -196,7 +188,8 @@ static OnyxAstNode* parse_factor(OnyxParser* parser) {
                     negate_node->flags |= ONYX_AST_FLAG_COMPTIME;
                 }
 
-                return negate_node;
+                retval = (OnyxAstNode *) negate_node;
+                break;
             }
 
                case TOKEN_TYPE_SYMBOL:
@@ -206,7 +199,8 @@ static OnyxAstNode* parse_factor(OnyxParser* parser) {
                 sym_node->token = sym_token;
 
                                if (parser->curr_token->type != TOKEN_TYPE_OPEN_PAREN) {
-                                       return sym_node;
+                                       retval = sym_node;
+                    break;
                                }
 
                                // NOTE: Function call
@@ -245,10 +239,13 @@ static OnyxAstNode* parse_factor(OnyxParser* parser) {
                                }
                                parser_next_token(parser);
 
-                               return (OnyxAstNode *) call_node;
+                               retval = (OnyxAstNode *) call_node;
+                break;
                        }
 
-        case TOKEN_TYPE_LITERAL_NUMERIC: return (OnyxAstNode *) parse_numeric_literal(parser);
+        case TOKEN_TYPE_LITERAL_NUMERIC:
+            retval = (OnyxAstNode *) parse_numeric_literal(parser);
+            break;
 
         case TOKEN_TYPE_LITERAL_BOOL_TRUE:
             {
@@ -256,7 +253,8 @@ static OnyxAstNode* parse_factor(OnyxParser* parser) {
                 bool_node->type = &builtin_types[ONYX_TYPE_INFO_KIND_BOOL];
                 bool_node->token = expect(parser, TOKEN_TYPE_LITERAL_BOOL_TRUE);
                 bool_node->value.i = 1;
-                return (OnyxAstNode *) bool_node;
+                retval = (OnyxAstNode *) bool_node;
+                break;
             }
 
         case TOKEN_TYPE_LITERAL_BOOL_FALSE:
@@ -265,7 +263,8 @@ static OnyxAstNode* parse_factor(OnyxParser* parser) {
                 bool_node->type = &builtin_types[ONYX_TYPE_INFO_KIND_BOOL];
                 bool_node->token = expect(parser, TOKEN_TYPE_LITERAL_BOOL_FALSE);
                 bool_node->value.i = 0;
-                return (OnyxAstNode *) bool_node;
+                retval = (OnyxAstNode *) bool_node;
+                break;
             }
 
                default:
@@ -273,36 +272,43 @@ static OnyxAstNode* parse_factor(OnyxParser* parser) {
                                        ONYX_MESSAGE_TYPE_UNEXPECTED_TOKEN,
                                        parser->curr_token->pos,
                                        onyx_get_token_type_name(parser->curr_token->type));
+            return NULL;
        }
 
-       return NULL;
+    if (parser->curr_token->type == TOKEN_TYPE_KEYWORD_CAST) {
+        OnyxAstNodeUnaryOp* cast_node = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_UNARY_OP);
+        cast_node->operation = ONYX_UNARY_OP_CAST;
+        cast_node->type = parse_type(parser);
+        cast_node->left = retval;
+        retval = (OnyxAstNode *) cast_node;
+    }
+
+    return retval;
 }
 
-static inline i32 get_precedence(OnyxAstNodeKind kind) {
+static inline i32 get_precedence(OnyxBinaryOp kind) {
     switch (kind) {
-        case ONYX_AST_NODE_KIND_EQUAL: return 3;
-        case ONYX_AST_NODE_KIND_NOT_EQUAL: return 3;
+        case ONYX_BINARY_OP_EQUAL: return 3;
+        case ONYX_BINARY_OP_NOT_EQUAL: return 3;
 
-        case ONYX_AST_NODE_KIND_LESS_EQUAL: return 4;
-        case ONYX_AST_NODE_KIND_LESS: return 4;
-        case ONYX_AST_NODE_KIND_GREATER_EQUAL: return 4;
-        case ONYX_AST_NODE_KIND_GREATER: return 4;
+        case ONYX_BINARY_OP_LESS_EQUAL: return 4;
+        case ONYX_BINARY_OP_LESS: return 4;
+        case ONYX_BINARY_OP_GREATER_EQUAL: return 4;
+        case ONYX_BINARY_OP_GREATER: return 4;
 
-        case ONYX_AST_NODE_KIND_ADD: return 5;
-        case ONYX_AST_NODE_KIND_MINUS: return 5;
+        case ONYX_BINARY_OP_ADD: return 5;
+        case ONYX_BINARY_OP_MINUS: return 5;
 
-        case ONYX_AST_NODE_KIND_MULTIPLY: return 6;
-        case ONYX_AST_NODE_KIND_DIVIDE: return 6;
+        case ONYX_BINARY_OP_MULTIPLY: return 6;
+        case ONYX_BINARY_OP_DIVIDE: return 6;
 
-        case ONYX_AST_NODE_KIND_MODULUS: return 7;
-
-        case ONYX_AST_NODE_KIND_CAST: return 8;
+        case ONYX_BINARY_OP_MODULUS: return 7;
         default: return -1;
     }
 }
 
 static OnyxAstNode* parse_expression(OnyxParser* parser) {
-    bh_arr(OnyxAstNode*) tree_stack = NULL;
+    bh_arr(OnyxAstNodeBinOp*) tree_stack = NULL;
     bh_arr_new(global_scratch_allocator, tree_stack, 4);
     bh_arr_set_length(tree_stack, 0);
 
@@ -310,25 +316,24 @@ static OnyxAstNode* parse_expression(OnyxParser* parser) {
     OnyxAstNode* right;
     OnyxAstNode* root = left;
 
-    i32 bin_op_kind;
+    OnyxBinaryOp bin_op_kind;
     OnyxToken* bin_op_tok;
 
     while (1) {
         bin_op_kind = -1;
         switch (parser->curr_token->type) {
-            case TOKEN_TYPE_SYM_EQUAL_EQUAL:    bin_op_kind = ONYX_AST_NODE_KIND_EQUAL; break;
-            case TOKEN_TYPE_SYM_NOT_EQUAL:      bin_op_kind = ONYX_AST_NODE_KIND_NOT_EQUAL; break;
-            case TOKEN_TYPE_SYM_LESS_EQUAL:     bin_op_kind = ONYX_AST_NODE_KIND_LESS_EQUAL; break;
-            case TOKEN_TYPE_SYM_LESS:           bin_op_kind = ONYX_AST_NODE_KIND_LESS; break;
-            case TOKEN_TYPE_SYM_GREATER_EQUAL:  bin_op_kind = ONYX_AST_NODE_KIND_GREATER_EQUAL; break;
-            case TOKEN_TYPE_SYM_GREATER:        bin_op_kind = ONYX_AST_NODE_KIND_GREATER; break;
-
-            case TOKEN_TYPE_SYM_PLUS:       bin_op_kind = ONYX_AST_NODE_KIND_ADD; break;
-            case TOKEN_TYPE_SYM_MINUS:      bin_op_kind = ONYX_AST_NODE_KIND_MINUS; break;
-            case TOKEN_TYPE_SYM_STAR:       bin_op_kind = ONYX_AST_NODE_KIND_MULTIPLY; break;
-            case TOKEN_TYPE_SYM_FSLASH:     bin_op_kind = ONYX_AST_NODE_KIND_DIVIDE; break;
-            case TOKEN_TYPE_SYM_PERCENT:    bin_op_kind = ONYX_AST_NODE_KIND_MODULUS; break;
-            case TOKEN_TYPE_KEYWORD_CAST:   bin_op_kind = ONYX_AST_NODE_KIND_CAST; break;
+            case TOKEN_TYPE_SYM_EQUAL_EQUAL:    bin_op_kind = ONYX_BINARY_OP_EQUAL; break;
+            case TOKEN_TYPE_SYM_NOT_EQUAL:      bin_op_kind = ONYX_BINARY_OP_NOT_EQUAL; break;
+            case TOKEN_TYPE_SYM_LESS_EQUAL:     bin_op_kind = ONYX_BINARY_OP_LESS_EQUAL; break;
+            case TOKEN_TYPE_SYM_LESS:           bin_op_kind = ONYX_BINARY_OP_LESS; break;
+            case TOKEN_TYPE_SYM_GREATER_EQUAL:  bin_op_kind = ONYX_BINARY_OP_GREATER_EQUAL; break;
+            case TOKEN_TYPE_SYM_GREATER:        bin_op_kind = ONYX_BINARY_OP_GREATER; break;
+
+            case TOKEN_TYPE_SYM_PLUS:       bin_op_kind = ONYX_BINARY_OP_ADD; break;
+            case TOKEN_TYPE_SYM_MINUS:      bin_op_kind = ONYX_BINARY_OP_MINUS; break;
+            case TOKEN_TYPE_SYM_STAR:       bin_op_kind = ONYX_BINARY_OP_MULTIPLY; break;
+            case TOKEN_TYPE_SYM_FSLASH:     bin_op_kind = ONYX_BINARY_OP_DIVIDE; break;
+            case TOKEN_TYPE_SYM_PERCENT:    bin_op_kind = ONYX_BINARY_OP_MODULUS; break;
             default: goto expression_done;
         }
 
@@ -336,34 +341,31 @@ static OnyxAstNode* parse_expression(OnyxParser* parser) {
             bin_op_tok = parser->curr_token;
             parser_next_token(parser);
 
-            OnyxAstNode* bin_op = onyx_ast_node_new(parser->allocator, bin_op_kind);
+            OnyxAstNodeBinOp* bin_op = onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_BIN_OP);
+            bin_op->operation = bin_op_kind;
             bin_op->token = bin_op_tok;
 
             while ( !bh_arr_is_empty(tree_stack) &&
-                    get_precedence(bh_arr_last(tree_stack)->kind) >= get_precedence(bin_op_kind))
+                    get_precedence(bh_arr_last(tree_stack)->operation) >= get_precedence(bin_op_kind))
                 bh_arr_pop(tree_stack);
 
             if (bh_arr_is_empty(tree_stack)) {
                 // NOTE: new is now the root node
                 bin_op->left = root;
-                root = bin_op;
+                root = (OnyxAstNode *) bin_op;
             } else {
                 bin_op->left = bh_arr_last(tree_stack)->right;
-                bh_arr_last(tree_stack)->right = bin_op;
+                bh_arr_last(tree_stack)->right = (OnyxAstNode *) bin_op;
             }
 
             bh_arr_push(tree_stack, bin_op);
 
-            if (bin_op_kind == ONYX_AST_NODE_KIND_CAST) {
-                bin_op->type = parse_type(parser);
-            } else {
-                right = parse_factor(parser);
-                bin_op->right = right;
-                bin_op->type = right->type;
+            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;
-                }
+            if ((left->flags & ONYX_AST_FLAG_COMPTIME) != 0 && (right->flags & ONYX_AST_FLAG_COMPTIME) != 0) {
+                bin_op->flags |= ONYX_AST_FLAG_COMPTIME;
             }
         }
     }
@@ -558,6 +560,16 @@ static OnyxAstNode* parse_statement(OnyxParser* parser) {
             retval = (OnyxAstNode *) parse_while_stmt(parser);
             break;
 
+        case TOKEN_TYPE_KEYWORD_BREAK:
+            retval = onyx_ast_node_new(parser->allocator, ONYX_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->token = expect(parser, TOKEN_TYPE_KEYWORD_CONTINUE);
+            break;
+
                default:
             break;
        }
@@ -779,12 +791,14 @@ const char* onyx_ast_node_kind_string(OnyxAstNodeKind kind) {
        return ast_node_names[kind];
 }
 
-OnyxAstNode* onyx_ast_node_new(bh_allocator alloc, OnyxAstNodeKind kind) {\
-       OnyxAstNode* node = (OnyxAstNode *) bh_alloc(alloc, sizeof(OnyxAstNode));
+// 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;
index a03dd61468441140577b71dc88d67984fc54c5d8..d5cf6d6ea7ea9c6b050f3d24580502a5dccee897 100644 (file)
@@ -131,30 +131,12 @@ static void symres_call(OnyxSemPassState* state, OnyxAstNode* stmt) {
 
 static void symres_expression(OnyxSemPassState* state, OnyxAstNode** expr) {
     switch ((*expr)->kind) {
-        case ONYX_AST_NODE_KIND_ADD:
-        case ONYX_AST_NODE_KIND_MINUS:
-        case ONYX_AST_NODE_KIND_MULTIPLY:
-        case ONYX_AST_NODE_KIND_DIVIDE:
-        case ONYX_AST_NODE_KIND_MODULUS:
-        case ONYX_AST_NODE_KIND_EQUAL:
-        case ONYX_AST_NODE_KIND_NOT_EQUAL:
-        case ONYX_AST_NODE_KIND_LESS:
-        case ONYX_AST_NODE_KIND_LESS_EQUAL:
-        case ONYX_AST_NODE_KIND_GREATER:
-        case ONYX_AST_NODE_KIND_GREATER_EQUAL:
+        case ONYX_AST_NODE_KIND_BIN_OP:
             symres_expression(state, &(*expr)->left);
             symres_expression(state, &(*expr)->right);
             break;
 
-        case ONYX_AST_NODE_KIND_NEGATE:
-            symres_expression(state, &(*expr)->left);
-            break;
-
-        case ONYX_AST_NODE_KIND_CAST:
-            if ((*expr)->type == NULL) {
-                DEBUG_HERE;
-                return;
-            }
+        case ONYX_AST_NODE_KIND_UNARY_OP:
             symres_expression(state, &(*expr)->left);
             break;
 
index 65c687c5522b8e6db42c03f993a7c8f8025dbf8a..a1846c2fa7ff4ef8a05727f5d5f3cddd023e721d 100644 (file)
@@ -161,17 +161,7 @@ static void typecheck_call(OnyxSemPassState* state, OnyxAstNodeCall* call) {
 
 static void typecheck_expression(OnyxSemPassState* state, OnyxAstNode* expr) {
     switch (expr->kind) {
-        case ONYX_AST_NODE_KIND_ADD:
-        case ONYX_AST_NODE_KIND_MINUS:
-        case ONYX_AST_NODE_KIND_MULTIPLY:
-        case ONYX_AST_NODE_KIND_DIVIDE:
-        case ONYX_AST_NODE_KIND_MODULUS:
-        case ONYX_AST_NODE_KIND_EQUAL:
-        case ONYX_AST_NODE_KIND_NOT_EQUAL:
-        case ONYX_AST_NODE_KIND_LESS:
-        case ONYX_AST_NODE_KIND_LESS_EQUAL:
-        case ONYX_AST_NODE_KIND_GREATER:
-        case ONYX_AST_NODE_KIND_GREATER_EQUAL:
+        case ONYX_AST_NODE_KIND_BIN_OP:
             expr->type = &builtin_types[ONYX_TYPE_INFO_KIND_UNKNOWN];
 
             typecheck_expression(state, expr->left);
@@ -202,8 +192,8 @@ static void typecheck_expression(OnyxSemPassState* state, OnyxAstNode* expr) {
                 return;
             }
 
-            if (expr->kind >= ONYX_AST_NODE_KIND_EQUAL
-                    && expr->kind <= ONYX_AST_NODE_KIND_GREATER_EQUAL) {
+            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];
             } else {
                 expr->type = expr->left->type;
@@ -211,14 +201,11 @@ static void typecheck_expression(OnyxSemPassState* state, OnyxAstNode* expr) {
 
             break;
 
-        case ONYX_AST_NODE_KIND_NEGATE:
-            typecheck_expression(state, expr->left);
-            expr->type = expr->left->type;
-            break;
-
-        case ONYX_AST_NODE_KIND_CAST:
-            // NOTE: Do nothing. The resulting type from the cast
-            // is already in the cast expression.
+        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;
+            }
             break;
 
         case ONYX_AST_NODE_KIND_CALL:
index a9c6d22a5675a1b3ae0effcb9cd80af56b6e0856..02941609be558ded656871c3ef710d82ce955e16 100644 (file)
@@ -215,8 +215,10 @@ static void compile_assign_lval(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode
 static void compile_assignment(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* assign);
 static void compile_if(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNodeIf* if_node);
 static void compile_while(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNodeWhile* while_node);
+static void compile_binop(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNodeBinOp* binop);
+static void compile_unaryop(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNodeUnaryOp* unop);
 static void compile_expression(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* expr);
-static void compile_cast(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* cast);
+static void compile_cast(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNodeUnaryOp* cast);
 static void compile_return(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* ret);
 
 static void compile_function_body(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNodeFuncDef* fd) {
@@ -321,105 +323,79 @@ static void compile_assignment(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode*
        compile_assign_lval(mod, func, assign->left);
 }
 
-#define BIN_OP_PROCESS(ast_binop, wasm_binop) \
-       case ONYX_AST_NODE_KIND_##ast_binop: \
-               { \
-                       WasmInstructionType instr_type; \
-                       switch (expr->left->type->kind) { \
-                case ONYX_TYPE_INFO_KIND_BOOL: \
-                               case ONYX_TYPE_INFO_KIND_UINT32: \
-                               case ONYX_TYPE_INFO_KIND_INT32: instr_type = WI_I32_##wasm_binop;               break; \
-                               case ONYX_TYPE_INFO_KIND_UINT64: \
-                               case ONYX_TYPE_INFO_KIND_INT64: instr_type = WI_I64_##wasm_binop;               break; \
-                               case ONYX_TYPE_INFO_KIND_FLOAT32: instr_type = WI_F32_##wasm_binop;             break; \
-                               case ONYX_TYPE_INFO_KIND_FLOAT64: instr_type = WI_F64_##wasm_binop;             break; \
-                               default: assert(("Invalid type", 0)); \
-                       } \
- \
-                       compile_expression(mod, func, expr->left); \
-                       compile_expression(mod, func, expr->right); \
-                       bh_arr_push(func->code, ((WasmInstruction){ instr_type, 0x00 })); \
-                       break; \
-               }
+// NOTE: These need to be in the same order as
+// the OnyxBinaryOp enum
+static const WasmInstructionType binop_map[][4] = {
+    //          I32           I64           F32         F64
+    /* ADD */ { WI_I32_ADD,   WI_I64_ADD,   WI_F32_ADD, WI_F64_ADD },
+    /* SUB */ { WI_I32_SUB,   WI_I64_SUB,   WI_F32_SUB, WI_F64_SUB },
+    /* MUL */ { WI_I32_MUL,   WI_I64_MUL,   WI_F32_MUL, WI_F64_MUL },
+    /* DIV */ { WI_I32_DIV_S, WI_I64_DIV_S, WI_F32_DIV, WI_F64_DIV },
+    /* REM */ { WI_I32_REM_S, WI_I64_REM_S, WI_NOP,     WI_NOP     },
+
+    /* EQ  */ { WI_I32_EQ,    WI_I64_EQ,    WI_F32_EQ,  WI_F64_EQ },
+    /* NEQ */ { WI_NOP,       WI_NOP,       WI_F32_NE , WI_F64_NE },
+    /* LT  */ { WI_I32_LT_S,  WI_I64_LT_S,  WI_F32_LT,  WI_F64_LT },
+    /* LTE */ { WI_I32_LE_S,  WI_I64_LE_S,  WI_F32_LE,  WI_F64_LE },
+    /* GT  */ { WI_I32_GT_S,  WI_I64_GT_S,  WI_F32_GT,  WI_F64_GT },
+    /* GTE */ { WI_I32_GE_S,  WI_I64_GE_S,  WI_F32_GE,  WI_F64_GE },
+};
 
-#define BIN_OP_SIGNED_PROCESS(ast_binop, wasm_binop) \
-               case ONYX_AST_NODE_KIND_##ast_binop: \
-                       { \
-                               WasmInstructionType instr_type; \
-                               switch (expr->left->type->kind) { \
-                    case ONYX_TYPE_INFO_KIND_BOOL: \
-                                       case ONYX_TYPE_INFO_KIND_UINT32: \
-                                       case ONYX_TYPE_INFO_KIND_INT32: \
-                                               if (expr->left->type->is_unsigned) instr_type = WI_I32_##wasm_binop##_U; \
-                                               else instr_type = WI_I32_##wasm_binop##_S; \
-                                               break; \
-                                       case ONYX_TYPE_INFO_KIND_UINT64: \
-                                       case ONYX_TYPE_INFO_KIND_INT64: \
-                                               if (expr->left->type->is_unsigned) instr_type = WI_I64_##wasm_binop##_U; \
-                                               else instr_type = WI_I64_##wasm_binop##_S; \
-                                               break; \
-                                       case ONYX_TYPE_INFO_KIND_FLOAT32: instr_type = WI_F32_##wasm_binop;             break; \
-                                       case ONYX_TYPE_INFO_KIND_FLOAT64: instr_type = WI_F64_##wasm_binop;             break; \
-                                       default: assert(("Invalid type", 0)); \
-                               } \
- \
-                               compile_expression(mod, func, expr->left); \
-                               compile_expression(mod, func, expr->right); \
-                               bh_arr_push(func->code, ((WasmInstruction){ instr_type, 0x00 })); \
-                               break; \
-                       }
+static void compile_binop(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNodeBinOp* binop) {
+    b32 is_sign_significant = 0;
 
-static void compile_expression(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* expr) {
-       switch (expr->kind) {
-               BIN_OP_PROCESS(ADD, ADD);
-               BIN_OP_PROCESS(MINUS, SUB);
-               BIN_OP_PROCESS(MULTIPLY, MUL);
-        BIN_OP_SIGNED_PROCESS(DIVIDE, DIV);
-
-        BIN_OP_SIGNED_PROCESS(LESS, LT);
-        BIN_OP_SIGNED_PROCESS(LESS_EQUAL, LE);
-        BIN_OP_SIGNED_PROCESS(GREATER, GT);
-        BIN_OP_SIGNED_PROCESS(GREATER_EQUAL, GE);
-        BIN_OP_PROCESS(EQUAL, EQ);
-        BIN_OP_PROCESS(NOT_EQUAL, NE);
-
-               case ONYX_AST_NODE_KIND_MODULUS:
-                       {
-                               WasmInstructionType instr_type;
-                               switch (expr->type->kind) {
-                                       case ONYX_TYPE_INFO_KIND_INT32:
-                                               if (expr->type->is_unsigned) instr_type = WI_I32_REM_U;
-                                               else instr_type = WI_I32_REM_S;
-                                               break;
-                                       case ONYX_TYPE_INFO_KIND_INT64:
-                                               if (expr->type->is_unsigned) instr_type = WI_I64_REM_U;
-                                               else instr_type = WI_I64_REM_S;
-                                               break;
-                                       default: assert(("Invalid type", 0));
-                               }
+    switch (binop->operation) {
+        case ONYX_BINARY_OP_DIVIDE:
+        case ONYX_BINARY_OP_MODULUS:
+        case ONYX_BINARY_OP_LESS:
+        case ONYX_BINARY_OP_LESS_EQUAL:
+        case ONYX_BINARY_OP_GREATER:
+        case ONYX_BINARY_OP_GREATER_EQUAL:
+            is_sign_significant = 1;
 
-                               compile_expression(mod, func, expr->left);
-                               compile_expression(mod, func, expr->right);
-                               bh_arr_push(func->code, ((WasmInstruction){ instr_type, 0x00 }));
-                               break;
-                       }
+        default: break;
+    }
+
+    WasmType operator_type = onyx_type_to_wasm_type(binop->left->type);
+    WasmInstructionType binop_instr = binop_map[binop->operation][operator_type];
+
+    if (binop_instr == WI_NOP) {
+        assert(("Invalid type and operation", 0));
+    }
+
+    // NOTE: Use unsigned variant if needed
+    // Unsigned instructions are always right after
+    // the signed equivalent
+    if (is_sign_significant) {
+        if (binop->left->type->is_unsigned) {
+            binop_instr += 1;
+        }
+    }
 
-        case ONYX_AST_NODE_KIND_NEGATE:
+    compile_expression(mod, func, binop->left);
+    compile_expression(mod, func, binop->right);
+
+    bh_arr_push(func->code, ((WasmInstruction){ binop_instr, 0x00 }));
+}
+
+static void compile_unaryop(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNodeUnaryOp* unop) {
+    switch (unop->operation) {
+        case ONYX_UNARY_OP_NEGATE:
             {
-                OnyxTypeInfoKind type_kind = expr->type->kind;
+                OnyxTypeInfoKind type_kind = unop->type->kind;
 
                 if (type_kind == ONYX_TYPE_INFO_KIND_INT32) {
                     bh_arr_push(func->code, ((WasmInstruction){ WI_I32_CONST, 0x00 }));
-                    compile_expression(mod, func, expr->left);
+                    compile_expression(mod, func, unop->left);
                     bh_arr_push(func->code, ((WasmInstruction){ WI_I32_SUB, 0x00 }));
 
                 } else if (type_kind == ONYX_TYPE_INFO_KIND_INT64) {
                     bh_arr_push(func->code, ((WasmInstruction){ WI_I64_CONST, 0x00 }));
-                    compile_expression(mod, func, expr->left);
+                    compile_expression(mod, func, unop->left);
                     bh_arr_push(func->code, ((WasmInstruction){ WI_I64_SUB, 0x00 }));
 
                 } else {
-                    compile_expression(mod, func, expr->left);
+                    compile_expression(mod, func, unop->left);
 
                     if (type_kind == ONYX_TYPE_INFO_KIND_FLOAT32)
                         bh_arr_push(func->code, ((WasmInstruction){ WI_F32_NEG, 0x00 }));
@@ -427,9 +403,29 @@ static void compile_expression(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode*
                     if (type_kind == ONYX_TYPE_INFO_KIND_FLOAT64)
                         bh_arr_push(func->code, ((WasmInstruction){ WI_F32_NEG, 0x00 }));
                 }
+
                 break;
             }
 
+        case ONYX_UNARY_OP_NOT:
+            compile_expression(mod, func, unop->left);
+            bh_arr_push(func->code, ((WasmInstruction){ WI_I32_EQZ, 0x00 }));
+            break;
+
+        case ONYX_UNARY_OP_CAST: compile_cast(mod, func, unop); break;
+    }
+}
+
+static void compile_expression(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* expr) {
+       switch (expr->kind) {
+        case ONYX_AST_NODE_KIND_BIN_OP:
+            compile_binop(mod, func, &expr->as_binop);
+            break;
+
+        case ONYX_AST_NODE_KIND_UNARY_OP:
+            compile_unaryop(mod, func, &expr->as_unaryop);
+            break;
+
                case ONYX_AST_NODE_KIND_LOCAL:
                case ONYX_AST_NODE_KIND_PARAM:
                        {
@@ -439,7 +435,6 @@ static void compile_expression(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode*
                                break;
                        }
 
-               case ONYX_AST_NODE_KIND_CAST: compile_cast(mod, func, expr); break;
                case ONYX_AST_NODE_KIND_LITERAL:
                        {
                 OnyxAstNodeNumLit* lit = &expr->as_numlit;
@@ -496,7 +491,7 @@ 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, WasmFunc* func, OnyxAstNode* cast) {
+static void compile_cast(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNodeUnaryOp* cast) {
        compile_expression(mod, func, cast->left);
 
        OnyxTypeInfo* from = cast->left->type;