From abdcae0f839d0bd772c5f7211cb1cb2034355b62 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Sun, 24 Oct 2021 16:47:15 +0200 Subject: Cleanup IF jump code in compiler --- src/bytecode/compiler.h | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) (limited to 'src/bytecode/compiler.h') 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) { } } +size_t +emit_jump(Chunk *chunk, Token tok, Ops op) { + add_code(chunk, op, tok.line, tok.column); + add_code(chunk, 0xFF, tok.line, tok.column); + add_code(chunk, 0xFF, tok.line, tok.column); + return array_size(chunk->code) - 2; +} + +void +patch_jump(Chunk *chunk, size_t offset) { + size_t jump = array_size(chunk->code) - offset - 2; + assert(jump <= UINT16_MAX && "error: jump is too long"); + chunk->code[offset] = (jump >> 8) & 0xFF; + chunk->code[offset + 1] = (jump) & 0xFF; +} + void parse_fixnum(Chunk *chunk, Token tok) { ssize_t num = 0; @@ -255,34 +271,23 @@ compile_if_op(Chunk *chunk, Visitor *vs, Token start) { // Condition. parse_tree(chunk, vs); - emit_constant(chunk, tok, FIXNUM_VAL(0xFF)); - size_t pos = array_size(chunk->code); - add_code(chunk, OP_JUMP_IF_FALSE, start.line, start.column); + size_t jmp_false = emit_jump(chunk, start, OP_JUMP_IF_FALSE); - // Block true. + // True expression. parse_tree(chunk, vs); - // No else. + // No second expression. if (peek_token(vs).type == TOKEN_RPAREN) { - size_t false_block_start = array_size(chunk->code) - pos - 1; - size_t num_idx = add_constant(chunk, FIXNUM_VAL(false_block_start)); - chunk->code[pos - 1] = num_idx; + patch_jump(chunk, jmp_false); next_token(vs); return; } - // Else. - emit_constant(chunk, tok, FIXNUM_VAL(0xFF)); - size_t else_pos = array_size(chunk->code); - add_code(chunk, OP_JUMP, start.line, start.column); - - size_t false_block_start = array_size(chunk->code) - pos - 1; - size_t num_idx = add_constant(chunk, FIXNUM_VAL(false_block_start)); - chunk->code[pos - 1] = num_idx; + // False expression. + size_t jmp_end = emit_jump(chunk, start, OP_JUMP); + patch_jump(chunk, jmp_false); parse_tree(chunk, vs); - false_block_start = array_size(chunk->code) - else_pos - 1; - num_idx = add_constant(chunk, FIXNUM_VAL(false_block_start)); - chunk->code[else_pos - 1] = num_idx; + patch_jump(chunk, jmp_end); if (peek_token(vs).type != TOKEN_RPAREN) { error_push((Error){ -- cgit v1.2.1