aboutsummaryrefslogtreecommitdiffstats
path: root/src/bytecode/vm.h
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-10-28 10:40:22 +0200
committerBad Diode <bd@badd10de.dev>2021-10-28 10:40:22 +0200
commitd04aea3c5875cd2859d6ab961256b11189c49839 (patch)
tree911b6df338dde38ed28c447cfba999bcc3cb1743 /src/bytecode/vm.h
parent4515d21211263a2c7367ec20ec01ce9efaae1d18 (diff)
downloadbdl-d04aea3c5875cd2859d6ab961256b11189c49839.tar.gz
bdl-d04aea3c5875cd2859d6ab961256b11189c49839.zip
Prepare for closure capture
Diffstat (limited to 'src/bytecode/vm.h')
-rwxr-xr-xsrc/bytecode/vm.h53
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
14typedef struct CallFrame { 14typedef 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) {
149void 149void
150vm_interpret(VM *vm) { 150vm_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