aboutsummaryrefslogtreecommitdiffstats
path: root/src/bytecode/compiler.h
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 /src/bytecode/compiler.h
parent8c8353dab0b4a7f6ed9332f968a5b5da67375f62 (diff)
downloadbdl-7264715260fe0235413b6bd0cf6ee339e3328dc2.tar.gz
bdl-7264715260fe0235413b6bd0cf6ee339e3328dc2.zip
Add OP_SET_CAPTURED operation
Diffstat (limited to 'src/bytecode/compiler.h')
-rwxr-xr-xsrc/bytecode/compiler.h50
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);