From e8a30ba744982f1f00db6a962bd849ef53514bff Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Thu, 30 Dec 2021 14:33:11 +0100 Subject: Add `def` builtin and local var load/store ops --- src/ir.h | 44 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/src/ir.h b/src/ir.h index 8518adb..d9706ee 100644 --- a/src/ir.h +++ b/src/ir.h @@ -49,6 +49,13 @@ typedef enum Op { OP_JUMP_IF_LT, OP_JUMP_IF_GE, OP_JUMP_IF_LE, + // Variable access. + // - Require an index corresponding to the local variable to store. + // - Consume the last item in the stack. + OP_STORE_LOCAL, + // - Require an index corresponding to the local variable to load. + // - The loaded value is pushed into the stack. + OP_LOAD_LOCAL, // Primitive complex commands. // - Prints the last object in the stack. OP_PRINT, @@ -83,6 +90,8 @@ static const char* ops_str[] = { [OP_JUMP_IF_LT] = "OP_JUMP_IF_LT", [OP_JUMP_IF_GE] = "OP_JUMP_IF_GE", [OP_JUMP_IF_LE] = "OP_JUMP_IF_LE", + [OP_STORE_LOCAL] = "OP_STORE_LOCAL", + [OP_LOAD_LOCAL] = "OP_LOAD_LOCAL", [OP_PRINT] = "OP_PRINT", [OP_CALL] = "OP_CALL", [OP_RETURN] = "OP_RETURN", @@ -100,6 +109,10 @@ typedef struct Instruction { // OP_JUMP // OP_JUMP_IF_xxx size_t label_id; + + // OP_STORE_LOCAL + // OP_LOAD_LOCAL + size_t index; }; // Original line/column for debugging purposes. @@ -114,6 +127,9 @@ typedef struct Procedure { // Program code. Instruction *instructions; + // Locals code. + Object **locals; + // Number of locals and parameters. size_t n_params; size_t n_locals; @@ -142,6 +158,12 @@ typedef struct ProgramIr { array_push((PROC)->instructions, inst); \ } while(false); +#define INST_VAR(PROC, OP, ARG, LINE, COL) \ + do { \ + Instruction inst = (Instruction){(OP), .index = (ARG), (LINE), (COL)}; \ + array_push((PROC)->instructions, inst); \ + } while(false); + void print_instruction(Instruction *instruction) { printf("%4ld:%-4ld ", instruction->line, instruction->col); @@ -163,6 +185,10 @@ print_instruction(Instruction *instruction) { case OP_LABEL: { printf("%-16s -> %zu\n", ops_str[op], instruction->label_id); } break; + case OP_STORE_LOCAL: + case OP_LOAD_LOCAL: { + printf("%-16s -> %zu\n", ops_str[op], instruction->index); + } break; default: { printf("%s\n", ops_str[op]); } break; @@ -184,6 +210,7 @@ proc_alloc(ProgramIr *program, StringView name) { array_init(proc->name, name.n); array_insert(proc->name, name.start, name.n); array_init(proc->instructions, 0); + array_init(proc->locals, 0); array_push(program->procedures, proc); return proc; } @@ -351,6 +378,17 @@ compile_if(ProgramIr *program, Procedure *proc, Object *obj) { } } +void +compile_def(ProgramIr *program, Procedure *proc, Object *obj) { + ssize_t idx = find_var_index(proc->locals, obj->var_name); + if (idx == -1) { + array_push(proc->locals, obj->var_name); + idx = array_size(proc->locals) - 1; + } + compile_object(program, proc, obj->var_expr); + INST_VAR(proc, OP_STORE_LOCAL, idx, obj->line, obj->col); +} + void compile_object(ProgramIr *program, Procedure *proc, Object *obj) { switch (obj->type) { @@ -358,13 +396,11 @@ compile_object(ProgramIr *program, Procedure *proc, Object *obj) { case OBJ_TYPE_TRUE: case OBJ_TYPE_FALSE: case OBJ_TYPE_STRING: - case OBJ_TYPE_FIXNUM: { - INST_ARG(proc, OP_PUSH, obj, obj->line, obj->col); - } break; + case OBJ_TYPE_FIXNUM: { 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(program, proc, obj); } break; // case OBJ_TYPE_LAMBDA: { compile_lambda(obj); } break; - // case OBJ_TYPE_DEF: { compile_def(obj); } break; + case OBJ_TYPE_DEF: { compile_def(program, proc, obj); } break; // case OBJ_TYPE_SYMBOL: { compile_symbol(obj); } break; default: { // TODO: assert? -- cgit v1.2.1