diff options
Diffstat (limited to 'src/bytecode/vm.h')
-rwxr-xr-x | src/bytecode/vm.h | 53 |
1 files changed, 32 insertions, 21 deletions
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 @@ | |||
13 | 13 | ||
14 | typedef struct CallFrame { | 14 | typedef struct CallFrame { |
15 | // Current code being run. | 15 | // Current code being run. |
16 | Chunk *chunk; | 16 | Closure *closure; |
17 | // Current program counter for this call. | 17 | // Current program counter for this call. |
18 | // Ref to stack. Is this really needed? | 18 | // Ref to stack. Is this really needed? |
19 | // Object *locals; | 19 | // Object *locals; |
@@ -65,7 +65,7 @@ vm_reset(VM *vm) { | |||
65 | fprintf(stderr, "stack trace:\n"); \ | 65 | fprintf(stderr, "stack trace:\n"); \ |
66 | for (ssize_t i = array_size(vm->frames) - 1; i >= 0 ; i--) { \ | 66 | for (ssize_t i = array_size(vm->frames) - 1; i >= 0 ; i--) { \ |
67 | CallFrame frame = vm->frames[i]; \ | 67 | CallFrame frame = vm->frames[i]; \ |
68 | Chunk *chunk = frame.chunk; \ | 68 | Chunk *chunk = frame.closure->chunk; \ |
69 | size_t instruction = vm->pc - chunk->code - 1; \ | 69 | size_t instruction = vm->pc - chunk->code - 1; \ |
70 | fprintf(stderr, "\t%-4ld -> ", i); \ | 70 | fprintf(stderr, "\t%-4ld -> ", i); \ |
71 | fprintf(stderr, "%.*s",(int)array_size(chunk->name), chunk->name); \ | 71 | fprintf(stderr, "%.*s",(int)array_size(chunk->name), chunk->name); \ |
@@ -80,8 +80,8 @@ vm_reset(VM *vm) { | |||
80 | error_push((Error){ \ | 80 | error_push((Error){ \ |
81 | .type = ERR_TYPE_RUNTIME, \ | 81 | .type = ERR_TYPE_RUNTIME, \ |
82 | .value = (ERR), \ | 82 | .value = (ERR), \ |
83 | .line = frame->chunk->lines[vm->pc - frame->chunk->code - 1].line, \ | 83 | .line = chunk->lines[vm->pc - chunk->code - 1].line, \ |
84 | .col = frame->chunk->lines[vm->pc - frame->chunk->code - 1].col, \ | 84 | .col = chunk->lines[vm->pc - chunk->code - 1].col, \ |
85 | }); \ | 85 | }); \ |
86 | STACK_TRACE() \ | 86 | STACK_TRACE() \ |
87 | return | 87 | return |
@@ -149,10 +149,11 @@ vm_reset(VM *vm) { | |||
149 | void | 149 | void |
150 | vm_interpret(VM *vm) { | 150 | vm_interpret(VM *vm) { |
151 | CallFrame *frame = &vm->frames[0]; | 151 | CallFrame *frame = &vm->frames[0]; |
152 | vm->pc = frame->chunk->code; | 152 | Chunk *chunk = frame->closure->chunk; |
153 | vm->pc = chunk->code; | ||
153 | frame->rp = NULL; | 154 | frame->rp = NULL; |
154 | 155 | ||
155 | if (frame->chunk->code == NULL || array_size(frame->chunk->code) == 0) { | 156 | if (chunk->code == NULL || array_size(chunk->code) == 0) { |
156 | error_push((Error){ | 157 | error_push((Error){ |
157 | .type = ERR_TYPE_RUNTIME, | 158 | .type = ERR_TYPE_RUNTIME, |
158 | .value = ERR_EMPTY_CHUNK, | 159 | .value = ERR_EMPTY_CHUNK, |
@@ -170,22 +171,31 @@ vm_interpret(VM *vm) { | |||
170 | } | 171 | } |
171 | } | 172 | } |
172 | printf(" ]\nop: "); | 173 | printf(" ]\nop: "); |
173 | disassemble_instruction(frame->chunk, (vm->pc - frame->chunk->code)); | 174 | disassemble_instruction(chunk, (vm->pc - chunk->code)); |
174 | #endif | 175 | #endif |
175 | u8 instruction = *vm->pc++; | 176 | u8 instruction = *vm->pc++; |
176 | switch (instruction) { | 177 | switch (instruction) { |
177 | case OP_LOCAL: { | 178 | case OP_LOCAL: { |
178 | ssize_t idx = AS_FIXNUM(array_pop(vm->stack)); | 179 | ssize_t idx = AS_FIXNUM(array_pop(vm->stack)); |
179 | ssize_t depth = AS_FIXNUM(array_pop(vm->stack)); | 180 | CallFrame frame = vm->frames[array_size(vm->frames) - 1]; |
180 | depth = array_size(vm->frames) - depth; | ||
181 | CallFrame frame = vm->frames[depth]; | ||
182 | array_push(vm->stack, vm->stack[frame.stack_offset + idx]); | 181 | array_push(vm->stack, vm->stack[frame.stack_offset + idx]); |
183 | } break; | 182 | } break; |
184 | case OP_CONSTANT: { | 183 | case OP_CONSTANT: { |
185 | u8 constant = *vm->pc++; | 184 | u8 constant = *vm->pc++; |
186 | Object obj = frame->chunk->constants[constant]; | 185 | Object obj = chunk->constants[constant]; |
187 | array_push(vm->stack, obj); | 186 | array_push(vm->stack, obj); |
188 | } break; | 187 | } break; |
188 | case OP_CAPTURED: { | ||
189 | assert(false && "not implemented"); | ||
190 | } break; | ||
191 | case OP_CAPTURE_LOCAL: { | ||
192 | assert(false && "not implemented"); | ||
193 | // Object value = array_pop(vm->stack); | ||
194 | // ssize_t idx = AS_FIXNUM(array_pop(vm->stack)); | ||
195 | // ssize_t depth = AS_FIXNUM(array_pop(vm->stack)); | ||
196 | // CallFrame frame = vm->frames[depth]; | ||
197 | // vm->stack[frame.stack_offset + idx] = value; | ||
198 | } break; | ||
189 | case OP_DEF_LOCAL: { | 199 | case OP_DEF_LOCAL: { |
190 | Object value = array_pop(vm->stack); | 200 | Object value = array_pop(vm->stack); |
191 | ssize_t idx = AS_FIXNUM(array_pop(vm->stack)); | 201 | ssize_t idx = AS_FIXNUM(array_pop(vm->stack)); |
@@ -194,8 +204,7 @@ vm_interpret(VM *vm) { | |||
194 | case OP_SET_LOCAL: { | 204 | case OP_SET_LOCAL: { |
195 | Object value = array_pop(vm->stack); | 205 | Object value = array_pop(vm->stack); |
196 | ssize_t idx = AS_FIXNUM(array_pop(vm->stack)); | 206 | ssize_t idx = AS_FIXNUM(array_pop(vm->stack)); |
197 | ssize_t depth = AS_FIXNUM(array_pop(vm->stack)); | 207 | CallFrame frame = vm->frames[array_size(vm->frames) - 1]; |
198 | CallFrame frame = vm->frames[depth]; | ||
199 | vm->stack[frame.stack_offset + idx] = value; | 208 | vm->stack[frame.stack_offset + idx] = value; |
200 | } break; | 209 | } break; |
201 | case OP_DEF: { | 210 | case OP_DEF: { |
@@ -290,8 +299,8 @@ vm_interpret(VM *vm) { | |||
290 | // Check the number of arguments is correct. | 299 | // Check the number of arguments is correct. |
291 | // NOTE: This is probably better handled at compilation, but for | 300 | // NOTE: This is probably better handled at compilation, but for |
292 | // now this is simpler to implement. | 301 | // now this is simpler to implement. |
293 | ssize_t n_params = proc.chunk->n_params; | 302 | ssize_t n_params = proc.closure->chunk->n_params; |
294 | ssize_t n_locals = proc.chunk->n_locals - n_params; | 303 | ssize_t n_locals = proc.closure->chunk->n_locals - n_params; |
295 | if (n_args < n_params) { | 304 | if (n_args < n_params) { |
296 | RUNTIME_ERROR(ERR_NOT_ENOUGH_ARGS); | 305 | RUNTIME_ERROR(ERR_NOT_ENOUGH_ARGS); |
297 | } else if (n_args > n_params) { | 306 | } else if (n_args > n_params) { |
@@ -299,20 +308,21 @@ vm_interpret(VM *vm) { | |||
299 | } | 308 | } |
300 | 309 | ||
301 | #ifdef DEBUG | 310 | #ifdef DEBUG |
302 | disassemble_chunk(proc.chunk); | 311 | disassemble_chunk(proc.closure->chunk); |
303 | printf("n_locals: %ld\n", n_locals); | 312 | printf("n_locals: %ld\n", n_locals); |
304 | printf("n_params: %ld\n", n_params); | 313 | printf("n_params: %ld\n", n_params); |
305 | #endif | 314 | #endif |
306 | // Tail-call optimization. | 315 | // Tail-call optimization. |
307 | if (proc.chunk != frame->chunk || *vm->pc != OP_RETURN) { | 316 | if (proc.closure->chunk != chunk || *vm->pc != OP_RETURN) { |
308 | // Prepare new call frame. | 317 | // Prepare new call frame. |
309 | CallFrame new_frame = (CallFrame){ | 318 | CallFrame new_frame = (CallFrame){ |
310 | .chunk = proc.chunk, | 319 | .closure = proc.closure, |
311 | .rp = vm->pc, | 320 | .rp = vm->pc, |
312 | .stack_offset = array_size(vm->stack) - n_params, | 321 | .stack_offset = array_size(vm->stack) - n_params, |
313 | }; | 322 | }; |
314 | array_push(vm->frames, new_frame); | 323 | array_push(vm->frames, new_frame); |
315 | frame = &vm->frames[array_size(vm->frames) - 1]; | 324 | frame = &vm->frames[array_size(vm->frames) - 1]; |
325 | chunk = frame->closure->chunk; | ||
316 | 326 | ||
317 | // Prepare local slots. | 327 | // Prepare local slots. |
318 | for (ssize_t i = 0; i < n_locals; i++) { | 328 | for (ssize_t i = 0; i < n_locals; i++) { |
@@ -330,7 +340,7 @@ vm_interpret(VM *vm) { | |||
330 | size_t offset = frame->stack_offset + n_params + n_locals; | 340 | size_t offset = frame->stack_offset + n_params + n_locals; |
331 | array_head(vm->stack)->size = offset; | 341 | array_head(vm->stack)->size = offset; |
332 | } | 342 | } |
333 | vm->pc = frame->chunk->code; | 343 | vm->pc = chunk->code; |
334 | } break; | 344 | } break; |
335 | case OP_RETURN: { | 345 | case OP_RETURN: { |
336 | if (frame->rp == NULL) { | 346 | if (frame->rp == NULL) { |
@@ -347,6 +357,7 @@ vm_interpret(VM *vm) { | |||
347 | array_head(vm->stack)->size = frame->stack_offset; | 357 | array_head(vm->stack)->size = frame->stack_offset; |
348 | array_push(vm->stack, ret); | 358 | array_push(vm->stack, ret); |
349 | frame = &vm->frames[array_size(vm->frames) - 1]; | 359 | frame = &vm->frames[array_size(vm->frames) - 1]; |
360 | chunk = frame->closure->chunk; | ||
350 | } break; | 361 | } break; |
351 | case OP_DROP: { | 362 | case OP_DROP: { |
352 | array_head(vm->stack)->size = 0; | 363 | array_head(vm->stack)->size = 0; |
@@ -360,8 +371,8 @@ vm_interpret(VM *vm) { | |||
360 | error_push((Error){ | 371 | error_push((Error){ |
361 | .type = ERR_TYPE_RUNTIME, | 372 | .type = ERR_TYPE_RUNTIME, |
362 | .value = ERR_PC_OOB, | 373 | .value = ERR_PC_OOB, |
363 | .line = frame->chunk->lines[0].line, | 374 | .line = chunk->lines[0].line, |
364 | .col = frame->chunk->lines[0].col, | 375 | .col = chunk->lines[0].col, |
365 | }); | 376 | }); |
366 | } | 377 | } |
367 | 378 | ||