summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorubq323 <ubq323@ubq323.website>2024-06-25 15:23:44 +0100
committerubq323 <ubq323@ubq323.website>2024-06-25 15:23:44 +0100
commite48386449b1f50c9f9d9b0645c8c469c1d4cbe4a (patch)
tree633eadafb39f383899fa681aa68248f5b1f0a99e
parent6aef97b52844b8868e5ada38ce0936619c1077a7 (diff)
allow local resolution into outer scopes
-rw-r--r--com.c32
-rw-r--r--tests/vars3.bth6
-rw-r--r--tests/vars3.out1
-rw-r--r--todo3
4 files changed, 25 insertions, 17 deletions
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