diff options
Diffstat (limited to 'src/bytecode')
-rwxr-xr-x | src/bytecode/compiler.h | 43 | ||||
-rwxr-xr-x | src/bytecode/debug.h | 10 | ||||
-rwxr-xr-x | src/bytecode/vm.h | 12 |
3 files changed, 41 insertions, 24 deletions
diff --git a/src/bytecode/compiler.h b/src/bytecode/compiler.h index 559ad1c..c01f745 100755 --- a/src/bytecode/compiler.h +++ b/src/bytecode/compiler.h | |||
@@ -45,6 +45,22 @@ emit_constant(Chunk *chunk, Token tok, Object obj) { | |||
45 | } | 45 | } |
46 | } | 46 | } |
47 | 47 | ||
48 | size_t | ||
49 | emit_jump(Chunk *chunk, Token tok, Ops op) { | ||
50 | add_code(chunk, op, tok.line, tok.column); | ||
51 | add_code(chunk, 0xFF, tok.line, tok.column); | ||
52 | add_code(chunk, 0xFF, tok.line, tok.column); | ||
53 | return array_size(chunk->code) - 2; | ||
54 | } | ||
55 | |||
56 | void | ||
57 | patch_jump(Chunk *chunk, size_t offset) { | ||
58 | size_t jump = array_size(chunk->code) - offset - 2; | ||
59 | assert(jump <= UINT16_MAX && "error: jump is too long"); | ||
60 | chunk->code[offset] = (jump >> 8) & 0xFF; | ||
61 | chunk->code[offset + 1] = (jump) & 0xFF; | ||
62 | } | ||
63 | |||
48 | void | 64 | void |
49 | parse_fixnum(Chunk *chunk, Token tok) { | 65 | parse_fixnum(Chunk *chunk, Token tok) { |
50 | ssize_t num = 0; | 66 | ssize_t num = 0; |
@@ -255,34 +271,23 @@ compile_if_op(Chunk *chunk, Visitor *vs, Token start) { | |||
255 | 271 | ||
256 | // Condition. | 272 | // Condition. |
257 | parse_tree(chunk, vs); | 273 | parse_tree(chunk, vs); |
258 | emit_constant(chunk, tok, FIXNUM_VAL(0xFF)); | 274 | size_t jmp_false = emit_jump(chunk, start, OP_JUMP_IF_FALSE); |
259 | size_t pos = array_size(chunk->code); | ||
260 | add_code(chunk, OP_JUMP_IF_FALSE, start.line, start.column); | ||
261 | 275 | ||
262 | // Block true. | 276 | // True expression. |
263 | parse_tree(chunk, vs); | 277 | parse_tree(chunk, vs); |
264 | 278 | ||
265 | // No else. | 279 | // No second expression. |
266 | if (peek_token(vs).type == TOKEN_RPAREN) { | 280 | if (peek_token(vs).type == TOKEN_RPAREN) { |
267 | size_t false_block_start = array_size(chunk->code) - pos - 1; | 281 | patch_jump(chunk, jmp_false); |
268 | size_t num_idx = add_constant(chunk, FIXNUM_VAL(false_block_start)); | ||
269 | chunk->code[pos - 1] = num_idx; | ||
270 | next_token(vs); | 282 | next_token(vs); |
271 | return; | 283 | return; |
272 | } | 284 | } |
273 | 285 | ||
274 | // Else. | 286 | // False expression. |
275 | emit_constant(chunk, tok, FIXNUM_VAL(0xFF)); | 287 | size_t jmp_end = emit_jump(chunk, start, OP_JUMP); |
276 | size_t else_pos = array_size(chunk->code); | 288 | patch_jump(chunk, jmp_false); |
277 | add_code(chunk, OP_JUMP, start.line, start.column); | ||
278 | |||
279 | size_t false_block_start = array_size(chunk->code) - pos - 1; | ||
280 | size_t num_idx = add_constant(chunk, FIXNUM_VAL(false_block_start)); | ||
281 | chunk->code[pos - 1] = num_idx; | ||
282 | parse_tree(chunk, vs); | 289 | parse_tree(chunk, vs); |
283 | false_block_start = array_size(chunk->code) - else_pos - 1; | 290 | patch_jump(chunk, jmp_end); |
284 | num_idx = add_constant(chunk, FIXNUM_VAL(false_block_start)); | ||
285 | chunk->code[else_pos - 1] = num_idx; | ||
286 | 291 | ||
287 | if (peek_token(vs).type != TOKEN_RPAREN) { | 292 | if (peek_token(vs).type != TOKEN_RPAREN) { |
288 | error_push((Error){ | 293 | error_push((Error){ |
diff --git a/src/bytecode/debug.h b/src/bytecode/debug.h index 674d469..bc736f9 100755 --- a/src/bytecode/debug.h +++ b/src/bytecode/debug.h | |||
@@ -71,11 +71,19 @@ disassemble_instruction(Chunk *chunk, size_t offset) { | |||
71 | switch (instruction) { | 71 | switch (instruction) { |
72 | case OP_CONSTANT: { | 72 | case OP_CONSTANT: { |
73 | u8 constant = chunk->code[offset + 1]; | 73 | u8 constant = chunk->code[offset + 1]; |
74 | printf("%-16s %4d -> ", "OP_CONSTANT", constant); | 74 | printf("%-16s %4d -> ", ops_str[instruction], constant); |
75 | display(chunk->constants[constant]); | 75 | display(chunk->constants[constant]); |
76 | printf("\n"); | 76 | printf("\n"); |
77 | return offset + 2; | 77 | return offset + 2; |
78 | } break; | 78 | } break; |
79 | case OP_JUMP: | ||
80 | case OP_JUMP_IF_FALSE: { | ||
81 | u16 a = chunk->code[offset + 1]; | ||
82 | u16 b = chunk->code[offset + 2]; | ||
83 | u16 jmp = (a << 8) | b; | ||
84 | printf("%-16s %4d\n", ops_str[instruction], jmp); | ||
85 | return offset + 3; | ||
86 | } break; | ||
79 | default: { | 87 | default: { |
80 | printf("%s\n", ops_str[instruction]); | 88 | printf("%s\n", ops_str[instruction]); |
81 | return offset + 1; | 89 | return offset + 1; |
diff --git a/src/bytecode/vm.h b/src/bytecode/vm.h index b24a5fa..ba33077 100755 --- a/src/bytecode/vm.h +++ b/src/bytecode/vm.h | |||
@@ -197,13 +197,17 @@ vm_interpret(VM *vm, Chunk *chunk) { | |||
197 | case OP_LESS_EQUAL: { FIXNUM_COMPARE_OP(<=); } break; | 197 | case OP_LESS_EQUAL: { FIXNUM_COMPARE_OP(<=); } break; |
198 | case OP_GREATER_EQUAL: { FIXNUM_COMPARE_OP(>=); } break; | 198 | case OP_GREATER_EQUAL: { FIXNUM_COMPARE_OP(>=); } break; |
199 | case OP_JUMP: { | 199 | case OP_JUMP: { |
200 | ssize_t off = AS_FIXNUM(array_pop(vm->stack)); | 200 | u16 a = *vm->pc++; |
201 | vm->pc += off; | 201 | u16 b = *vm->pc++; |
202 | u16 offset = (a << 8) | b; | ||
203 | vm->pc += offset; | ||
202 | } break; | 204 | } break; |
203 | case OP_JUMP_IF_FALSE: { | 205 | case OP_JUMP_IF_FALSE: { |
204 | ssize_t off = AS_FIXNUM(array_pop(vm->stack)); | 206 | u16 a = *vm->pc++; |
207 | u16 b = *vm->pc++; | ||
208 | u16 offset = (a << 8) | b; | ||
205 | if (IS_FALSE(array_pop(vm->stack))) { | 209 | if (IS_FALSE(array_pop(vm->stack))) { |
206 | vm->pc += off; | 210 | vm->pc += offset; |
207 | } | 211 | } |
208 | } break; | 212 | } break; |
209 | case OP_DISPLAY: { | 213 | case OP_DISPLAY: { |