From 4c2be0ee13ce16c0274741f77c0d07ea768a2f64 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Thu, 23 Dec 2021 13:40:23 +0100 Subject: Add `if` compilation for ir --- src/ir.h | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/src/ir.h b/src/ir.h index 514a3ac..c87babe 100644 --- a/src/ir.h +++ b/src/ir.h @@ -10,6 +10,7 @@ typedef enum Op { // Arithmetic ops. // - Binary operations. // - Arguments are passed via the stack. + // - Consume two items in the stack. OP_ADD, OP_SUB, OP_MUL, @@ -18,7 +19,7 @@ typedef enum Op { // Logic ops. OP_NOT, // Stack ops. - // - Requires an Object to push into the stack. + // - Requires a constant Object to push into the stack. OP_PUSH, // - Discards the last value in the stack. OP_DROP, @@ -34,8 +35,9 @@ typedef enum Op { OP_LABEL, // Jump/conditional ops. // - Take a label as argument. - // - For conditional jumps, the last value in the stack is used. OP_JUMP, + // - Consume one value in the stack. + // - All objects except `false` are considered `true`. OP_JUMP_IF_TRUE, OP_JUMP_IF_FALSE, // - These require numerical objects on the stack. @@ -96,7 +98,7 @@ typedef struct Instruction { // OP_LABEL // OP_JUMP - // OP_JUMP_IF_FALSE + // OP_JUMP_IF_xxx size_t label_id; }; @@ -316,6 +318,7 @@ compile_proc_call(ProgramIr *program, Procedure *proc, Object *obj) { case BUILTIN_LE: { compile_numeric_cmp(program, proc, OP_JUMP_IF_GT, line, col, obj->tail); } break; + // TODO: cons, car, cdr, type checks (nil? zero? fixnum? bool? ...) default: { assert(false && "builtin not implemented"); } break; @@ -325,6 +328,23 @@ compile_proc_call(ProgramIr *program, Procedure *proc, Object *obj) { } } +void +compile_if(ProgramIr *program, Procedure *proc, Object *obj) { + size_t label_false = program->labels++; + compile_object(program, proc, obj->condition); + INST_ARG(proc, OP_JUMP_IF_FALSE, label_false, obj->line, obj->col); + compile_object(program, proc, obj->expr_true); + if (obj->expr_false != NULL) { + size_t label_exit = program->labels++; + INST_ARG(proc, OP_JUMP, label_exit, obj->line, obj->col); + INST_ARG(proc, OP_LABEL, label_false, obj->line, obj->col); + compile_object(program, proc, obj->expr_false); + INST_ARG(proc, OP_LABEL, label_exit, obj->line, obj->col); + } else { + INST_ARG(proc, OP_LABEL, label_false, obj->line, obj->col); + } +} + void compile_object(ProgramIr *program, Procedure *proc, Object *obj) { switch (obj->type) { @@ -336,7 +356,7 @@ compile_object(ProgramIr *program, Procedure *proc, Object *obj) { INST_ARG(proc, OP_PUSH, obj, obj->line, obj->col); } break; case OBJ_TYPE_PAIR: { compile_proc_call(program, proc, obj); } break; - // case OBJ_TYPE_IF: { compile_if(obj); } break; + case OBJ_TYPE_IF: { compile_if(program, proc, obj); } break; // case OBJ_TYPE_LAMBDA: { compile_lambda(obj); } break; // case OBJ_TYPE_DEF: { compile_def(obj); } break; // case OBJ_TYPE_SYMBOL: { compile_symbol(obj); } break; -- cgit v1.2.1