diff options
Diffstat (limited to 'src/bytecode/compiler.h')
-rwxr-xr-x | src/bytecode/compiler.h | 50 |
1 files changed, 29 insertions, 21 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); |