From: Brendan Hansen Date: Sat, 20 Jun 2020 20:10:29 +0000 (-0500) Subject: Added if statements X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=fa710a01039be5e0c3b45c7b78a8a0aa68817574;p=onyx.git Added if statements --- diff --git a/include/onyxlex.h b/include/onyxlex.h index 97754648..c9a4632a 100644 --- a/include/onyxlex.h +++ b/include/onyxlex.h @@ -14,6 +14,7 @@ typedef enum OnyxTokenType { TOKEN_TYPE_KEYWORD_EXPORT, TOKEN_TYPE_KEYWORD_IF, TOKEN_TYPE_KEYWORD_ELSE, + TOKEN_TYPE_KEYWORD_ELSEIF, TOKEN_TYPE_KEYWORD_FOR, TOKEN_TYPE_KEYWORD_DO, TOKEN_TYPE_KEYWORD_RETURN, diff --git a/include/onyxparser.h b/include/onyxparser.h index 91dc48ff..081e2adc 100644 --- a/include/onyxparser.h +++ b/include/onyxparser.h @@ -11,6 +11,7 @@ typedef struct OnyxAstNodeNumLit OnyxAstNodeNumLit; typedef struct OnyxAstNodeLocal OnyxAstNodeLocal; typedef struct OnyxAstNodeScope OnyxAstNodeScope; typedef struct OnyxAstNodeBlock OnyxAstNodeBlock; +typedef struct OnyxAstNodeIf OnyxAstNodeIf; typedef struct OnyxAstNodeParam OnyxAstNodeParam; typedef struct OnyxAstNodeFuncDef OnyxAstNodeFuncDef; typedef struct OnyxAstNodeForeign OnyxAstNodeForeign; @@ -162,6 +163,16 @@ struct OnyxAstNodeBlock { OnyxAstNodeScope *scope; // NOTE: Only set on blocks belonging to functions }; +struct OnyxAstNodeIf { + OnyxAstNodeKind kind; + u32 flags; + OnyxToken *token; // NOTE: UNUSED + OnyxAstNode *false_block; + OnyxAstNode *next; + OnyxAstNode *cond; + OnyxAstNode *true_block; +}; + struct OnyxAstNodeFuncDef { OnyxAstNodeKind kind; u32 flags; @@ -215,6 +226,7 @@ union OnyxAstNode { OnyxAstNodeCall as_call; OnyxAstNodeNumLit as_numlit; OnyxAstNodeForeign as_foreign; + OnyxAstNodeIf as_if; }; const char* onyx_ast_node_kind_string(OnyxAstNodeKind kind); diff --git a/onyx b/onyx index ea67fa4b..20ab6643 100755 Binary files a/onyx and b/onyx differ diff --git a/progs/minimal.onyx b/progs/minimal.onyx index a78a82af..818a598a 100644 --- a/progs/minimal.onyx +++ b/progs/minimal.onyx @@ -33,6 +33,14 @@ float_test :: proc -> f32 { export main :: proc { output := do_stuff(); + if output + 66 { + new_output :: -output * 2; + print(new_output); + + } else { + print(-1); + }; + print(output); print_float(float_test()); diff --git a/progs/test.onyx b/progs/test.onyx new file mode 100644 index 00000000..5c6f3671 --- /dev/null +++ b/progs/test.onyx @@ -0,0 +1,17 @@ + +// Foreign functions are included this way: +// sym_name :: foreign "module" "name" proc ... +print :: foreign "host" "print" proc (value i32) --- + +get_value :: foreign "env" "get_val" proc -> i32 --- + + + +// This is the entry point +export main :: proc { + nineteen :: 5 * 3 + 4; + thirty_five :: 5 * (3 + 4) + get_value(); + + print(nineteen); + print(thirty_five); +} diff --git a/src/onyxlex.c b/src/onyxlex.c index d0069690..3ed4c58f 100644 --- a/src/onyxlex.c +++ b/src/onyxlex.c @@ -12,6 +12,7 @@ static const char* onyx_token_type_names[] = { "export", //"TOKEN_TYPE_KEYWORD_EXPORT", "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", @@ -138,6 +139,7 @@ OnyxToken* onyx_get_token(OnyxTokenizer* tokenizer) { 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); diff --git a/src/onyxparser.c b/src/onyxparser.c index 07cbfd1b..0eaa4db1 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -341,7 +341,7 @@ static inline i32 get_precedence(OnyxAstNodeKind kind) { static OnyxAstNode* parse_expression(OnyxParser* parser) { bh_arr(OnyxAstNode*) tree_stack = NULL; - bh_arr_new(global_scratch_allocator, tree_stack, 1); + bh_arr_new(global_scratch_allocator, tree_stack, 4); bh_arr_set_length(tree_stack, 0); OnyxAstNode* left = parse_factor(parser); @@ -413,7 +413,39 @@ expression_done: } static OnyxAstNode* parse_if_stmt(OnyxParser* parser) { - return &error_node; + expect(parser, TOKEN_TYPE_KEYWORD_IF); + + OnyxAstNode* cond = parse_expression(parser); + OnyxAstNode* true_block = (OnyxAstNode *) parse_block(parser, 0); + + OnyxAstNodeIf* if_node = (OnyxAstNodeIf *) onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_IF); + OnyxAstNodeIf* root_if = if_node; + + if_node->cond = cond; + if_node->true_block = true_block->as_block.body; + + while (parser->curr_token->type == TOKEN_TYPE_KEYWORD_ELSEIF) { + parser_next_token(parser); + OnyxAstNodeIf* elseif_node = (OnyxAstNodeIf *) onyx_ast_node_new(parser->allocator, ONYX_AST_NODE_KIND_IF); + + cond = parse_expression(parser); + true_block = (OnyxAstNode *) parse_block(parser, 0); + + elseif_node->cond = cond; + elseif_node->true_block = true_block->as_block.body; + + if_node->false_block = (OnyxAstNode *) 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, 0); + if_node->false_block = false_block->as_block.body; + } + + return (OnyxAstNode *) root_if; } // Returns 1 if the symbol was consumed. Returns 0 otherwise diff --git a/src/onyxutils.c b/src/onyxutils.c index 77cd47d0..5070e721 100644 --- a/src/onyxutils.c +++ b/src/onyxutils.c @@ -143,6 +143,23 @@ void onyx_ast_print(OnyxAstNode* node, i32 indent) { break; } + case ONYX_AST_NODE_KIND_IF: { + OnyxAstNodeIf* if_node = &node->as_if; + if (if_node->cond) { + onyx_ast_print(if_node->cond, indent + 1); + } + if (if_node->true_block) { + onyx_ast_print(if_node->true_block, indent + 1); + } + if (if_node->false_block) { + onyx_ast_print(if_node->false_block, indent + 1); + } + if (if_node->next) { + onyx_ast_print(if_node->next, indent); + } + break; + } + default: { onyx_ast_print(node->left, indent + 1); onyx_ast_print(node->right, indent + 1); diff --git a/src/onyxwasm.c b/src/onyxwasm.c index ce965f20..09091992 100644 --- a/src/onyxwasm.c +++ b/src/onyxwasm.c @@ -213,6 +213,7 @@ static void process_block(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNodeBlock* static void process_statement(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* stmt); static void process_assign_lval(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* lval); static void process_assignment(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* assign); +static void process_if(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNodeIf* if_node); static void process_expression(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* expr); static void process_cast(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* cast); static void process_return(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* ret); @@ -242,6 +243,7 @@ static void process_statement(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* case ONYX_AST_NODE_KIND_SCOPE: break; case ONYX_AST_NODE_KIND_RETURN: process_return(mod, func, stmt); break; case ONYX_AST_NODE_KIND_ASSIGNMENT: process_assignment(mod, func, stmt); break; + case ONYX_AST_NODE_KIND_IF: process_if(mod, func, (OnyxAstNodeIf *) stmt); break; default: process_expression(mod, func, stmt); } } @@ -256,6 +258,28 @@ static void process_assign_lval(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode } } +static void process_if(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNodeIf* if_node) { + process_expression(mod, func, if_node->cond); + bh_arr_push(func->code, ((WasmInstruction){ WI_IF_START, 0x40 })); + + if (if_node->true_block) { + // NOTE: This is kind of gross, but making a function for this doesn't feel right + forll (OnyxAstNode, stmt, if_node->true_block, next) { + process_statement(mod, func, stmt); + } + } + + if (if_node->false_block) { + bh_arr_push(func->code, ((WasmInstruction){ WI_ELSE, 0x00 })); + + forll (OnyxAstNode, stmt, if_node->false_block, next) { + process_statement(mod, func, stmt); + } + } + + bh_arr_push(func->code, ((WasmInstruction){ WI_IF_END, 0x00 })); +} + static void process_assignment(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* assign) { process_expression(mod, func, assign->right); process_assign_lval(mod, func, assign->left); @@ -915,6 +939,7 @@ static void output_instruction(WasmInstruction* instr, bh_buffer* buff) { case WI_LOCAL_SET: case WI_CALL: case WI_BLOCK_START: + case WI_IF_START: leb = uint_to_uleb128((u64) instr->data.i1, &leb_len); bh_buffer_append(buff, leb, leb_len); break;