aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-10-25 14:32:18 +0200
committerBad Diode <bd@badd10de.dev>2021-10-25 14:32:18 +0200
commitad8c598e84bd1e5469e2487cc3e4d0ea784d0ff3 (patch)
tree0d2439abaf88f22009ad0cbe41d9ab0ac3cc0a05
parentb9644b4ccda5abee01fd0704ddc42b08b68e5b5d (diff)
downloadbdl-ad8c598e84bd1e5469e2487cc3e4d0ea784d0ff3.tar.gz
bdl-ad8c598e84bd1e5469e2487cc3e4d0ea784d0ff3.zip
Add callframe support for the VM
-rwxr-xr-xsrc/bytecode/compiler.h13
-rwxr-xr-xsrc/bytecode/main.c15
-rwxr-xr-xsrc/bytecode/vm.h70
3 files changed, 57 insertions, 41 deletions
diff --git a/src/bytecode/compiler.h b/src/bytecode/compiler.h
index 3b68868..4130269 100755
--- a/src/bytecode/compiler.h
+++ b/src/bytecode/compiler.h
@@ -14,7 +14,7 @@ Token next_token(Compiler *compiler);
14Token peek_token(const Compiler *compiler); 14Token peek_token(const Compiler *compiler);
15bool has_next_token(const Compiler *compiler); 15bool has_next_token(const Compiler *compiler);
16 16
17Chunk * compile(Token *tokens); 17Object compile(Token *tokens);
18 18
19Token 19Token
20peek_token(const Compiler *compiler) { 20peek_token(const Compiler *compiler) {
@@ -415,20 +415,19 @@ parse_tree(Chunk *chunk, Compiler *compiler) {
415 return; 415 return;
416} 416}
417 417
418Chunk * 418Object
419compile(Token *tokens) { 419compile(Token *tokens) {
420 Chunk *chunk = NULL; 420 Object main = make_lambda((StringView){"main", sizeof("main")});
421 chunk = NEW_CHUNK("main");
422 Compiler compiler = (Compiler){ 421 Compiler compiler = (Compiler){
423 .tokens = tokens, 422 .tokens = tokens,
424 .current = 0, 423 .current = 0,
425 }; 424 };
426 Token start_tok = peek_token(&compiler); 425 Token start_tok = peek_token(&compiler);
427 while (has_next_token(&compiler) && peek_token(&compiler).type != TOKEN_EOF) { 426 while (has_next_token(&compiler) && peek_token(&compiler).type != TOKEN_EOF) {
428 parse_tree(chunk, &compiler); 427 parse_tree(main.chunk, &compiler);
429 } 428 }
430 add_code(chunk, OP_RETURN, start_tok.line, start_tok.column); 429 add_code(main.chunk, OP_RETURN, start_tok.line, start_tok.column);
431 return chunk; 430 return main;
432} 431}
433 432
434#endif // BDL_COMPILER_H 433#endif // BDL_COMPILER_H
diff --git a/src/bytecode/main.c b/src/bytecode/main.c
index d1fbac2..e4cf643 100755
--- a/src/bytecode/main.c
+++ b/src/bytecode/main.c
@@ -45,22 +45,27 @@ process_source(const StringView *source) {
45 } 45 }
46 46
47 // Compile chunk. 47 // Compile chunk.
48 Chunk *chunk = compile(tokens); 48 Object main = compile(tokens);
49 if (errors_n != 0) { 49 if (errors_n != 0) {
50 chunk_free(chunk); 50 object_free(main);
51 array_free(tokens); 51 array_free(tokens);
52 return; 52 return;
53 } 53 }
54 54
55#ifdef DEBUG 55#ifdef DEBUG
56 disassemble_chunk(chunk); 56 disassemble_chunk(main.chunk);
57#endif 57#endif
58 58
59 // Interpret chunk. 59 // Interpret chunk.
60 vm_interpret(&vm, chunk); 60 CallFrame frame = (CallFrame){
61 .procedure = main,
62 .pc = main.chunk->code,
63 };
64 array_push(vm.frames, frame);
65 vm_interpret(&vm);
61 66
62 // Free resources. 67 // Free resources.
63 chunk_free(chunk); 68 object_free(main);
64 array_free(tokens); 69 array_free(tokens);
65} 70}
66 71
diff --git a/src/bytecode/vm.h b/src/bytecode/vm.h
index b6f9848..23c3d89 100755
--- a/src/bytecode/vm.h
+++ b/src/bytecode/vm.h
@@ -8,13 +8,20 @@
8#include "debug.h" 8#include "debug.h"
9#include "hashtable.h" 9#include "hashtable.h"
10 10
11#define VM_FRAMES_CAP 64
11#define VM_STACK_CAP 1024 12#define VM_STACK_CAP 1024
12 13
13typedef struct VM { 14typedef struct CallFrame {
14 // Program code. 15 // Current code being run.
15 Chunk *chunk; 16 Object procedure;
16 // Program counter. 17 // Current program counter for this call.
17 u8 *pc; 18 u8 *pc;
19 // Ref to stack. Is this really needed?
20 // Object *stack;
21} CallFrame;
22
23typedef struct VM {
24 CallFrame *frames;
18 // Stack. 25 // Stack.
19 Object *stack; 26 Object *stack;
20 // Global variables. 27 // Global variables.
@@ -24,17 +31,22 @@ typedef struct VM {
24void vm_init(VM *vm); 31void vm_init(VM *vm);
25void vm_free(VM *vm); 32void vm_free(VM *vm);
26void vm_reset(VM *vm); 33void vm_reset(VM *vm);
27void vm_interpret(VM *vm, Chunk *chunk); 34void vm_interpret(VM *vm);
28 35
29void 36void
30vm_init(VM *vm) { 37vm_init(VM *vm) {
31 *vm = (VM){0}; 38 *vm = (VM){0};
39 array_init(vm->frames, VM_FRAMES_CAP);
40 for (size_t i = 0; i < array_cap(vm->frames); i++) {
41 vm->frames[i] = (CallFrame){0};
42 }
32 array_init(vm->stack, VM_STACK_CAP); 43 array_init(vm->stack, VM_STACK_CAP);
33 vm->globals = ht_init(); 44 vm->globals = ht_init();
34} 45}
35 46
36void 47void
37vm_free(VM *vm) { 48vm_free(VM *vm) {
49 array_free(vm->frames);
38 array_free(vm->stack); 50 array_free(vm->stack);
39 ht_free(vm->globals); 51 ht_free(vm->globals);
40} 52}
@@ -50,16 +62,16 @@ vm_reset(VM *vm) {
50 error_push((Error){ \ 62 error_push((Error){ \
51 .type = ERR_TYPE_RUNTIME, \ 63 .type = ERR_TYPE_RUNTIME, \
52 .value = ERR_WRONG_ARG_TYPE, \ 64 .value = ERR_WRONG_ARG_TYPE, \
53 .line = vm->chunk->lines[vm->pc - vm->chunk->code - 1].line, \ 65 .line = chunk->lines[frame->pc - chunk->code - 1].line, \
54 .col = vm->chunk->lines[vm->pc - vm->chunk->code - 1].col, \ 66 .col = chunk->lines[frame->pc - chunk->code - 1].col, \
55 }) 67 })
56 68
57#define SYMBOL_NOT_FOUND_ERR() \ 69#define SYMBOL_NOT_FOUND_ERR() \
58 error_push((Error){ \ 70 error_push((Error){ \
59 .type = ERR_TYPE_RUNTIME, \ 71 .type = ERR_TYPE_RUNTIME, \
60 .value = ERR_SYMBOL_NOT_FOUND, \ 72 .value = ERR_SYMBOL_NOT_FOUND, \
61 .line = vm->chunk->lines[vm->pc - vm->chunk->code - 1].line, \ 73 .line = chunk->lines[frame->pc - chunk->code - 1].line, \
62 .col = vm->chunk->lines[vm->pc - vm->chunk->code - 1].col, \ 74 .col = chunk->lines[frame->pc - chunk->code - 1].col, \
63 }) 75 })
64 76
65#define FIXNUM_ARITHMETIC_OP(OP) \ 77#define FIXNUM_ARITHMETIC_OP(OP) \
@@ -123,11 +135,11 @@ vm_reset(VM *vm) {
123 } while (false) 135 } while (false)
124 136
125void 137void
126vm_interpret(VM *vm, Chunk *chunk) { 138vm_interpret(VM *vm) {
127 vm->chunk = chunk; 139 CallFrame *frame = &vm->frames[array_size(vm->frames) - 1];
128 vm->pc = vm->chunk->code; 140 Chunk *chunk = frame->procedure.chunk;
129 141
130 if (vm->chunk->code == NULL || array_size(vm->chunk->code) == 0) { 142 if (chunk->code == NULL || array_size(chunk->code) == 0) {
131 error_push((Error){ 143 error_push((Error){
132 .type = ERR_TYPE_RUNTIME, 144 .type = ERR_TYPE_RUNTIME,
133 .value = ERR_EMPTY_CHUNK, 145 .value = ERR_EMPTY_CHUNK,
@@ -135,8 +147,8 @@ vm_interpret(VM *vm, Chunk *chunk) {
135 return; 147 return;
136 } 148 }
137 149
138 u8 *last = vm->chunk->code + array_size(vm->chunk->code); 150 u8 *last = chunk->code + array_size(chunk->code);
139 while (vm->pc < last) { 151 while (frame->pc < last) {
140#ifdef DEBUG_TRACE_EXECUTION 152#ifdef DEBUG_TRACE_EXECUTION
141 printf("stack: [ "); 153 printf("stack: [ ");
142 for (size_t i = 0; i < array_size(vm->stack); i++) { 154 for (size_t i = 0; i < array_size(vm->stack); i++) {
@@ -146,13 +158,13 @@ vm_interpret(VM *vm, Chunk *chunk) {
146 } 158 }
147 } 159 }
148 printf(" ]\nop: "); 160 printf(" ]\nop: ");
149 disassemble_instruction(vm->chunk, (vm->pc - vm->chunk->code)); 161 disassemble_instruction(chunk, (frame->pc - chunk->code));
150#endif 162#endif
151 u8 instruction = *vm->pc++; 163 u8 instruction = *frame->pc++;
152 switch (instruction) { 164 switch (instruction) {
153 case OP_CONSTANT: { 165 case OP_CONSTANT: {
154 u8 constant = *vm->pc++; 166 u8 constant = *frame->pc++;
155 Object obj = vm->chunk->constants[constant]; 167 Object obj = chunk->constants[constant];
156 array_push(vm->stack, obj); 168 array_push(vm->stack, obj);
157 } break; 169 } break;
158 case OP_DEF: { 170 case OP_DEF: {
@@ -197,17 +209,17 @@ vm_interpret(VM *vm, Chunk *chunk) {
197 case OP_LESS_EQUAL: { FIXNUM_COMPARE_OP(<=); } break; 209 case OP_LESS_EQUAL: { FIXNUM_COMPARE_OP(<=); } break;
198 case OP_GREATER_EQUAL: { FIXNUM_COMPARE_OP(>=); } break; 210 case OP_GREATER_EQUAL: { FIXNUM_COMPARE_OP(>=); } break;
199 case OP_JUMP: { 211 case OP_JUMP: {
200 u16 a = *vm->pc++; 212 u16 a = *frame->pc++;
201 u16 b = *vm->pc++; 213 u16 b = *frame->pc++;
202 s16 offset = (a << 8) | b; 214 s16 offset = (a << 8) | b;
203 vm->pc += offset; 215 frame->pc += offset;
204 } break; 216 } break;
205 case OP_JUMP_IF_FALSE: { 217 case OP_JUMP_IF_FALSE: {
206 u16 a = *vm->pc++; 218 u16 a = *frame->pc++;
207 u16 b = *vm->pc++; 219 u16 b = *frame->pc++;
208 s16 offset = (a << 8) | b; 220 s16 offset = (a << 8) | b;
209 if (IS_FALSE(array_pop(vm->stack))) { 221 if (IS_FALSE(array_pop(vm->stack))) {
210 vm->pc += offset; 222 frame->pc += offset;
211 } 223 }
212 } break; 224 } break;
213 case OP_DISPLAY: { 225 case OP_DISPLAY: {
@@ -248,8 +260,8 @@ vm_interpret(VM *vm, Chunk *chunk) {
248 error_push((Error){ 260 error_push((Error){
249 .type = ERR_TYPE_RUNTIME, 261 .type = ERR_TYPE_RUNTIME,
250 .value = ERR_NOT_IMPLEMENTED, 262 .value = ERR_NOT_IMPLEMENTED,
251 .line = vm->chunk->lines[vm->pc - vm->chunk->code - 1].line, 263 .line = chunk->lines[frame->pc - chunk->code - 1].line,
252 .col = vm->chunk->lines[vm->pc - vm->chunk->code - 1].col, 264 .col = chunk->lines[frame->pc - chunk->code - 1].col,
253 }); 265 });
254 return; 266 return;
255 } break; 267 } break;
@@ -259,8 +271,8 @@ vm_interpret(VM *vm, Chunk *chunk) {
259 error_push((Error){ 271 error_push((Error){
260 .type = ERR_TYPE_RUNTIME, 272 .type = ERR_TYPE_RUNTIME,
261 .value = ERR_PC_OOB, 273 .value = ERR_PC_OOB,
262 .line = vm->chunk->lines[0].line, 274 .line = chunk->lines[0].line,
263 .col = vm->chunk->lines[0].col, 275 .col = chunk->lines[0].col,
264 }); 276 });
265} 277}
266 278