ox

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

commit 9f0b5e9d7ae7671c422f1b7fe85151f630e1a4df
parent 938420285b53653449172e0a7ccaef79406583dd
Author: citbl <citbl@citbl.org>
Date:   Mon,  6 Oct 2025 17:03:54 +1000

basic int handling

Diffstat:
M.zed/debug.json | 2+-
Mex2.ox | 2+-
Mgen/gen.c | 81++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------
Mmakefile | 2+-
Mparser.h | 2+-
5 files changed, 64 insertions(+), 25 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/ex10.ox"], + "args": ["$ZED_WORKTREE_ROOT/ex2.ox"], "request": "launch", "adapter": "CodeLLDB" } diff --git a/ex2.ox b/ex2.ox @@ -3,6 +3,6 @@ // T add(T a, b) inline pure => a + b; void main() { - string name = "harrold"; + int peter = 42; print("harold"); } diff --git a/gen/gen.c b/gen/gen.c @@ -1,6 +1,7 @@ #include "../gen.h" #include "../utils.h" +#include <_string.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> @@ -15,6 +16,19 @@ static gcc_jit_type* type_cstr; #define MAXARGS 16 +gcc_jit_location* +loc_from_node(Gen* gen, Node* node) +{ + if(node->filename == NULL) + exit(1); + if(node->line == NULL) + exit(1); + if(node->col == NULL) + exit(1); + + return gcc_jit_context_new_location(gen->ctx, node->filename, node->line, node->col); +} + Gen gen_init(Scope* scope, const char* src) { @@ -30,8 +44,8 @@ gen_init(Scope* scope, const char* src) // 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_DUMP_INITIAL_TREE, - // 1); low level gcc_jit_context_set_bool_option(ctx, - // GCC_JIT_BOOL_OPTION_DUMP_INITIAL_GIMPLE, 1); info + // 1); low level + 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_str_option(ctx, GCC_JIT_STR_OPTION_PROGNAME, "ox"); @@ -88,6 +102,13 @@ emit_literal_string(Gen* gen, Node* node) return gcc_jit_context_new_string_literal(gen->ctx, str); } +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); +} + static void build_program(Gen* gen, Node* node) { @@ -108,9 +129,11 @@ lower_builtin_print(Gen* gen, Node* node) = handle_expr(gen, node->data.call_expr.args[0]); // TODO [0] when many // cast common cases to const char* if (gcc_jit_rvalue_get_type(arg) != type_cstr) - arg = gcc_jit_context_new_cast(gen->ctx, NULL, 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, NULL, gen->puts_fn, 1, args); + return gcc_jit_context_new_call( + gen->ctx, loc_from_node(gen, node), gen->puts_fn, 1, args); } // softpanic("we don't currently handle formatted strings to print"); @@ -119,14 +142,13 @@ lower_builtin_print(Gen* gen, Node* node) // // 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*)); @@ -140,7 +162,8 @@ lower_builtin_print(Gen* gen, Node* node) 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, NULL, arg, type_cstr); + arg = gcc_jit_context_new_cast( + gen->ctx, loc_from_node(gen, node), arg, type_cstr); } } else { // @@ -148,7 +171,8 @@ 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, NULL, arg, type_cstr); + arg = gcc_jit_context_new_cast( + gen->ctx, loc_from_node(gen, node), arg, type_cstr); } else if (ty == type_float) { // variadics already promote float→double; double is } else if (ty == type_cstr) { @@ -156,7 +180,7 @@ lower_builtin_print(Gen* gen, Node* node) } else { // fallback: pass pointer as void* arg = gcc_jit_context_new_cast(gen->ctx, - NULL, + loc_from_node(gen, node), arg, gcc_jit_context_get_type(gen->ctx, GCC_JIT_TYPE_VOID_PTR)); } @@ -168,11 +192,11 @@ lower_builtin_print(Gen* gen, Node* node) return NULL; } -static gcc_jit_function* -lookup_function(Gen* gen, const char* func_name) -{ - // TODO see todo below about linked list parameters... -} +// static gcc_jit_function* +// lookup_function(Gen* gen, const char* func_name) +// { +// // TODO see todo below about linked list parameters... +// } static gcc_jit_rvalue* handle_func_call(Gen* gen, Node* node) @@ -182,6 +206,7 @@ handle_func_call(Gen* gen, Node* node) if (strcmp(func_name, "print") == 0) return lower_builtin_print(gen, node); softpanic("unhandled func call named: %s", func_name); + return NULL; // // TODO handle any function other than print... @@ -222,9 +247,20 @@ build_statement(Gen* gen, Node* node) break; case NODE_RETURN: break; + case NODE_VAR_DECL: { + gcc_jit_location* loc = loc_from_node(gen, node); + const char* var_name + = span_str(gen->src, node->data.var_decl.name, (char[IDENTSZ]) { 0 }); + gcc_jit_lvalue* var = gcc_jit_function_new_local(gen->curr_func, + loc, + type_int, + strdup(var_name)); // to be initialised + gcc_jit_rvalue* integer_value = emit_literal_int(gen, node->data.var_decl.init); + gcc_jit_block_add_assignment(gen->curr_block, loc, var, integer_value); + } break; 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, NULL, rv); + if (rv) gcc_jit_block_add_eval(gen->curr_block, loc_from_node(gen, node), rv); } break; default: printf("build_statement unhandled, %s\n", node_type_str(node->type)); @@ -244,7 +280,7 @@ static void build_func_decl(Gen* gen, Node* node) { gcc_jit_function* func = gcc_jit_context_new_function(gen->ctx, - NULL, // loc + loc_from_node(gen, node), GCC_JIT_FUNCTION_EXPORTED, // declared type_int, // ret "main", // name @@ -287,6 +323,9 @@ gen_next(Gen* gen, Node* node) case NODE_STRING_LITERAL: emit_literal_string(gen, node); break; + case NODE_NUMBER_LITERAL: + emit_literal_int(gen, node); + break; default: printf("unhandled, %s\n", node_type_str(node->type)); } diff --git a/makefile b/makefile @@ -22,7 +22,7 @@ BIN = oxc STD = -std=c99 default: - cc ${STD} -g -Wall -Wextra -Wpedantic -Wshadow -Wconversion -Wno-unused-function -o ${BIN} ${SRC} ${LIB} + cc ${STD} -g -Wall -Wextra -Wno-unused-parameter -Wno-unused-function -o ${BIN} ${SRC} ${LIB} # -Wpedantic -Wshadow -Wconversion clean: rm -rf ${BIN} ${BIN}.* err.log diff --git a/parser.h b/parser.h @@ -91,7 +91,7 @@ typedef struct Node { struct Node* next; struct Scope* scope; const char* filename; - size_t line, col; + int line, col; /* NOTE we will eventually add spans for condition info, etc. to print out in errors */