diff options
author | Bad Diode <bd@badd10de.dev> | 2021-10-24 15:42:01 +0200 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2021-10-24 15:42:01 +0200 |
commit | dd5210368634e2b322435385eaaaccaa5125b5a9 (patch) | |
tree | 81c2bb47907281a82a198ed8cb28d9b7e34e7bf3 | |
parent | d90b9f42a361bc3563b1f11bbd707c4288a65b40 (diff) | |
download | bdl-dd5210368634e2b322435385eaaaccaa5125b5a9.tar.gz bdl-dd5210368634e2b322435385eaaaccaa5125b5a9.zip |
Add initial IF implementation
-rwxr-xr-x | src/bytecode/compiler.h | 66 | ||||
-rwxr-xr-x | src/bytecode/debug.h | 3 | ||||
-rwxr-xr-x | src/bytecode/ops.h | 3 | ||||
-rwxr-xr-x | src/bytecode/vm.h | 10 |
4 files changed, 82 insertions, 0 deletions
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 | |||
@@ -232,6 +232,71 @@ compile_declare_op(Chunk *chunk, Visitor *vs, Token start, Ops op) { | |||
232 | } | 232 | } |
233 | 233 | ||
234 | void | 234 | void |
235 | compile_if_op(Chunk *chunk, Visitor *vs, Token start) { | ||
236 | Token tok = peek_token(vs); | ||
237 | if (tok.type == TOKEN_EOF) { | ||
238 | error_push((Error){ | ||
239 | .type = ERR_TYPE_COMPILER, | ||
240 | .value = ERR_UNBALANCED_PAREN, | ||
241 | .line = start.line, | ||
242 | .col = start.column, | ||
243 | }); | ||
244 | return; | ||
245 | } | ||
246 | if (tok.type == TOKEN_RPAREN) { | ||
247 | error_push((Error){ | ||
248 | .type = ERR_TYPE_COMPILER, | ||
249 | .value = ERR_NOT_ENOUGH_ARGS, | ||
250 | .line = start.line, | ||
251 | .col = start.column, | ||
252 | }); | ||
253 | return; | ||
254 | } | ||
255 | |||
256 | // Condition. | ||
257 | parse_tree(chunk, vs); | ||
258 | emit_constant(chunk, tok, FIXNUM_VAL(0xFF)); | ||
259 | size_t pos = array_size(chunk->code); | ||
260 | add_code(chunk, OP_JUMP_IF_FALSE, start.line, start.column); | ||
261 | |||
262 | // Block true. | ||
263 | parse_tree(chunk, vs); | ||
264 | |||
265 | // No else. | ||
266 | if (peek_token(vs).type == TOKEN_RPAREN) { | ||
267 | size_t false_block_start = array_size(chunk->code) - pos - 1; | ||
268 | size_t num_idx = add_constant(chunk, FIXNUM_VAL(false_block_start)); | ||
269 | chunk->code[pos - 1] = num_idx; | ||
270 | next_token(vs); | ||
271 | return; | ||
272 | } | ||
273 | |||
274 | // Else. | ||
275 | emit_constant(chunk, tok, FIXNUM_VAL(0xFF)); | ||
276 | size_t else_pos = array_size(chunk->code); | ||
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); | ||
283 | false_block_start = array_size(chunk->code) - else_pos - 1; | ||
284 | num_idx = add_constant(chunk, FIXNUM_VAL(false_block_start)); | ||
285 | chunk->code[else_pos - 1] = num_idx; | ||
286 | |||
287 | if (peek_token(vs).type != TOKEN_RPAREN) { | ||
288 | error_push((Error){ | ||
289 | .type = ERR_TYPE_COMPILER, | ||
290 | .value = ERR_TOO_MANY_ARGS, | ||
291 | .line = start.line, | ||
292 | .col = start.column, | ||
293 | }); | ||
294 | return; | ||
295 | } | ||
296 | next_token(vs); | ||
297 | } | ||
298 | |||
299 | void | ||
235 | parse_list(Chunk *chunk, Visitor *vs, Token start) { | 300 | parse_list(Chunk *chunk, Visitor *vs, Token start) { |
236 | if (!has_next_token(vs)) { | 301 | if (!has_next_token(vs)) { |
237 | error_push((Error){ | 302 | error_push((Error){ |
@@ -262,6 +327,7 @@ parse_list(Chunk *chunk, Visitor *vs, Token start) { | |||
262 | case TOKEN_NEWLINE: { compile_list_simple_op(chunk, vs, start, OP_NEWLINE); } break; | 327 | case TOKEN_NEWLINE: { compile_list_simple_op(chunk, vs, start, OP_NEWLINE); } break; |
263 | case TOKEN_DEF: { compile_declare_op(chunk, vs, start, OP_DEF); } break; | 328 | case TOKEN_DEF: { compile_declare_op(chunk, vs, start, OP_DEF); } break; |
264 | case TOKEN_SET: { compile_declare_op(chunk, vs, start, OP_SET); } break; | 329 | case TOKEN_SET: { compile_declare_op(chunk, vs, start, OP_SET); } break; |
330 | case TOKEN_IF: { compile_if_op(chunk, vs, start); } break; | ||
265 | default: { | 331 | default: { |
266 | error_push((Error){ | 332 | error_push((Error){ |
267 | .type = ERR_TYPE_COMPILER, | 333 | .type = ERR_TYPE_COMPILER, |
diff --git a/src/bytecode/debug.h b/src/bytecode/debug.h index 889ae03..674d469 100755 --- a/src/bytecode/debug.h +++ b/src/bytecode/debug.h | |||
@@ -28,6 +28,9 @@ static const char* ops_str[] = { | |||
28 | [OP_GREATER] = "OP_GREATER", | 28 | [OP_GREATER] = "OP_GREATER", |
29 | [OP_LESS_EQUAL] = "OP_LESS_EQUAL", | 29 | [OP_LESS_EQUAL] = "OP_LESS_EQUAL", |
30 | [OP_GREATER_EQUAL] = "OP_GREATER_EQUAL", | 30 | [OP_GREATER_EQUAL] = "OP_GREATER_EQUAL", |
31 | // Jump/conditional ops. | ||
32 | [OP_JUMP] = "OP_JUMP", | ||
33 | [OP_JUMP_IF_FALSE] = "OP_JUMP_IF_FALSE", | ||
31 | // Display ops. | 34 | // Display ops. |
32 | [OP_DISPLAY] = "OP_DISPLAY", | 35 | [OP_DISPLAY] = "OP_DISPLAY", |
33 | [OP_PRINT] = "OP_PRINT", | 36 | [OP_PRINT] = "OP_PRINT", |
diff --git a/src/bytecode/ops.h b/src/bytecode/ops.h index 50d12fe..5eacaea 100755 --- a/src/bytecode/ops.h +++ b/src/bytecode/ops.h | |||
@@ -23,6 +23,9 @@ typedef enum Ops { | |||
23 | OP_GREATER, | 23 | OP_GREATER, |
24 | OP_LESS_EQUAL, | 24 | OP_LESS_EQUAL, |
25 | OP_GREATER_EQUAL, | 25 | OP_GREATER_EQUAL, |
26 | // Jump/conditional ops. | ||
27 | OP_JUMP, | ||
28 | OP_JUMP_IF_FALSE, | ||
26 | // Display ops. | 29 | // Display ops. |
27 | OP_DISPLAY, | 30 | OP_DISPLAY, |
28 | OP_PRINT, | 31 | OP_PRINT, |
diff --git a/src/bytecode/vm.h b/src/bytecode/vm.h index 51a6f44..b24a5fa 100755 --- a/src/bytecode/vm.h +++ b/src/bytecode/vm.h | |||
@@ -196,6 +196,16 @@ vm_interpret(VM *vm, Chunk *chunk) { | |||
196 | case OP_GREATER: { FIXNUM_COMPARE_OP(>); } break; | 196 | case OP_GREATER: { FIXNUM_COMPARE_OP(>); } break; |
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: { | ||
200 | ssize_t off = AS_FIXNUM(array_pop(vm->stack)); | ||
201 | vm->pc += off; | ||
202 | } break; | ||
203 | case OP_JUMP_IF_FALSE: { | ||
204 | ssize_t off = AS_FIXNUM(array_pop(vm->stack)); | ||
205 | if (IS_FALSE(array_pop(vm->stack))) { | ||
206 | vm->pc += off; | ||
207 | } | ||
208 | } break; | ||
199 | case OP_DISPLAY: { | 209 | case OP_DISPLAY: { |
200 | display(array_pop(vm->stack)); | 210 | display(array_pop(vm->stack)); |
201 | } break; | 211 | } break; |