ox

The Ox programming language, compiler and tools (WIP)
Log | Files | Refs | README | LICENSE

commit ecc6a44d87f87542ed5b3da1fb88fad2e32132b6
parent a30c84cfa89fefe405d9727ff9c6fbb3823c4f31
Author: citbl <citbl@citbl.org>
Date:   Thu, 23 Oct 2025 20:28:05 +1000

wip if nested

Diffstat:
M.zed/debug.json | 2+-
Mex3.ox | 12++++++++++--
Msrc/gen.h | 1+
Msrc/gen/gen.c | 93++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
Msrc/parser/parser.c | 26+++++++++++++++++++++++++-
Msrc/types.h | 2+-
6 files changed, 123 insertions(+), 13 deletions(-)

diff --git a/.zed/debug.json b/.zed/debug.json @@ -11,7 +11,7 @@ "cwd": "$ZED_WORKTREE_ROOT" }, "program": "$ZED_WORKTREE_ROOT/oxc", - "args": ["$ZED_WORKTREE_ROOT/ex12.ox"], + "args": ["$ZED_WORKTREE_ROOT/ex3.ox"], "request": "launch", "adapter": "CodeLLDB" } diff --git a/ex3.ox b/ex3.ox @@ -1,7 +1,15 @@ // conditional to be handled void main() { - if (a == true) { - print("conditional test passed"); + print("did it work?"); + string password = "123"; + if (password == "1234") { + print("it worked!"); + } else { + if(password == "123") { + print("the else worked!"); + } else { + print("booboo"); + } } } diff --git a/src/gen.h b/src/gen.h @@ -16,6 +16,7 @@ typedef struct { // gcc_jit_type *type_kind; need type too? Scope* scope; const char* src; + bool block_terminated; } Gen; Gen gen_init(Scope*, const char*, Node*, bool); diff --git a/src/gen/gen.c b/src/gen/gen.c @@ -95,12 +95,11 @@ handle_ident_call(Gen* gen, Node* node) for (size_t i = 0; i < gen->scope->len; i++) { Symbol* sym = gen->scope->symbols[i]; const char* sym_name = span_str(gen->src, sym->name, (char[IDENTSZ]) { 0 }); - printf("symbol %s\n", sym_name); + // printf("symbol %s\n", sym_name); const char* ident_name = span_str(gen->src, node->data.ident.name, (char[IDENTSZ]) { 0 }); - printf("ident %s\n", ident_name); + // printf("ident %s\n", ident_name); - printf("comparing: %s vs. %s\n", sym_name, ident_name); if (strncmp(sym_name, ident_name, strlen(sym_name)) == 0) { printf("found %s\n", sym_name); return gcc_jit_lvalue_as_rvalue(sym->d.lvalue); @@ -301,6 +300,18 @@ add_symbol(Gen* gen, Symbol* sym) } static void +end_jump_if_needed(Gen* gen, gcc_jit_location* loc, gcc_jit_block* target) +{ + if (!gen->block_terminated && gen->curr_block) { + gcc_jit_block_end_with_jump(gen->curr_block, loc, target); + gen->block_terminated = true; + } +} + +static void build_block(Gen* gen, Node* body); +static int block_counter = 0; + +static void build_statement(Gen* gen, Node* node) { switch (node->type) { @@ -349,9 +360,7 @@ build_statement(Gen* gen, Node* node) // check the type of lvalue matches the rvalue gcc_jit_type* ltype = sym->ctype; gcc_jit_type* rtype = gcc_jit_rvalue_get_type(rvalue); - if (rtype != ltype) { - panic_at(node, "right hand side of assigment doesn't match the type of the left hand side"); - } + if (rtype != ltype) { panic_at(node, "right hand side of assigment doesn't match the type of the left hand side"); } if (lvalue) gcc_jit_block_add_assignment(gen->curr_block, loc, lvalue, rvalue); } } @@ -362,6 +371,75 @@ build_statement(Gen* gen, Node* node) if (rv) gcc_jit_block_add_eval(gen->curr_block, loc_from_node(gen, node), rv); break; } + case NODE_IF: { + gcc_jit_location* loc = loc_from_node(gen, node); + + // build the condition + + OpType op = node->data.if_statement.cond->data.binary_expr.op; + Node* lhs = node->data.if_statement.cond->data.binary_expr.lhs; + Node* rhs = node->data.if_statement.cond->data.binary_expr.rhs; + + Node* then_body = node->data.if_statement.then_body; + Node* else_body = node->data.if_statement.else_body; + + enum gcc_jit_comparison cmp; + switch (op) { + case OP_EQUALITY: + cmp = GCC_JIT_COMPARISON_EQ; + break; + case OP_INEQUALITY: + cmp = GCC_JIT_COMPARISON_NE; + break; + default: + printf("build_statement NODE_IF unhandled, %d\n", op); + cmp = GCC_JIT_COMPARISON_EQ; + } + + gcc_jit_rvalue* lhs_val = handle_expr(gen, lhs); + gcc_jit_rvalue* rhs_val = handle_expr(gen, rhs); + + gcc_jit_rvalue* cond = gcc_jit_context_new_comparison(gen->ctx, loc, cmp, lhs_val, rhs_val); + + // create the BLOCKS + + // labels + block_counter++; + char label_then[64], label_else[64], label_end[64]; + snprintf(label_then, 64, "if.then%d", block_counter); + snprintf(label_else, 64, "if.else%d", block_counter); + snprintf(label_end, 64, "if.end%d", block_counter); + + // blocks + gcc_jit_block* then_block = gcc_jit_function_new_block(gen->curr_func, label_then); + gcc_jit_block* merge_block = gcc_jit_function_new_block(gen->curr_func, label_else); + gcc_jit_block* else_block = else_body ? gcc_jit_function_new_block(gen->curr_func, label_else) : NULL; + + // rig the jumps + + gcc_jit_block_end_with_conditional(gen->curr_block, loc, cond, then_block, else_body ? else_block : merge_block); + + // build THEN + + gen->curr_block = then_block; + gen->block_terminated = false; + build_block(gen, then_body); + end_jump_if_needed(gen, loc, merge_block); + + // build ELSE block (optional) + if (else_block != NULL) { + gen->curr_block = else_block; + gen->block_terminated = false; + build_block(gen, else_body); + end_jump_if_needed(gen, loc, merge_block); + } + + // continue after if, note that the original block is terminated. + gen->curr_block = merge_block; + gen->block_terminated = false; + + break; + } default: printf("build_statement unhandled, %s\n", node_type_str(node->type)); break; @@ -406,11 +484,10 @@ build_func_decl(Gen* gen, Node* node) gcc_jit_rvalue* ret_value = gcc_jit_context_new_rvalue_from_int(gen->ctx, type_int, 0); gcc_jit_block_end_with_return(gen->curr_block, loc, ret_value); } else { + printf("build_func_decl unhandled return type, %s\n", node_type_str(node->type)); gcc_jit_block_end_with_void_return(gen->curr_block, loc); } - gen->curr_block = NULL; - gen->curr_func = prev_func; gen->curr_block = prev_block; } diff --git a/src/parser/parser.c b/src/parser/parser.c @@ -135,6 +135,28 @@ static Node* parse_equality(Parser* par) { Node* node = parse_relational(par); + + // TODO handle all enum gcc_jit_comparison + // { + // /* (EXPR_A) == (EXPR_B). */ + // GCC_JIT_COMPARISON_EQ, + + // /* (EXPR_A) != (EXPR_B). */ + // GCC_JIT_COMPARISON_NE, + + // /* (EXPR_A) < (EXPR_B). */ + // GCC_JIT_COMPARISON_LT, + + // /* (EXPR_A) <=(EXPR_B). */ + // GCC_JIT_COMPARISON_LE, + + // /* (EXPR_A) > (EXPR_B). */ + // GCC_JIT_COMPARISON_GT, + + // /* (EXPR_A) >= (EXPR_B). */ + // GCC_JIT_COMPARISON_GE + // }; + for (;;) { if (match(par, TOKEN_EQUALITY)) { // "==" Node* rhs = parse_relational(par); @@ -142,8 +164,10 @@ parse_equality(Parser* par) } else if (match(par, TOKEN_INEQUALITY)) { // "!=" Node* rhs = parse_relational(par); node = make_binary_node(OP_INEQUALITY, node, rhs); - } else + } else { + perror("unhandled parse_equality token"); break; + } } return node; } diff --git a/src/types.h b/src/types.h @@ -115,7 +115,7 @@ typedef enum { */ typedef enum { - OP_PLUS = 23, + OP_PLUS = 300, OP_MINUS, OP_MUL, OP_DIV,