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,
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;
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;
OnyxAstNodeCall as_call;
OnyxAstNodeNumLit as_numlit;
OnyxAstNodeForeign as_foreign;
+ OnyxAstNodeIf as_if;
};
const char* onyx_ast_node_kind_string(OnyxAstNodeKind kind);
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());
--- /dev/null
+
+// 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);
+}
"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",
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);
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);
}
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
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);
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);
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);
}
}
}
}
+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);
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;