diff options
-rwxr-xr-x | src/bytecode/vm.h | 22 |
1 files changed, 15 insertions, 7 deletions
diff --git a/src/bytecode/vm.h b/src/bytecode/vm.h index 98c94fa..6c44fc6 100755 --- a/src/bytecode/vm.h +++ b/src/bytecode/vm.h | |||
@@ -261,13 +261,21 @@ vm_interpret(VM *vm) { | |||
261 | } break; | 261 | } break; |
262 | case OP_CALL: { | 262 | case OP_CALL: { |
263 | Object proc = array_pop(vm->stack); | 263 | Object proc = array_pop(vm->stack); |
264 | CallFrame new_frame = (CallFrame){ | 264 | |
265 | .chunk = proc.chunk, | 265 | // Tail-call optimization. |
266 | .rp = vm->pc, | 266 | if (proc.chunk != frame->chunk || *vm->pc != OP_RETURN) { |
267 | .stack_offset = array_size(vm->stack) - array_size(proc.chunk->params), | 267 | CallFrame new_frame = (CallFrame){ |
268 | }; | 268 | .chunk = proc.chunk, |
269 | array_push(vm->frames, new_frame); | 269 | .rp = vm->pc, |
270 | frame = &vm->frames[array_size(vm->frames) - 1]; | 270 | .stack_offset = array_size(vm->stack) - array_size(proc.chunk->params), |
271 | }; | ||
272 | array_push(vm->frames, new_frame); | ||
273 | frame = &vm->frames[array_size(vm->frames) - 1]; | ||
274 | } else { | ||
275 | // TODO: restore all parameters. | ||
276 | Object a = array_pop(vm->stack); | ||
277 | vm->stack[frame->stack_offset] = a; | ||
278 | } | ||
271 | vm->pc = frame->chunk->code; | 279 | vm->pc = frame->chunk->code; |
272 | } break; | 280 | } break; |
273 | case OP_RETURN: { | 281 | case OP_RETURN: { |