From dd5210368634e2b322435385eaaaccaa5125b5a9 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Sun, 24 Oct 2021 15:42:01 +0200 Subject: Add initial IF implementation --- src/bytecode/compiler.h | 66 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) (limited to 'src/bytecode/compiler.h') diff --git a/src/bytecode/compiler.h b/src/bytecode/compiler.h index b1cdfb9..559ad1c 100755 --- a/src/bytecode/compiler.h +++ b/src/bytecode/compiler.h @@ -231,6 +231,71 @@ compile_declare_op(Chunk *chunk, Visitor *vs, Token start, Ops op) { add_code(chunk, op, start.line, start.column); } +void +compile_if_op(Chunk *chunk, Visitor *vs, Token start) { + Token tok = peek_token(vs); + if (tok.type == TOKEN_EOF) { + error_push((Error){ + .type = ERR_TYPE_COMPILER, + .value = ERR_UNBALANCED_PAREN, + .line = start.line, + .col = start.column, + }); + return; + } + if (tok.type == TOKEN_RPAREN) { + error_push((Error){ + .type = ERR_TYPE_COMPILER, + .value = ERR_NOT_ENOUGH_ARGS, + .line = start.line, + .col = start.column, + }); + return; + } + + // 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); + + // Block true. + parse_tree(chunk, vs); + + // No else. + 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; + 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; + 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; + + if (peek_token(vs).type != TOKEN_RPAREN) { + error_push((Error){ + .type = ERR_TYPE_COMPILER, + .value = ERR_TOO_MANY_ARGS, + .line = start.line, + .col = start.column, + }); + return; + } + next_token(vs); +} + void parse_list(Chunk *chunk, Visitor *vs, Token start) { if (!has_next_token(vs)) { @@ -262,6 +327,7 @@ parse_list(Chunk *chunk, Visitor *vs, Token start) { case TOKEN_NEWLINE: { compile_list_simple_op(chunk, vs, start, OP_NEWLINE); } break; case TOKEN_DEF: { compile_declare_op(chunk, vs, start, OP_DEF); } break; case TOKEN_SET: { compile_declare_op(chunk, vs, start, OP_SET); } break; + case TOKEN_IF: { compile_if_op(chunk, vs, start); } break; default: { error_push((Error){ .type = ERR_TYPE_COMPILER, -- cgit v1.2.1