diff options
author | Bad Diode <bd@badd10de.dev> | 2021-12-23 13:40:23 +0100 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2021-12-23 13:40:23 +0100 |
commit | 4c2be0ee13ce16c0274741f77c0d07ea768a2f64 (patch) | |
tree | 5b115d4dc5c991cc704fe5d76611911158d5e3d8 | |
parent | d22ba5b4f2758e5700d7cc32e3d20a75f1f3c9df (diff) | |
download | bdl-4c2be0ee13ce16c0274741f77c0d07ea768a2f64.tar.gz bdl-4c2be0ee13ce16c0274741f77c0d07ea768a2f64.zip |
Add `if` compilation for ir
-rw-r--r-- | src/ir.h | 28 |
1 files changed, 24 insertions, 4 deletions
@@ -10,6 +10,7 @@ typedef enum Op { | |||
10 | // Arithmetic ops. | 10 | // Arithmetic ops. |
11 | // - Binary operations. | 11 | // - Binary operations. |
12 | // - Arguments are passed via the stack. | 12 | // - Arguments are passed via the stack. |
13 | // - Consume two items in the stack. | ||
13 | OP_ADD, | 14 | OP_ADD, |
14 | OP_SUB, | 15 | OP_SUB, |
15 | OP_MUL, | 16 | OP_MUL, |
@@ -18,7 +19,7 @@ typedef enum Op { | |||
18 | // Logic ops. | 19 | // Logic ops. |
19 | OP_NOT, | 20 | OP_NOT, |
20 | // Stack ops. | 21 | // Stack ops. |
21 | // - Requires an Object to push into the stack. | 22 | // - Requires a constant Object to push into the stack. |
22 | OP_PUSH, | 23 | OP_PUSH, |
23 | // - Discards the last value in the stack. | 24 | // - Discards the last value in the stack. |
24 | OP_DROP, | 25 | OP_DROP, |
@@ -34,8 +35,9 @@ typedef enum Op { | |||
34 | OP_LABEL, | 35 | OP_LABEL, |
35 | // Jump/conditional ops. | 36 | // Jump/conditional ops. |
36 | // - Take a label as argument. | 37 | // - Take a label as argument. |
37 | // - For conditional jumps, the last value in the stack is used. | ||
38 | OP_JUMP, | 38 | OP_JUMP, |
39 | // - Consume one value in the stack. | ||
40 | // - All objects except `false` are considered `true`. | ||
39 | OP_JUMP_IF_TRUE, | 41 | OP_JUMP_IF_TRUE, |
40 | OP_JUMP_IF_FALSE, | 42 | OP_JUMP_IF_FALSE, |
41 | // - These require numerical objects on the stack. | 43 | // - These require numerical objects on the stack. |
@@ -96,7 +98,7 @@ typedef struct Instruction { | |||
96 | 98 | ||
97 | // OP_LABEL | 99 | // OP_LABEL |
98 | // OP_JUMP | 100 | // OP_JUMP |
99 | // OP_JUMP_IF_FALSE | 101 | // OP_JUMP_IF_xxx |
100 | size_t label_id; | 102 | size_t label_id; |
101 | }; | 103 | }; |
102 | 104 | ||
@@ -316,6 +318,7 @@ compile_proc_call(ProgramIr *program, Procedure *proc, Object *obj) { | |||
316 | case BUILTIN_LE: { | 318 | case BUILTIN_LE: { |
317 | compile_numeric_cmp(program, proc, OP_JUMP_IF_GT, line, col, obj->tail); | 319 | compile_numeric_cmp(program, proc, OP_JUMP_IF_GT, line, col, obj->tail); |
318 | } break; | 320 | } break; |
321 | // TODO: cons, car, cdr, type checks (nil? zero? fixnum? bool? ...) | ||
319 | default: { | 322 | default: { |
320 | assert(false && "builtin not implemented"); | 323 | assert(false && "builtin not implemented"); |
321 | } break; | 324 | } break; |
@@ -326,6 +329,23 @@ compile_proc_call(ProgramIr *program, Procedure *proc, Object *obj) { | |||
326 | } | 329 | } |
327 | 330 | ||
328 | void | 331 | void |
332 | compile_if(ProgramIr *program, Procedure *proc, Object *obj) { | ||
333 | size_t label_false = program->labels++; | ||
334 | compile_object(program, proc, obj->condition); | ||
335 | INST_ARG(proc, OP_JUMP_IF_FALSE, label_false, obj->line, obj->col); | ||
336 | compile_object(program, proc, obj->expr_true); | ||
337 | if (obj->expr_false != NULL) { | ||
338 | size_t label_exit = program->labels++; | ||
339 | INST_ARG(proc, OP_JUMP, label_exit, obj->line, obj->col); | ||
340 | INST_ARG(proc, OP_LABEL, label_false, obj->line, obj->col); | ||
341 | compile_object(program, proc, obj->expr_false); | ||
342 | INST_ARG(proc, OP_LABEL, label_exit, obj->line, obj->col); | ||
343 | } else { | ||
344 | INST_ARG(proc, OP_LABEL, label_false, obj->line, obj->col); | ||
345 | } | ||
346 | } | ||
347 | |||
348 | void | ||
329 | compile_object(ProgramIr *program, Procedure *proc, Object *obj) { | 349 | compile_object(ProgramIr *program, Procedure *proc, Object *obj) { |
330 | switch (obj->type) { | 350 | switch (obj->type) { |
331 | case OBJ_TYPE_NIL: | 351 | case OBJ_TYPE_NIL: |
@@ -336,7 +356,7 @@ compile_object(ProgramIr *program, Procedure *proc, Object *obj) { | |||
336 | INST_ARG(proc, OP_PUSH, obj, obj->line, obj->col); | 356 | INST_ARG(proc, OP_PUSH, obj, obj->line, obj->col); |
337 | } break; | 357 | } break; |
338 | case OBJ_TYPE_PAIR: { compile_proc_call(program, proc, obj); } break; | 358 | case OBJ_TYPE_PAIR: { compile_proc_call(program, proc, obj); } break; |
339 | // case OBJ_TYPE_IF: { compile_if(obj); } break; | 359 | case OBJ_TYPE_IF: { compile_if(program, proc, obj); } break; |
340 | // case OBJ_TYPE_LAMBDA: { compile_lambda(obj); } break; | 360 | // case OBJ_TYPE_LAMBDA: { compile_lambda(obj); } break; |
341 | // case OBJ_TYPE_DEF: { compile_def(obj); } break; | 361 | // case OBJ_TYPE_DEF: { compile_def(obj); } break; |
342 | // case OBJ_TYPE_SYMBOL: { compile_symbol(obj); } break; | 362 | // case OBJ_TYPE_SYMBOL: { compile_symbol(obj); } break; |