aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-10-28 12:26:14 +0200
committerBad Diode <bd@badd10de.dev>2021-10-28 12:26:14 +0200
commit7264715260fe0235413b6bd0cf6ee339e3328dc2 (patch)
tree776e8b8ba93bd1a95f277d5577647972c6af93c1
parent8c8353dab0b4a7f6ed9332f968a5b5da67375f62 (diff)
downloadbdl-7264715260fe0235413b6bd0cf6ee339e3328dc2.tar.gz
bdl-7264715260fe0235413b6bd0cf6ee339e3328dc2.zip
Add OP_SET_CAPTURED operation
-rwxr-xr-xsrc/bytecode/compiler.h50
-rwxr-xr-xsrc/bytecode/debug.h1
-rwxr-xr-xsrc/bytecode/ops.h2
-rwxr-xr-xsrc/bytecode/vm.h7
4 files changed, 37 insertions, 23 deletions
diff --git a/src/bytecode/compiler.h b/src/bytecode/compiler.h
index d35c7c6..bc39d47 100755
--- a/src/bytecode/compiler.h
+++ b/src/bytecode/compiler.h
@@ -171,8 +171,6 @@ parse_symbol(Chunk *chunk, Compiler *compiler, Token tok) {
171 } 171 }
172 172
173 // TODO: Capture globals? 173 // TODO: Capture globals?
174
175 // NOTE: set! must know how to deal also with captured vars.
176 } 174 }
177 175
178 Object obj = make_symbol(tok.value); 176 Object obj = make_symbol(tok.value);
@@ -326,28 +324,38 @@ compile_declare_op(Chunk *chunk, Compiler *compiler, Token start, Ops op) {
326 } 324 }
327 emit_constant(chunk, name, FIXNUM_VAL(idx)); 325 emit_constant(chunk, name, FIXNUM_VAL(idx));
328 } else if (op == OP_SET) { 326 } else if (op == OP_SET) {
329 size_t depth = compiler->scope_depth - 1; 327 // FIXME: This is fucking ugly.
328 Scope *current_scope = get_current_scope(compiler);
330 ssize_t idx = -1; 329 ssize_t idx = -1;
331 // Check if name is local in this or any previous scope. 330 // Check if the variable was already captured.
332 do { 331 idx = find_captued_index(current_scope, name);
333 Scope *scope = &compiler->scopes[depth];
334 idx = find_local_index(scope, name);
335 if (idx >= 0) {
336 break;
337 }
338 depth--;
339 } while (depth > 0);
340
341 if (idx >= 0) { 332 if (idx >= 0) {
342 // If the value is found emit OP_SET_LOCAL with tree parameters:
343 // The new value, the scope depth, and the scope index.
344 op = OP_SET_LOCAL;
345 emit_constant(chunk, name, FIXNUM_VAL(depth));
346 emit_constant(chunk, name, FIXNUM_VAL(idx)); 333 emit_constant(chunk, name, FIXNUM_VAL(idx));
334 op = OP_SET_CAPTURED;
347 } else { 335 } else {
348 // If not found at all, emit set for the global scope. 336 idx = find_local_index(current_scope, name);
349 Object obj = make_symbol(name.value); 337 if (idx >= 0) {
350 emit_constant(chunk, name, obj); 338 emit_constant(chunk, name, FIXNUM_VAL(idx));
339 op = OP_SET_LOCAL;
340 } else {
341 size_t depth = compiler->scope_depth - 2;
342 while (depth > 0) {
343 Scope *scope = &compiler->scopes[depth];
344 idx = find_local_index(scope, name);
345 if (idx >= 0) {
346 op = OP_SET_CAPTURED;
347 ssize_t captured_idx = array_size(current_scope->captured);
348 emit_constant(chunk, name, FIXNUM_VAL(captured_idx));
349 array_push(current_scope->captured, name);
350 break;
351 }
352 depth--;
353 }
354 if (idx < 0) {
355 Object obj = make_symbol(name.value);
356 emit_constant(chunk, name, obj);
357 }
358 }
351 } 359 }
352 } 360 }
353 } 361 }
@@ -471,7 +479,7 @@ compile_lambda(Chunk *chunk, Compiler *compiler, Token start, StringView name) {
471 size_t n_captured = array_size(scope->captured); 479 size_t n_captured = array_size(scope->captured);
472 if (n_captured > 0) { 480 if (n_captured > 0) {
473 compiler->scope_depth--; 481 compiler->scope_depth--;
474 for (ssize_t i = 0; i < n_captured; i++) { 482 for (size_t i = 0; i < n_captured; i++) {
475 Token tok = scope->captured[i]; 483 Token tok = scope->captured[i];
476 print_token(tok); 484 print_token(tok);
477 parse_symbol(chunk, compiler, tok); 485 parse_symbol(chunk, compiler, tok);
diff --git a/src/bytecode/debug.h b/src/bytecode/debug.h
index 7078744..b21d8e6 100755
--- a/src/bytecode/debug.h
+++ b/src/bytecode/debug.h
@@ -13,6 +13,7 @@ static const char* ops_str[] = {
13 [OP_LOCAL] = "OP_LOCAL", 13 [OP_LOCAL] = "OP_LOCAL",
14 [OP_CAPTURED] = "OP_CAPTURED", 14 [OP_CAPTURED] = "OP_CAPTURED",
15 [OP_CAPTURE_LOCAL] = "OP_CAPTURE_LOCAL", 15 [OP_CAPTURE_LOCAL] = "OP_CAPTURE_LOCAL",
16 [OP_SET_CAPTURED] = "OP_SET_CAPTURED",
16 [OP_DEF_LOCAL] = "OP_DEF_LOCAL", 17 [OP_DEF_LOCAL] = "OP_DEF_LOCAL",
17 [OP_SET_LOCAL] = "OP_SET_LOCAL", 18 [OP_SET_LOCAL] = "OP_SET_LOCAL",
18 [OP_DEF] = "OP_DEF", 19 [OP_DEF] = "OP_DEF",
diff --git a/src/bytecode/ops.h b/src/bytecode/ops.h
index d45c27e..a43aed6 100755
--- a/src/bytecode/ops.h
+++ b/src/bytecode/ops.h
@@ -7,7 +7,7 @@ typedef enum Ops {
7 OP_LOCAL, 7 OP_LOCAL,
8 OP_CAPTURED, 8 OP_CAPTURED,
9 OP_CAPTURE_LOCAL, 9 OP_CAPTURE_LOCAL,
10 // OP_SET_CAPTURED, 10 OP_SET_CAPTURED,
11 OP_DEF_LOCAL, 11 OP_DEF_LOCAL,
12 OP_SET_LOCAL, 12 OP_SET_LOCAL,
13 OP_DEF, 13 OP_DEF,
diff --git a/src/bytecode/vm.h b/src/bytecode/vm.h
index f1c525d..4ff9743 100755
--- a/src/bytecode/vm.h
+++ b/src/bytecode/vm.h
@@ -191,12 +191,17 @@ vm_interpret(VM *vm) {
191 case OP_CAPTURE_LOCAL: { 191 case OP_CAPTURE_LOCAL: {
192 Object proc = array_pop(vm->stack); 192 Object proc = array_pop(vm->stack);
193 ssize_t n_captured = AS_FIXNUM(array_pop(vm->stack)); 193 ssize_t n_captured = AS_FIXNUM(array_pop(vm->stack));
194 for (size_t i = 0; i < n_captured; i++) { 194 for (ssize_t i = 0; i < n_captured; i++) {
195 Object value = array_pop(vm->stack); 195 Object value = array_pop(vm->stack);
196 array_push(proc.closure->values, value); 196 array_push(proc.closure->values, value);
197 } 197 }
198 array_push(vm->stack, proc); 198 array_push(vm->stack, proc);
199 } break; 199 } break;
200 case OP_SET_CAPTURED: {
201 Object value = array_pop(vm->stack);
202 ssize_t idx = AS_FIXNUM(array_pop(vm->stack));
203 frame->closure->values[idx] = value;
204 } break;
200 case OP_DEF_LOCAL: { 205 case OP_DEF_LOCAL: {
201 Object value = array_pop(vm->stack); 206 Object value = array_pop(vm->stack);
202 ssize_t idx = AS_FIXNUM(array_pop(vm->stack)); 207 ssize_t idx = AS_FIXNUM(array_pop(vm->stack));