From d04aea3c5875cd2859d6ab961256b11189c49839 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Thu, 28 Oct 2021 10:40:22 +0200 Subject: Prepare for closure capture --- src/bytecode/vm.h | 53 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 21 deletions(-) (limited to 'src/bytecode/vm.h') diff --git a/src/bytecode/vm.h b/src/bytecode/vm.h index 3fba3d7..a32d0a1 100755 --- a/src/bytecode/vm.h +++ b/src/bytecode/vm.h @@ -13,7 +13,7 @@ typedef struct CallFrame { // Current code being run. - Chunk *chunk; + Closure *closure; // Current program counter for this call. // Ref to stack. Is this really needed? // Object *locals; @@ -65,7 +65,7 @@ vm_reset(VM *vm) { fprintf(stderr, "stack trace:\n"); \ for (ssize_t i = array_size(vm->frames) - 1; i >= 0 ; i--) { \ CallFrame frame = vm->frames[i]; \ - Chunk *chunk = frame.chunk; \ + Chunk *chunk = frame.closure->chunk; \ size_t instruction = vm->pc - chunk->code - 1; \ fprintf(stderr, "\t%-4ld -> ", i); \ fprintf(stderr, "%.*s",(int)array_size(chunk->name), chunk->name); \ @@ -80,8 +80,8 @@ vm_reset(VM *vm) { error_push((Error){ \ .type = ERR_TYPE_RUNTIME, \ .value = (ERR), \ - .line = frame->chunk->lines[vm->pc - frame->chunk->code - 1].line, \ - .col = frame->chunk->lines[vm->pc - frame->chunk->code - 1].col, \ + .line = chunk->lines[vm->pc - chunk->code - 1].line, \ + .col = chunk->lines[vm->pc - chunk->code - 1].col, \ }); \ STACK_TRACE() \ return @@ -149,10 +149,11 @@ vm_reset(VM *vm) { void vm_interpret(VM *vm) { CallFrame *frame = &vm->frames[0]; - vm->pc = frame->chunk->code; + Chunk *chunk = frame->closure->chunk; + vm->pc = chunk->code; frame->rp = NULL; - if (frame->chunk->code == NULL || array_size(frame->chunk->code) == 0) { + if (chunk->code == NULL || array_size(chunk->code) == 0) { error_push((Error){ .type = ERR_TYPE_RUNTIME, .value = ERR_EMPTY_CHUNK, @@ -170,22 +171,31 @@ vm_interpret(VM *vm) { } } printf(" ]\nop: "); - disassemble_instruction(frame->chunk, (vm->pc - frame->chunk->code)); + disassemble_instruction(chunk, (vm->pc - chunk->code)); #endif u8 instruction = *vm->pc++; switch (instruction) { case OP_LOCAL: { ssize_t idx = AS_FIXNUM(array_pop(vm->stack)); - ssize_t depth = AS_FIXNUM(array_pop(vm->stack)); - depth = array_size(vm->frames) - depth; - CallFrame frame = vm->frames[depth]; + CallFrame frame = vm->frames[array_size(vm->frames) - 1]; array_push(vm->stack, vm->stack[frame.stack_offset + idx]); } break; case OP_CONSTANT: { u8 constant = *vm->pc++; - Object obj = frame->chunk->constants[constant]; + Object obj = chunk->constants[constant]; array_push(vm->stack, obj); } break; + case OP_CAPTURED: { + assert(false && "not implemented"); + } break; + case OP_CAPTURE_LOCAL: { + assert(false && "not implemented"); + // Object value = array_pop(vm->stack); + // ssize_t idx = AS_FIXNUM(array_pop(vm->stack)); + // ssize_t depth = AS_FIXNUM(array_pop(vm->stack)); + // CallFrame frame = vm->frames[depth]; + // vm->stack[frame.stack_offset + idx] = value; + } break; case OP_DEF_LOCAL: { Object value = array_pop(vm->stack); ssize_t idx = AS_FIXNUM(array_pop(vm->stack)); @@ -194,8 +204,7 @@ vm_interpret(VM *vm) { case OP_SET_LOCAL: { Object value = array_pop(vm->stack); ssize_t idx = AS_FIXNUM(array_pop(vm->stack)); - ssize_t depth = AS_FIXNUM(array_pop(vm->stack)); - CallFrame frame = vm->frames[depth]; + CallFrame frame = vm->frames[array_size(vm->frames) - 1]; vm->stack[frame.stack_offset + idx] = value; } break; case OP_DEF: { @@ -290,8 +299,8 @@ vm_interpret(VM *vm) { // Check the number of arguments is correct. // NOTE: This is probably better handled at compilation, but for // now this is simpler to implement. - ssize_t n_params = proc.chunk->n_params; - ssize_t n_locals = proc.chunk->n_locals - n_params; + ssize_t n_params = proc.closure->chunk->n_params; + ssize_t n_locals = proc.closure->chunk->n_locals - n_params; if (n_args < n_params) { RUNTIME_ERROR(ERR_NOT_ENOUGH_ARGS); } else if (n_args > n_params) { @@ -299,20 +308,21 @@ vm_interpret(VM *vm) { } #ifdef DEBUG - disassemble_chunk(proc.chunk); + disassemble_chunk(proc.closure->chunk); printf("n_locals: %ld\n", n_locals); printf("n_params: %ld\n", n_params); #endif // Tail-call optimization. - if (proc.chunk != frame->chunk || *vm->pc != OP_RETURN) { + if (proc.closure->chunk != chunk || *vm->pc != OP_RETURN) { // Prepare new call frame. CallFrame new_frame = (CallFrame){ - .chunk = proc.chunk, + .closure = proc.closure, .rp = vm->pc, .stack_offset = array_size(vm->stack) - n_params, }; array_push(vm->frames, new_frame); frame = &vm->frames[array_size(vm->frames) - 1]; + chunk = frame->closure->chunk; // Prepare local slots. for (ssize_t i = 0; i < n_locals; i++) { @@ -330,7 +340,7 @@ vm_interpret(VM *vm) { size_t offset = frame->stack_offset + n_params + n_locals; array_head(vm->stack)->size = offset; } - vm->pc = frame->chunk->code; + vm->pc = chunk->code; } break; case OP_RETURN: { if (frame->rp == NULL) { @@ -347,6 +357,7 @@ vm_interpret(VM *vm) { array_head(vm->stack)->size = frame->stack_offset; array_push(vm->stack, ret); frame = &vm->frames[array_size(vm->frames) - 1]; + chunk = frame->closure->chunk; } break; case OP_DROP: { array_head(vm->stack)->size = 0; @@ -360,8 +371,8 @@ vm_interpret(VM *vm) { error_push((Error){ .type = ERR_TYPE_RUNTIME, .value = ERR_PC_OOB, - .line = frame->chunk->lines[0].line, - .col = frame->chunk->lines[0].col, + .line = chunk->lines[0].line, + .col = chunk->lines[0].col, }); } -- cgit v1.2.1