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:
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;
}