diff options
-rwxr-xr-x | src/bytecode/compiler.h | 13 | ||||
-rwxr-xr-x | src/bytecode/main.c | 15 | ||||
-rwxr-xr-x | src/bytecode/vm.h | 70 |
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); | |||
14 | Token peek_token(const Compiler *compiler); | 14 | Token peek_token(const Compiler *compiler); |
15 | bool has_next_token(const Compiler *compiler); | 15 | bool has_next_token(const Compiler *compiler); |
16 | 16 | ||
17 | Chunk * compile(Token *tokens); | 17 | Object compile(Token *tokens); |
18 | 18 | ||
19 | Token | 19 | Token |
20 | peek_token(const Compiler *compiler) { | 20 | peek_token(const Compiler *compiler) { |
@@ -415,20 +415,19 @@ parse_tree(Chunk *chunk, Compiler *compiler) { | |||
415 | return; | 415 | return; |
416 | } | 416 | } |
417 | 417 | ||
418 | Chunk * | 418 | Object |
419 | compile(Token *tokens) { | 419 | compile(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 | ||
13 | typedef struct VM { | 14 | typedef 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 | |||
23 | typedef 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 { | |||
24 | void vm_init(VM *vm); | 31 | void vm_init(VM *vm); |
25 | void vm_free(VM *vm); | 32 | void vm_free(VM *vm); |
26 | void vm_reset(VM *vm); | 33 | void vm_reset(VM *vm); |
27 | void vm_interpret(VM *vm, Chunk *chunk); | 34 | void vm_interpret(VM *vm); |
28 | 35 | ||
29 | void | 36 | void |
30 | vm_init(VM *vm) { | 37 | vm_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 | ||
36 | void | 47 | void |
37 | vm_free(VM *vm) { | 48 | vm_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 | ||
125 | void | 137 | void |
126 | vm_interpret(VM *vm, Chunk *chunk) { | 138 | vm_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 | ||