commit 61c13e81caf86e7a92f5bbd3eb7819ec4a565566
parent 52d5fb89bc8d20bdc529ed2c8cd34f19bc11e95d
Author: citbl <citbl@citbl.org>
Date: Mon, 27 Oct 2025 21:05:11 +1000
wip for loop, array subscript done
Diffstat:
13 files changed, 400 insertions(+), 94 deletions(-)
diff --git a/.clang-format b/.clang-format
@@ -19,7 +19,7 @@ AlignConsecutiveMacros: false
SortIncludes: false
IndentCaseLabels: false
-ColumnLimit: 150
+ColumnLimit: 100
PenaltyBreakBeforeFirstCallParameter: 1
AlignAfterOpenBracket: DontAlign
BinPackArguments: false
diff --git a/.zed/debug.json b/.zed/debug.json
@@ -6,12 +6,12 @@
{
"label": "Debug native binary",
"build": {
- "command": "make",
+ "command": "make check",
"args": ["debug"],
"cwd": "$ZED_WORKTREE_ROOT"
},
"program": "$ZED_WORKTREE_ROOT/oxc",
- "args": ["$ZED_WORKTREE_ROOT/ex123.ox"],
+ "args": ["$ZED_WORKTREE_ROOT/ex-subscript-simple.ox"],
"request": "launch",
"adapter": "CodeLLDB"
}
diff --git a/README b/README
@@ -0,0 +1,17 @@
+ _,.---._ ,-.--,
+ ,-.' , - `..--.-. /=/, .'
+ /==/_, , - \==\ -\/=/- /
+|==| .=. \==\ `-' ,/
+|==|_ : ;=: - ||==|, - |
+|==| , '=' /==/ , \
+ \==\ - ,_ /==/, .--, - \
+ '.='. - .'\==\- \/=/ , /
+ `--`--'' `--`-' `--`
+
+ ,,,,,,,,,,,,,,,,,,,,,,,,,,,,
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ Ox Programming language
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ```````````````````````````
+
+ WIP
diff --git a/README.md b/README.md
@@ -1,3 +0,0 @@
-### Ox Programming language
-
-WIP
diff --git a/TODO b/TODO
@@ -16,3 +16,4 @@
[x] redo arguments as list and not linked list, handle in parse and in gen (2 places in gen?)
[x] get rid of count_args and search for 'argc'
+[ ] printing -5 crashes, I think parsing is wrong for `-`, sees as value 5
diff --git a/ex-decl-no-init.ox b/ex-decl-no-init.ox
@@ -0,0 +1,3 @@
+void main() {
+ int i;
+}
diff --git a/ex-for-simple1.ox b/ex-for-simple1.ox
@@ -1,6 +1,6 @@
void main() {
- int i;
- for(i = 0; i < 5; i++) {
+ int i = 0;
+ for(i = 0; i < 5; i = i + 1) {
print("bozo!");
}
}
diff --git a/ex-subscript-simple.ox b/ex-subscript-simple.ox
@@ -0,0 +1,6 @@
+void main() {
+ int i = 0;
+ print(i);
+ i++;
+ print(i);
+}
diff --git a/src/gen.h b/src/gen.h
@@ -5,6 +5,12 @@
#include "types.h"
+typedef struct LoopContext {
+ gcc_jit_block* break_target;
+ gcc_jit_block* continue_target;
+ struct LoopContext* prev;
+} LoopContext;
+
typedef struct {
gcc_jit_context* ctx;
gcc_jit_function* prev_func;
@@ -15,6 +21,7 @@ typedef struct {
gcc_jit_block* curr_block;
// gcc_jit_type *type_kind; need type too?
Scope* scope;
+ LoopContext* loop;
const char* src;
} Gen;
diff --git a/src/gen/gen.c b/src/gen/gen.c
@@ -24,6 +24,37 @@ loc_from_node(Gen* gen, Node* node)
return gcc_jit_context_new_location(gen->ctx, node->filename, node->line, node->col);
}
+static void
+push_loop(Gen* gen, gcc_jit_block* brk, gcc_jit_block* cont)
+{
+ LoopContext* lctx = (LoopContext*)malloc(sizeof(LoopContext));
+ if (lctx == NULL) { panic("push_loop: could not alloc"); }
+ lctx->break_target = brk;
+ lctx->continue_target = cont;
+ lctx->prev = gen->loop;
+ gen->loop = lctx;
+}
+
+static void
+pop_loop(Gen* gen)
+{
+ LoopContext* lctx = gen->loop;
+ gen->loop = lctx->prev;
+ free(lctx);
+}
+
+static inline gcc_jit_block*
+current_break(Gen* gen)
+{
+ return gen->loop ? gen->loop->break_target : NULL;
+}
+
+static inline gcc_jit_block*
+current_continue(Gen* gen)
+{
+ return gen->loop ? gen->loop->continue_target : NULL;
+}
+
Gen
gen_init(Scope* scope, const char* src, Node* node, bool quiet)
{
@@ -36,14 +67,17 @@ gen_init(Scope* scope, const char* src, Node* node, bool quiet)
if (!ctx) { panic("could not acquire gcc jit context"); }
// needs loc* to work
- // gcc_jit_context_set_bool_option(ctx, GCC_JIT_BOOL_OPTION_DEBUGINFO, 1);
- // high level
+ // gcc_jit_context_set_bool_option(ctx, GCC_JIT_BOOL_OPTION_DEBUGINFO,
+ // 1); high level
gcc_jit_context_set_bool_option(ctx, GCC_JIT_BOOL_OPTION_DEBUGINFO, 1);
- if (quiet == false) { gcc_jit_context_set_bool_option(ctx, GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE, 1); }
+ if (quiet == false) {
+ gcc_jit_context_set_bool_option(ctx, GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE, 1);
+ }
- // gcc_jit_context_set_bool_option(ctx, GCC_JIT_BOOL_OPTION_DUMP_SUMMARY, 1);
+ // gcc_jit_context_set_bool_option(ctx,
+ // GCC_JIT_BOOL_OPTION_DUMP_SUMMARY, 1);
gcc_jit_context_set_str_option(ctx, GCC_JIT_STR_OPTION_PROGNAME, "ox");
// keep FP
@@ -63,7 +97,8 @@ gen_init(Scope* scope, const char* src, Node* node, bool quiet)
gcc_jit_location* loc = gcc_jit_context_new_location(ctx, node->filename, 0, 0);
gcc_jit_param* pm_puts[] = { gcc_jit_context_new_param(ctx, loc, type_cstr, "s") };
- gcc_jit_function* fn_puts = gcc_jit_context_new_function(ctx, loc, GCC_JIT_FUNCTION_IMPORTED, type_int, "puts", 1, pm_puts, 0);
+ gcc_jit_function* fn_puts = gcc_jit_context_new_function(
+ ctx, loc, GCC_JIT_FUNCTION_IMPORTED, type_int, "puts", 1, pm_puts, 0);
gcc_jit_param* pm_printf[] = { gcc_jit_context_new_param(ctx, loc, type_cstr, "fmt") };
gcc_jit_function* fn_printf = gcc_jit_context_new_function(ctx,
@@ -88,25 +123,78 @@ gen_init(Scope* scope, const char* src, Node* node, bool quiet)
};
}
-static gcc_jit_rvalue*
-handle_ident_call(Gen* gen, Node* node)
+static Symbol*
+find_symbol(Gen* gen, Span name)
{
- // Look up the symbol in the current scope // TODO look up in parent scope with utility function and recursion
+ const char* ident_name = span_str(gen->src, name, (char[IDENTSZ]) { 0 });
+ // Look up the symbol in the current scope // TODO look up in parent
+ // scope with utility function and recursion
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);
-
- const char* ident_name = span_str(gen->src, node->data.ident.name, (char[IDENTSZ]) { 0 });
// printf("ident %s\n", 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);
+ printf("found symbol %s\n", sym_name);
+ return sym;
}
}
+ printf("find_symbol: not found: %s!\n", ident_name);
+ return NULL;
+}
- softpanic("undefined variable: %s\n", span_str(gen->src, node->data.ident.name, (char[IDENTSZ]) { 0 }));
+static gcc_jit_rvalue*
+handle_ident_call(Gen* gen, Node* node)
+{
+ // Look up the symbol in the current scope // TODO look up in parent
+ // scope with utility function and recursion
+ Symbol* sym = find_symbol(gen, node->data.ident.name);
+
+ if (sym == NULL) {
+ softpanic("handle_ident_call: undefined variable: %s\n",
+ span_str(gen->src, node->data.ident.name, (char[IDENTSZ]) { 0 }));
+ }
+ return gcc_jit_lvalue_as_rvalue(sym->d.lvalue);
+}
+
+static gcc_jit_rvalue*
+handle_unary_expr(Gen* gen, Node* node)
+{
+ gcc_jit_context* ctx = gen->ctx;
+ gcc_jit_block* bb = gen->curr_block;
+
+ Node* opnd = node->data.unary_expr.operand;
+ Symbol* sym = find_symbol(gen, opnd->data.ident.name);
+ if (sym == NULL) {
+ softpanic("handle_unary_expr: undefined variable: %s\n",
+ span_str(gen->src, opnd->data.ident.name, (char[IDENTSZ]) { 0 }));
+ }
+
+ // gcc_jit_lvalue* lv = gcc_jit_rvalue_dereference(, NULL);
+ gcc_jit_lvalue* lv = sym->d.lvalue;
+ gcc_jit_rvalue* orig = gcc_jit_lvalue_as_rvalue(sym->d.lvalue);
+ gcc_jit_type* ty = gcc_jit_rvalue_get_type(orig);
+ gcc_jit_rvalue* one = gcc_jit_context_one(ctx, ty);
+
+ gcc_jit_rvalue* inc
+ = gcc_jit_context_new_binary_op(ctx, NULL, GCC_JIT_BINARY_OP_PLUS, ty, orig, one);
+ switch (node->data.unary_expr.op) {
+ case OPER_POSTINC: { // i++
+ gcc_jit_block_add_assignment(bb, NULL, lv, inc);
+ return orig; // return value before incr as ++ is postfix
+
+ if (lv == NULL) {
+ printf("handle_unary_expr: no lvalue\n");
+ return NULL;
+ }
+ printf("wef\n");
+ break;
+ }
+ default:
+ printf("handle_unary_expr, unhandled op %d\n", node->data.unary_expr.op);
+ return NULL;
+ break;
+ }
return NULL;
}
@@ -126,13 +214,15 @@ emit_literal_string(Gen* gen, Node* node)
static gcc_jit_rvalue*
emit_literal_int(Gen* gen, Node* node)
{
- return gcc_jit_context_new_rvalue_from_int(gen->ctx, type_int, (int)node->data.number.value);
+ return gcc_jit_context_new_rvalue_from_int(
+ gen->ctx, type_int, (int)node->data.number.value);
}
static gcc_jit_rvalue*
emit_literal_float(Gen* gen, Node* node)
{
- return gcc_jit_context_new_rvalue_from_double(gen->ctx, type_double, node->data.number.value);
+ return gcc_jit_context_new_rvalue_from_double(
+ gen->ctx, type_double, node->data.number.value);
}
static void
@@ -143,46 +233,113 @@ build_program(Gen* gen, Node* node)
gen_next(gen, node->data.program.decl[i]);
}
}
+static inline int
+is_intlike(gcc_jit_context* ctx, gcc_jit_type* t)
+{
+ return t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_INT)
+ || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UNSIGNED_INT)
+ || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_SHORT)
+ || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UNSIGNED_SHORT)
+ || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_LONG)
+ || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UNSIGNED_LONG)
+ || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_LONG_LONG)
+ || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UNSIGNED_LONG_LONG)
+ || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_INT64_T)
+ || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_INT32_T)
+ || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_CHAR)
+ || t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_UNSIGNED_CHAR);
+}
+static inline int
+is_cstr(gcc_jit_context* ctx, gcc_jit_type* t)
+{
+ return t == gcc_jit_context_get_type(ctx, GCC_JIT_TYPE_CONST_CHAR_PTR);
+}
static gcc_jit_rvalue*
lower_builtin_print(Gen* gen, Node* node)
{
size_t argc = node->data.call_expr.len;
+ for (size_t i = 0; i < argc; i++) {
+ Node* arg = node->data.call_expr.args[i];
+ }
+
// 1-arg, treat as puts(arg)
if (argc == 1) {
- gcc_jit_rvalue* arg = handle_expr(gen, node->data.call_expr.args[0]); // TODO [0] when many
+ gcc_jit_rvalue* arg = handle_expr(gen, node->data.call_expr.args[0]);
+ gcc_jit_type* t = gcc_jit_rvalue_get_type(arg);
+ gcc_jit_location* loc = loc_from_node(gen, node->data.call_expr.args[0]);
+ // print a string
+ if (is_cstr(gen->ctx, t)) {
+ gcc_jit_rvalue* args[] = { arg };
+ return gcc_jit_context_new_call(gen->ctx, loc, gen->puts_fn, 1, args);
+ }
+ // print a integer
+ else if (is_intlike(gen->ctx, t)) {
+ // cast to int for a clean %d
+ gcc_jit_type* t_int = gcc_jit_context_get_type(gen->ctx, GCC_JIT_TYPE_INT64_T);
+ gcc_jit_rvalue* fmt = gcc_jit_context_new_string_literal(gen->ctx, "%d\n");
+ gcc_jit_rvalue* ival = arg;//(t == t_int)
+ //? arg
+ //: gcc_jit_context_new_cast(gen->ctx, NULL, arg, t_int);
+ gcc_jit_rvalue* args[] = { fmt, ival };
+ return gcc_jit_context_new_call(gen->ctx, loc, gen->printf_fn, 2, args);
+ }
// cast common cases to const char*
- // if (gcc_jit_rvalue_get_type(arg) != type_cstr) arg = gcc_jit_context_new_cast(gen->ctx, loc_from_node(gen, node), arg, type_cstr);
- gcc_jit_rvalue* args[] = { arg };
- return gcc_jit_context_new_call(gen->ctx, loc_from_node(gen, node), gen->puts_fn, 1, args);
+ // if (gcc_jit_rvalue_get_type(arg) != type_cstr) arg =
+ // gcc_jit_context_new_cast(gen->ctx, loc_from_node(gen, node),
+ // arg, type_cstr);
+
+ // gcc_jit_rvalue* args[] = { arg };
+ // return gcc_jit_context_new_call(
+ // gen->ctx, loc_from_node(gen, node), gen->puts_fn, 1, args);
+
+ // gcc_jit_type* type_of_args = gcc_jit_rvalue_get_type(arg);
+ // switch (type_of_args) {
+ // case GCC_JIT_TYPE_CONST_CHAR_PTR:
+
+ // break;
+ // default:
+ // printf("lower_builtin_print: unhandled type passed %s\n", type_of_args);
+ // break;
+ // }
}
+ return NULL;
+
// softpanic("we don't currently handle formatted strings to print");
- // n>=1, treat as printf(fmt, ...) // Part of TODO about args as list and not
+ // n>=1, treat as printf(fmt, ...) // Part of TODO about args as list
+ // and not
//
- // through each args, form the ("formatted %s string %d etc.", str, intv) for clib's printf
+ // through each args, form the ("formatted %s string %d etc.", str,
+ // intv) for clib's printf
- // TODO we're talking about formatting here, which we plan on doing as a string
- // interpolation, something along the lines of {{variable}} without defining its type would
- // involve lookup split of the string and then formatting
+ // TODO we're talking about formatting here, which we plan on doing as a
+ // string interpolation, something along the lines of {{variable}}
+ // without defining its type would involve lookup split of the string
+ // and then formatting
- // we need to discuss and decide what we'd do when the user inevitably would print out a ref
- // to a struct. Do we say [[struct]] or do we have some automatic unwrap and display of
- // struct data... probably, yes.
+ // we need to discuss and decide what we'd do when the user inevitably
+ // would print out a ref to a struct. Do we say [[struct]] or do we have
+ // some automatic unwrap and display of struct data... probably, yes.
gcc_jit_rvalue** args = (gcc_jit_rvalue**)calloc(MAXARGS, sizeof(gcc_jit_rvalue*));
- if (argc > MAXARGS) { softpanic("we do not currently support more than 16 args to a print call"); }
+ if (argc > MAXARGS) {
+ softpanic("we do not currently support more than 16 args to a "
+ "print call");
+ }
for (size_t i = 0; i < argc; i++) {
gcc_jit_rvalue* arg = handle_expr(gen, node->data.call_expr.args[i]);
if (i == 0) {
if (gcc_jit_rvalue_get_type(arg) != type_cstr) {
- // note this is probably not going to work as limited cast supported
- // and string isn't one of them
- arg = gcc_jit_context_new_cast(gen->ctx, loc_from_node(gen, node), arg, type_cstr);
+ // note this is probably not going to work as
+ // limited cast supported and string isn't one
+ // of them
+ arg = gcc_jit_context_new_cast(
+ gen->ctx, loc_from_node(gen, node), arg, type_cstr);
}
} else {
//
@@ -190,15 +347,19 @@ lower_builtin_print(Gen* gen, Node* node)
//
gcc_jit_type* ty = gcc_jit_rvalue_get_type(arg);
if (ty == type_int) {
- arg = gcc_jit_context_new_cast(gen->ctx, loc_from_node(gen, node), arg, type_cstr);
+ arg = gcc_jit_context_new_cast(
+ gen->ctx, loc_from_node(gen, node), arg, type_cstr);
} else if (ty == type_double) {
- // variadics already promote float→double; double is
+ // variadics already promote float→double;
+ // double is
} else if (ty == type_cstr) {
// leave as const char*
} else {
// fallback: pass pointer as void*
- arg = gcc_jit_context_new_cast(
- gen->ctx, loc_from_node(gen, node), arg, gcc_jit_context_get_type(gen->ctx, GCC_JIT_TYPE_VOID_PTR));
+ arg = gcc_jit_context_new_cast(gen->ctx,
+ loc_from_node(gen, node),
+ arg,
+ gcc_jit_context_get_type(gen->ctx, GCC_JIT_TYPE_VOID_PTR));
}
}
// TODO auto grow
@@ -253,10 +414,13 @@ handle_expr(Gen* gen, Node* node)
case NODE_CALL_EXPR:
return handle_func_call(gen, node);
break;
- case NODE_IDENT: {
+ case NODE_IDENT:
return handle_ident_call(gen, node);
break;
- }
+ case NODE_UNARY_EXPR: // ++ etc.
+ return handle_unary_expr(gen, node);
+ break;
+
// case NODE_IDENT: {
// return NULL; // fixme
// break;
@@ -293,7 +457,8 @@ add_symbol(Gen* gen, Symbol* sym)
{
if (gen->scope->len == gen->scope->cap) {
gen->scope->cap *= 2;
- gen->scope->symbols = (Symbol**)realloc(gen->scope->symbols, sizeof(Symbol*) * gen->scope->cap);
+ gen->scope->symbols
+ = (Symbol**)realloc(gen->scope->symbols, sizeof(Symbol*) * gen->scope->cap);
}
gen->scope->symbols[gen->scope->len++] = sym;
@@ -302,6 +467,8 @@ add_symbol(Gen* gen, Symbol* sym)
static bool build_block(Gen*, Node*);
static bool build_statement(Gen*, Node*);
+static gcc_jit_rvalue* build_bool_value(Gen*, Node*);
+
static int block_counter = 0, loop_counter = 0;
static bool
@@ -311,47 +478,71 @@ build_for_statement(Gen* gen, Node* node)
entry → (init) → [head: cond?] ──T──> (body) ──continue──> (step) ──┐
└──F───────────────────> (end) → next
^
- └── back to [head]
+ └── back to
+ [head]
*/
- // gcc_jit_location* loc = loc_from_node(gen, node);
+ gcc_jit_location* loc = loc_from_node(gen, node);
- // Node* init = node->data.for_statement.init;
- // Node* cond = node->data.for_statement.cond;
- // Node* step = node->data.for_statement.increment;
- // Node* body = node->data.for_statement.body;
+ Node* init = node->data.for_statement.init;
+ Node* cond = node->data.for_statement.cond;
+ Node* step = node->data.for_statement.increment;
+ Node* body = node->data.for_statement.body;
- // loop_counter++;
+ loop_counter++;
- // char label_cond[64], label_body[64], label_step[64], label_end[64];
- // snprintf(label_cond, 64, "for.cond%d", loop_counter);
- // snprintf(label_body, 64, "for.body%d", loop_counter);
- // snprintf(label_step, 64, "for.step%d", loop_counter);
- // snprintf(label_end, 64, "for.end%d", loop_counter);
+ char label_cond[64], label_body[64], label_step[64], label_end[64];
+ snprintf(label_cond, 64, "for.cond%d", loop_counter);
+ snprintf(label_body, 64, "for.body%d", loop_counter);
+ snprintf(label_step, 64, "for.step%d", loop_counter);
+ snprintf(label_end, 64, "for.end%d", loop_counter);
- // gcc_jit_block* cond_block = gcc_jit_function_new_block(gen->curr_func, label_cond);
- // gcc_jit_block* body_block = gcc_jit_function_new_block(gen->curr_func, label_body);
- // gcc_jit_block* step_block = gcc_jit_function_new_block(gen->curr_func, label_step);
- // gcc_jit_block* end_block = gcc_jit_function_new_block(gen->curr_func, label_end);
+ gcc_jit_block* cond_block = gcc_jit_function_new_block(gen->curr_func, label_cond);
+ gcc_jit_block* body_block = gcc_jit_function_new_block(gen->curr_func, label_body);
+ gcc_jit_block* step_block = gcc_jit_function_new_block(gen->curr_func, label_step);
+ gcc_jit_block* end_block = gcc_jit_function_new_block(gen->curr_func, label_end);
- // // header, e.g. for(int = 0 <-
- // if (init) { build_statement(gen, init); }
+ // gcc_jit_block* saved_break = gen->loop->break_target;
+ // gcc_jit_block* saved_cont = gen->loop->continue_target;
+ // gen->loop->break_target = end_block;
+ // gen->loop->continue_target = step_block;
- // // jump to cond e.g. ; i < 5 <-
- // gcc_jit_block_end_with_jump(gen->curr_block, loc, cond_block);
+ // header, e.g. for(int = 0 <-
+ if (init) { build_statement(gen, init); }
- // // cond: evaluate
- // gen->curr_block = cond_block;
- // gcc_jit_rvalue* cnd = NULL;
+ // jump to cond e.g. ; i < 5 <-
+ gcc_jit_block_end_with_jump(gen->curr_block, loc, cond_block);
- // if (cond != NULL) {
- // // cnd = build_bool_rvalue(gen, cond);
- // // TODO our parsing needs to handle the int i = 0;
- // // need to handle binary_expr like if
- // // or check if it's already a bool
- // // or check if it's numbers(?)
- // }
+ // cond: evaluate
+ gen->curr_block = cond_block;
+ gcc_jit_rvalue* cnd = NULL;
+
+ if (cond != NULL) {
+ cnd = build_bool_value(gen, cond);
+ gcc_jit_block_end_with_conditional(cond_block, loc, cnd, body_block, end_block);
+ } else {
+ gcc_jit_block_end_with_jump(cond_block, loc, body_block); // presume for(;;)
+ }
+
+ push_loop(gen, /*break to*/ end_block, /*continue to*/ step_block);
+
+ // build for body
+
+ gen->curr_block = body_block;
+ bool for_body_ended = build_block(gen, body);
+ if (!for_body_ended) { gcc_jit_block_end_with_jump(gen->curr_block, loc, step_block); }
+
+ pop_loop(gen);
+
+ // step incr etc.
+ gen->curr_block = step_block;
+ if (step) { build_statement(gen, step); }
+ gcc_jit_block_end_with_jump(step_block, loc, end_block);
+
+ // resume after loop
+
+ gen->curr_block = end_block;
return false;
}
@@ -403,7 +594,8 @@ build_if_statement(Gen* gen, Node* node)
// blocks
gcc_jit_block* then_bb = gcc_jit_function_new_block(gen->curr_func, label_then);
- gcc_jit_block* else_bb = else_body ? gcc_jit_function_new_block(gen->curr_func, label_else) : NULL;
+ gcc_jit_block* else_bb
+ = else_body ? gcc_jit_function_new_block(gen->curr_func, label_else) : NULL;
gcc_jit_block* merge_bb = NULL;
if (!else_bb) {
@@ -418,7 +610,8 @@ build_if_statement(Gen* gen, Node* node)
// THEN
gen->curr_block = then_bb;
bool then_ended = build_block(gen, then_body);
- gcc_jit_block* then_open = gen->curr_block; // last open block in THEN (may differ from then_bb)
+ gcc_jit_block* then_open = gen->curr_block; // last open block in THEN
+ // (may differ from then_bb)
// ELSE
bool else_ended = false;
@@ -429,7 +622,8 @@ build_if_statement(Gen* gen, Node* node)
else_open = gen->curr_block; // last open block in ELSE
}
- // If both branches ended, no merge needed, we notify we have ended as well
+ // If both branches ended, no merge needed, we notify we have ended as
+ // well
if (else_bb && then_ended && else_ended) return true;
// Ensure we have a merge if any branch continues.
@@ -450,14 +644,21 @@ build_var_decl_statement(Gen* gen, Node* node)
gcc_jit_type* declared_type = ox_type_to_c_type(gen, node->data.var_decl.type);
gcc_jit_lvalue* var_decl = NULL;
- gcc_jit_rvalue* rvalue = handle_expr(gen, node->data.var_decl.init);
+
+ gcc_jit_rvalue* rvalue = NULL;
+ Node* init = node->data.var_decl.init;
+ if (init != NULL) { rvalue = handle_expr(gen, init); }
if (gen->curr_func == NULL && gen->curr_block == NULL) {
- var_decl = gcc_jit_context_new_global(gen->ctx, loc, GCC_JIT_GLOBAL_INTERNAL, declared_type, strdup(var_name));
- gcc_jit_global_set_initializer_rvalue(var_decl, rvalue);
+ // global var
+ var_decl = gcc_jit_context_new_global(
+ gen->ctx, loc, GCC_JIT_GLOBAL_INTERNAL, declared_type, strdup(var_name));
+ if (rvalue) gcc_jit_global_set_initializer_rvalue(var_decl, rvalue);
} else {
- var_decl = gcc_jit_function_new_local(gen->curr_func, loc, declared_type, strdup(var_name));
- gcc_jit_block_add_assignment(gen->curr_block, loc, var_decl, rvalue);
+ // local var
+ var_decl = gcc_jit_function_new_local(
+ gen->curr_func, loc, declared_type, strdup(var_name));
+ if (rvalue) gcc_jit_block_add_assignment(gen->curr_block, loc, var_decl, rvalue);
}
if (node->data.var_decl.init == NULL) { panic("could not instanciate gcc jit new local"); }
@@ -486,6 +687,20 @@ build_statement(Gen* gen, Node* node)
gen->curr_block = NULL; // important
return true; // we end the block here
}
+ case NODE_BREAK: {
+ gcc_jit_block* t = current_break(gen);
+ if (!t) return true; // break outside the loop
+ gcc_jit_block_end_with_jump(gen->curr_block, loc, t);
+ gen->curr_block = NULL;
+ return true;
+ }
+ case NODE_CONTINUE: {
+ gcc_jit_block* t = current_continue(gen);
+ if (!t) return true; // continue outside of a loop
+ gcc_jit_block_end_with_jump(gen->curr_block, loc, t);
+ gen->curr_block = NULL;
+ return true;
+ }
case NODE_VAR_DECL: {
return build_var_decl_statement(gen, node);
}
@@ -494,19 +709,33 @@ build_statement(Gen* gen, Node* node)
// find the var_decl (d.lvalue) from the symbols table's symbol.
for (size_t i = 0; i < gen->scope->len; i++) {
Symbol* sym = gen->scope->symbols[i];
- if (span_ident_same(sym->name, node->data.var_assign.lhs->data.ident.name, gen->src)) {
+ if (span_ident_same(sym->name,
+ node->data.var_assign.lhs->data.ident.name,
+ gen->src)) {
// we found the symbol we are assigning to
gcc_jit_lvalue* lvalue = sym->d.lvalue;
// 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 (lvalue) gcc_jit_block_add_assignment(gen->curr_block, loc, lvalue, rvalue);
+ 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);
}
}
break;
}
+ case NODE_BINARY_EXPR: {
+ printf("TODO NODE_BINARY_EXPR\nTODO NODE_BINARY_EXPR\nTODO "
+ "NODE_BINARY_EXPR\nTODO\n");
+ }
+
case NODE_EXPR_STATEMENT: {
gcc_jit_rvalue* rv = handle_expr(gen, node->data.expr_statement.expr);
if (rv) gcc_jit_block_add_eval(gen->curr_block, loc_from_node(gen, node), rv);
@@ -523,6 +752,46 @@ build_statement(Gen* gen, Node* node)
return false;
}
+static gcc_jit_rvalue*
+build_bool_value(Gen* gen, Node* node)
+{
+ gcc_jit_location* loc = loc_from_node(gen, node);
+
+ switch (node->type) {
+ case NODE_BINARY_EXPR: {
+ gcc_jit_rvalue* lvalue = handle_expr(gen, node->data.binary_expr.lhs);
+ gcc_jit_rvalue* rvalue = handle_expr(gen, node->data.binary_expr.rhs);
+ enum gcc_jit_comparison op;
+ switch (node->data.binary_expr.op) {
+ case OP_LT:
+ op = GCC_JIT_COMPARISON_LT;
+ break;
+ case OP_GT:
+ op = GCC_JIT_COMPARISON_GT;
+ break;
+ case OP_LT_EQ:
+ op = GCC_JIT_COMPARISON_LE;
+ break;
+ case OP_GT_EQ:
+ op = GCC_JIT_COMPARISON_GE;
+ break;
+ default:
+ printf("build_bool_rvalue nodebinary op unhandled, "
+ "%s\n",
+ node_type_str(node->type));
+ return NULL;
+ }
+ return gcc_jit_context_new_comparison(gen->ctx, loc, op, lvalue, rvalue);
+ break;
+ }
+ default:
+ printf("build_bool_rvalue unhandled, %s\n", node_type_str(node->type));
+ break;
+ }
+
+ return NULL;
+}
+
// build_block: returns true if block ended with a terminator
static bool
build_block(Gen* gen, Node* body)
@@ -538,7 +807,8 @@ build_block(Gen* gen, Node* body)
static void
build_func_decl(Gen* gen, Node* node)
{
- const char* func_name = span_str(gen->src, node->data.function_decl.name, (char[IDENTSZ]) { 0 });
+ const char* func_name
+ = span_str(gen->src, node->data.function_decl.name, (char[IDENTSZ]) { 0 });
Node* return_type = node->data.function_decl.return_type;
gcc_jit_type* ret_type = ox_type_to_c_type(gen, return_type);
@@ -563,12 +833,15 @@ build_func_decl(Gen* gen, Node* node)
build_block(gen, node->data.function_decl.body);
if (gen->curr_block && ret_type == type_int) { // TODO handle more return types
- gcc_jit_rvalue* ret_value = gcc_jit_context_new_rvalue_from_int(gen->ctx, type_int, 0);
+ 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 if (gen->curr_block && ret_type == type_void) {
gcc_jit_block_end_with_void_return(gen->curr_block, loc);
} else {
- printf("build_func_decl unhandled return type in func: %s - defaulting to void\n", func_name);
+ printf("build_func_decl unhandled return type in func: %s - "
+ "defaulting to void\n",
+ func_name);
gcc_jit_block_end_with_void_return(gen->curr_block, loc);
}
diff --git a/src/parser.h b/src/parser.h
@@ -29,6 +29,7 @@ Node* parse_unary(Parser*);
Node* parse_term(Parser*);
Node* parse_expression(Parser*);
Node* parse_expression_statement(Parser*);
+Node* parse_assignment_expr(Parser*);
Node* parse_statement(Parser*);
Node* parse_block(Parser*);
Node* parse_declaration_statement(Parser*);
diff --git a/src/parser/parser.c b/src/parser/parser.c
@@ -115,13 +115,13 @@ parse_relational(Parser* par)
for (;;) {
if (match(par, TOKEN_LT)) {
Node* rhs = parse_additive(par);
- node = make_binary_node('<', node, rhs);
+ node = make_binary_node(OP_LT, node, rhs);
} else if (match(par, TOKEN_LT_EQ)) {
Node* rhs = parse_additive(par);
node = make_binary_node(OP_LT_EQ, node, rhs);
} else if (match(par, TOKEN_GT)) {
Node* rhs = parse_additive(par);
- node = make_binary_node('>', node, rhs);
+ node = make_binary_node(OP_GT, node, rhs);
} else if (match(par, TOKEN_GT_EQ)) {
Node* rhs = parse_additive(par);
node = make_binary_node(OP_GT_EQ, node, rhs);
@@ -172,7 +172,7 @@ parse_equality(Parser* par)
return node;
}
-static Node*
+Node*
parse_assignment_expr(Parser* par)
{
Node* left = parse_equality(par);
diff --git a/src/parser/stmt.c b/src/parser/stmt.c
@@ -61,6 +61,7 @@ parse_for(Parser* par)
if (tok2.type == TOKEN_IDENT) {
init = parse_declaration_statement(par);
} else {
+ // TODO check: init = parse_assignment_expr(par);
init = parse_expression_statement(par);
}
} else