diff options
-rwxr-xr-x | src/bytecode/compiler.h | 50 | ||||
-rwxr-xr-x | src/bytecode/debug.h | 1 | ||||
-rwxr-xr-x | src/bytecode/ops.h | 2 | ||||
-rwxr-xr-x | src/bytecode/vm.h | 7 |
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)); |