ox

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

commit 91424f0abc67e5b7a09958285ce08f1aca48a474
parent e40c7972195bdd8f1cbf7d81375004092aed71cd
Author: citbl <citbl@citbl.org>
Date:   Sun, 16 Nov 2025 16:30:26 +1000

func calls with parameters and proper scoping

Diffstat:
M.zed/debug.json | 6+++---
Msrc/gen/gen.c | 109++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------
2 files changed, 83 insertions(+), 32 deletions(-)

diff --git a/.zed/debug.json b/.zed/debug.json @@ -6,12 +6,12 @@ { "label": "Debug native binary", "build": { - "command": "make", - "args": ["check"], + "command": "make check", + "args": [], "cwd": "$ZED_WORKTREE_ROOT" }, "program": "$ZED_WORKTREE_ROOT/oxc", - "args": ["$ZED_WORKTREE_ROOT/ex-call-args.ox"], + "args": ["$ZED_WORKTREE_ROOT/tests/ex-call-args-same-names.ox"], "request": "launch", "adapter": "CodeLLDB" } diff --git a/src/gen/gen.c b/src/gen/gen.c @@ -6,6 +6,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <assert.h> #include <sys/param.h> static gcc_jit_type* type_int; @@ -136,14 +137,37 @@ gen_init(Scope* scope, const char* src, Node* node, bool quiet) }; } +static void +push_scope(Gen* gen) +{ + printf("push_scope\n"); + Scope* scope = calloc(1, sizeof(Scope)); + *scope = (Scope) { 0 }; + scope->symbols = (Symbol**)calloc(16, sizeof(Symbol*)); + if (scope->symbols == NULL) panic("push_scope: symbols: could not alloc"); + scope->cap = 16; + scope->len = 0; + + scope->parent = gen->scope; + gen->scope = scope; +} + +static void +pop_scope(Gen* gen) +{ + printf("pop_scope\n"); + Scope* s = gen->scope; + gen->scope = s->parent; +} + static Symbol* -find_symbol(Gen* gen, Span name) +find_symbol(Gen* gen, Scope* scope, Span name) { 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]; + for (size_t i = 0; i < scope->len; i++) { + Symbol* sym = scope->symbols[i]; const char* sym_name = span_str(gen->src, sym->name, (char[IDENTSZ]) { 0 }); // printf("symbol %s\n", sym_name); // printf("ident %s\n", ident_name); @@ -152,16 +176,41 @@ find_symbol(Gen* gen, Span name) return sym; } } - printf("find_symbol: not found: %s!\n", ident_name); + printf("find_symbol: not found locally: %s\n", ident_name); + + if (scope->parent != NULL) { + printf("looking up symbol %s in parent\n", ident_name); + return find_symbol(gen, scope->parent, name); + } + return NULL; } +static void +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[gen->scope->len++] = sym; + + printf("add_symbol: we now have %zu symbols: ", gen->scope->len); + for (size_t i = 0; i < gen->scope->len; i++) { + Symbol* symy = gen->scope->symbols[i]; + const char* name = span_str(gen->src, symy->name, (char[IDENTSZ]) { 0 }); + printf("%s, ", name); + } + printf("\n"); +} + 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); + Symbol* sym = find_symbol(gen, gen->scope, node->data.ident.name); if (sym == NULL) { softpanic("handle_ident_call: undefined variable: %s\n", @@ -328,7 +377,7 @@ handle_unary_expr(Gen* gen, Node* node) gcc_jit_block* bb = gen->curr_block; Node* opnd = node->data.unary_expr.operand; - Symbol* sym = find_symbol(gen, opnd->data.ident.name); + Symbol* sym = find_symbol(gen, gen->scope, 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 })); @@ -507,10 +556,10 @@ lower_builtin_print(Gen* gen, Node* node) } static gcc_jit_function* -lookup_function(Gen* gen, const char* func_name) +lookup_function(Gen* gen, Scope* scope, const char* func_name) { - for (size_t i = 0; i < gen->scope->len; i++) { - Symbol* sym = gen->scope->symbols[i]; + for (size_t i = 0; i < scope->len; i++) { + Symbol* sym = scope->symbols[i]; if (sym->ctype == type_voidp) { const char* name = span_str(gen->src, sym->name, (char[IDENTSZ]) { 0 }); @@ -519,6 +568,14 @@ lookup_function(Gen* gen, const char* func_name) } } } + + printf("lookup_function: not found locally: %s\n", func_name); + + if (scope->parent != NULL) { + printf("looking up function %s in parent\n", func_name); + return lookup_function(gen, scope->parent, func_name); + } + return NULL; } @@ -531,14 +588,12 @@ handle_func_call(Gen* gen, Node* node) // short circuit to print if (strcmp(func_name, "print") == 0) return lower_builtin_print(gen, node); - gcc_jit_function* callee = lookup_function(gen, func_name); + gcc_jit_function* callee = lookup_function(gen, gen->scope, func_name); gcc_jit_location* loc = loc_from_node(gen, node); // args handling - gcc_jit_rvalue* args[16]; size_t argc = node->data.call_expr.len; - - if (argc > 16) { softpanic("we don't currently handle more than 16 arguments in a function call"); } + gcc_jit_rvalue* args[argc]; for (size_t i = 0; i < argc; i++) { args[i] = handle_expr(gen, node->data.call_expr.args[i]); @@ -557,6 +612,9 @@ handle_func_call(Gen* gen, Node* node) gcc_jit_context_new_call(ctx, loc, print_fn, 1, args)); */ + // gcc_jit_rvalue *msg = gcc_jit_param_as_rvalue(callee_param); + // gcc_jit_rvalue *args[1] = { msg }; + assert(callee != NULL && "callee not found"); return gcc_jit_context_new_call(gen->ctx, loc, callee, argc, args); // TODO consider @@ -639,19 +697,6 @@ ox_type_to_c_type(Gen* gen, Node* node) } static void -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[gen->scope->len++] = sym; - - printf("we now have %zu symbols.\n", gen->scope->len); -} - -static void print_symbols_here(Gen* gen) { for (size_t i = 0; i < gen->scope->len; i++) { @@ -910,7 +955,7 @@ build_statement(Gen* gen, Node* node) break; } case NODE_BINARY_EXPR: { - Symbol* sym = find_symbol(gen, node->data.binary_expr.lhs->data.ident.name); + Symbol* sym = find_symbol(gen, gen->scope, node->data.binary_expr.lhs->data.ident.name); if (!sym) softpanic("undefined variable: %s\n", span_str(gen->src, node->data.ident.name, (char[IDENTSZ]) { 0 })); gcc_jit_lvalue* lv = sym->d.lvalue; @@ -1035,8 +1080,8 @@ build_func_decl(Gen* gen, Node* node) gcc_jit_function* prev_func = gen->curr_func; gcc_jit_block* prev_block = gen->curr_block; - gen->curr_block = block; gen->curr_func = func; + gen->curr_block = block; // 3) Add the function symbol to the current (enclosing) scope Symbol* sym = (Symbol*)calloc(1, sizeof(Symbol)); @@ -1045,7 +1090,10 @@ build_func_decl(Gen* gen, Node* node) sym->ctype = type_voidp; // whatever you use for function type metadata sym->d.funcvalue = func; sym->english_type = type_func; - add_symbol(gen, sym); + add_symbol(gen, sym); // to the 'parent scope', before we push_scope + + // ENTER FUNCTION SCOPE + push_scope(gen); // 4) Add parameter symbols to the FUNCTION scope, reusing the same gcc_jit_param* for (size_t i = 0; i < argc; i++) { @@ -1080,6 +1128,9 @@ build_func_decl(Gen* gen, Node* node) gcc_jit_block_end_with_void_return(gen->curr_block, loc); } + // LEAVE FUNCTION SCOPE + pop_scope(gen); + gen->curr_func = prev_func; gen->curr_block = prev_block; }