aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-10-24 16:47:15 +0200
committerBad Diode <bd@badd10de.dev>2021-10-24 16:47:15 +0200
commitabdcae0f839d0bd772c5f7211cb1cb2034355b62 (patch)
treeee3b8c8811a1383cfb453b5638acc20997876a4c
parentdd5210368634e2b322435385eaaaccaa5125b5a9 (diff)
downloadbdl-abdcae0f839d0bd772c5f7211cb1cb2034355b62.tar.gz
bdl-abdcae0f839d0bd772c5f7211cb1cb2034355b62.zip
Cleanup IF jump code in compiler
-rwxr-xr-xsrc/bytecode/compiler.h43
-rwxr-xr-xsrc/bytecode/debug.h10
-rwxr-xr-xsrc/bytecode/vm.h12
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
48size_t
49emit_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
56void
57patch_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
48void 64void
49parse_fixnum(Chunk *chunk, Token tok) { 65parse_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: {