From e48386449b1f50c9f9d9b0645c8c469c1d4cbe4a Mon Sep 17 00:00:00 2001 From: ubq323 Date: Tue, 25 Jun 2024 15:23:44 +0100 Subject: allow local resolution into outer scopes --- com.c | 32 +++++++++++++++++--------------- tests/vars3.bth | 6 ++++++ tests/vars3.out | 1 + todo | 3 +-- 4 files changed, 25 insertions(+), 17 deletions(-) create mode 100644 tests/vars3.bth create mode 100644 tests/vars3.out diff --git a/com.c b/com.c index c5362cd..a3cc5a8 100644 --- a/com.c +++ b/com.c @@ -244,6 +244,16 @@ static void declare_local(Compiler *C, char *name) { l->slot = C->stack_cur - 1; // printf("declaring local %s at %d, stack_cur is %d\n",l->name, l->slot, C->stack_cur); } +static Local *locate_local(Compiler *C, char *name) { + for (Scope *sc = C->scope; sc != NULL; sc = sc->outer) { + for (int i = 0; i < sc->nlocals; i++) { + Local *loc = &sc->locals[i]; + if (0 == strcmp(loc->name, name)) + return loc; + } + } + return NULL; +} void let_form(Compiler *C, AstVec l, Op _) { CHECK(l.vals[1].ty == AST_LIST, "let's first argument must be list"); @@ -345,6 +355,8 @@ static BuiltinIdent builtin_idents[] = { { 0 }, }; + + static void compile_node(Compiler *C, AstNode a) { switch (a.ty) { case AST_IDENT:; @@ -358,21 +370,11 @@ static void compile_node(Compiler *C, AstNode a) { } } if (!found_builtin) { - // read local or global variable - bool found_local = false; - if (C->scope != NULL) { - Scope *sc = C->scope; - for (int i = 0; i < sc->nlocals; i++) { - Local loc = sc->locals[i]; - if (0 == strcmp(ident, loc.name)) { - compile_opcode(C, OP_GETLOCAL); - compile_byte(C, loc.slot); - found_local = true; - break; - } - } - } - if (!found_local) { + Local *loc = locate_local(C, ident); + if (loc != NULL) { + compile_opcode(C, OP_GETLOCAL); + compile_byte(C, loc->slot); + } else { // read global ObjString *o = objstring_copy_cstr(C->S, a.as.str); compile_opcode(C, OP_GETGLOBAL); diff --git a/tests/vars3.bth b/tests/vars3.bth new file mode 100644 index 0000000..19e82fa --- /dev/null +++ b/tests/vars3.bth @@ -0,0 +1,6 @@ +(do + (set x 1) + (set y 10) + (let (x 2) + (let (y 20) + (+ x y)))) diff --git a/tests/vars3.out b/tests/vars3.out new file mode 100644 index 0000000..2bd5a0a --- /dev/null +++ b/tests/vars3.out @@ -0,0 +1 @@ +22 diff --git a/todo b/todo index 2e920ed..f724c3a 100644 --- a/todo +++ b/todo @@ -1,5 +1,4 @@ -functions, returning -locals, lexical scoping, closures, upvalues +closures, upvalues lists, hashes, other useful types garbage collector macros -- cgit v1.2.3