From: Brendan Hansen Date: Fri, 26 Jun 2020 15:26:25 +0000 (-0500) Subject: code cleanup; grouped all binary ops together X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=b00f7a508930a5377eb2b1b25deee255cfeeda70;p=onyx.git code cleanup; grouped all binary ops together --- diff --git a/.vimspector.json b/.vimspector.json index e309f7f9..1ecdcd93 100644 --- a/.vimspector.json +++ b/.vimspector.json @@ -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": [], diff --git a/Makefile b/Makefile index b300bbaf..aa3056cc 100644 --- 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 diff --git a/docs/plan b/docs/plan index c7f8e803..bdc27508 100644 --- 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 diff --git a/include/onyxlex.h b/include/onyxlex.h index 29c1c73a..6a2c7550 100644 --- a/include/onyxlex.h +++ b/include/onyxlex.h @@ -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, diff --git a/include/onyxparser.h b/include/onyxparser.h index f9dceade..1e237912 100644 --- a/include/onyxparser.h +++ b/include/onyxparser.h @@ -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 5c15d2c2..0245333a 100755 Binary files a/onyx and b/onyx differ diff --git a/progs/test.onyx b/progs/test.onyx index 7b492349..c2630139 100644 --- a/progs/test.onyx +++ b/progs/test.onyx @@ -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; } diff --git a/src/onyx.c b/src/onyx.c index a4614528..3d8912ef 100644 --- a/src/onyx.c +++ b/src/onyx.c @@ -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. diff --git a/src/onyxlex.c b/src/onyxlex.c index 9b0c68f9..925d3b03 100644 --- a/src/onyxlex.c +++ b/src/onyxlex.c @@ -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)) { diff --git a/src/onyxparser.c b/src/onyxparser.c index 9a7dbd51..8cf4a513 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -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; diff --git a/src/onyxsymres.c b/src/onyxsymres.c index a03dd614..d5cf6d6e 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -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; diff --git a/src/onyxtypecheck.c b/src/onyxtypecheck.c index 65c687c5..a1846c2f 100644 --- a/src/onyxtypecheck.c +++ b/src/onyxtypecheck.c @@ -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: diff --git a/src/onyxwasm.c b/src/onyxwasm.c index a9c6d22a..02941609 100644 --- a/src/onyxwasm.c +++ b/src/onyxwasm.c @@ -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;