From 6f5f0875685832be6efa75016a46d4c69dbcfd36 Mon Sep 17 00:00:00 2001 From: Bad Diode Date: Sun, 9 Jan 2022 14:34:03 +0100 Subject: Add `compile_symbol` for ir --- src/ir.h | 113 +++++++++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 82 insertions(+), 31 deletions(-) diff --git a/src/ir.h b/src/ir.h index f039882..1c7a6c8 100644 --- a/src/ir.h +++ b/src/ir.h @@ -50,12 +50,16 @@ typedef enum Op { OP_JUMP_IF_GE, OP_JUMP_IF_LE, // Variable access. - // - Require an index corresponding to the local variable to store. + // - Require an index corresponding to the variable to store. // - Consume the last item in the stack. OP_STORE_LOCAL, - // - Require an index corresponding to the local variable to load. + OP_STORE_CAPTURED, + OP_STORE_PARAM, + // - Require an index corresponding to the variable to load. // - The loaded value is pushed into the stack. OP_LOAD_LOCAL, + OP_LOAD_CAPTURED, + OP_LOAD_PARAM, // Primitive complex commands. // - Prints the last object in the stack. OP_PRINT, @@ -69,32 +73,36 @@ typedef enum Op { } Op; static const char* ops_str[] = { - [OP_ADD] = "OP_ADD", - [OP_SUB] = "OP_SUB", - [OP_MUL] = "OP_MUL", - [OP_DIV] = "OP_DIV", - [OP_MOD] = "OP_MOD", - [OP_NOT] = "OP_NOT", - [OP_PUSH] = "OP_PUSH", - [OP_DROP] = "OP_DROP", - [OP_DUP] = "OP_DUP", - [OP_ROT_RIGHT] = "OP_ROT_RIGHT", - [OP_ROT_LEFT] = "OP_ROT_LEFT", - [OP_LABEL] = "OP_LABEL", - [OP_JUMP] = "OP_JUMP", - [OP_JUMP_IF_TRUE] = "OP_JUMP_IF_TRUE", - [OP_JUMP_IF_FALSE] = "OP_JUMP_IF_FALSE", - [OP_JUMP_IF_EQ] = "OP_JUMP_IF_EQ", - [OP_JUMP_IF_NEQ] = "OP_JUMP_IF_NEQ", - [OP_JUMP_IF_GT] = "OP_JUMP_IF_GT", - [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", + [OP_ADD] = "OP_ADD", + [OP_SUB] = "OP_SUB", + [OP_MUL] = "OP_MUL", + [OP_DIV] = "OP_DIV", + [OP_MOD] = "OP_MOD", + [OP_NOT] = "OP_NOT", + [OP_PUSH] = "OP_PUSH", + [OP_DROP] = "OP_DROP", + [OP_DUP] = "OP_DUP", + [OP_ROT_RIGHT] = "OP_ROT_RIGHT", + [OP_ROT_LEFT] = "OP_ROT_LEFT", + [OP_LABEL] = "OP_LABEL", + [OP_JUMP] = "OP_JUMP", + [OP_JUMP_IF_TRUE] = "OP_JUMP_IF_TRUE", + [OP_JUMP_IF_FALSE] = "OP_JUMP_IF_FALSE", + [OP_JUMP_IF_EQ] = "OP_JUMP_IF_EQ", + [OP_JUMP_IF_NEQ] = "OP_JUMP_IF_NEQ", + [OP_JUMP_IF_GT] = "OP_JUMP_IF_GT", + [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_STORE_CAPTURED] = "OP_STORE_CAPTURED", + [OP_STORE_PARAM] = "OP_STORE_PARAM", + [OP_LOAD_LOCAL] = "OP_LOAD_LOCAL", + [OP_LOAD_CAPTURED] = "OP_LOAD_CAPTURED", + [OP_LOAD_PARAM] = "OP_LOAD_PARAM", + [OP_PRINT] = "OP_PRINT", + [OP_CALL] = "OP_CALL", + [OP_RETURN] = "OP_RETURN", }; typedef struct Instruction { @@ -129,8 +137,10 @@ typedef struct Procedure { // Program code. Instruction *instructions; - // Locals code. + // Variables. Object **locals; + Object **captured; + Object **params; } Procedure; typedef struct ProgramIr { @@ -185,7 +195,11 @@ print_instruction(Instruction *instruction) { printf("%-16s -> %zu\n", ops_str[op], instruction->label_id); } break; case OP_STORE_LOCAL: - case OP_LOAD_LOCAL: { + case OP_STORE_CAPTURED: + case OP_STORE_PARAM: + case OP_LOAD_LOCAL: + case OP_LOAD_CAPTURED: + case OP_LOAD_PARAM: { printf("%-16s -> %zu\n", ops_str[op], instruction->index); } break; default: { @@ -210,6 +224,8 @@ proc_alloc(ProgramIr *program, StringView name, Procedure *parent) { array_insert(proc->name, name.start, name.n); array_init(proc->instructions, 0); array_init(proc->locals, 0); + array_init(proc->captured, 0); + array_init(proc->params, 0); proc->parent = parent; array_push(program->procedures, proc); return proc; @@ -417,6 +433,13 @@ compile_lambda(ProgramIr *program, Procedure *proc, Object *obj) { } array_push(program->lambdas, obj); Procedure *lambda = proc_alloc(program, STRING("lambda"), proc); + + // Parameters. + for (size_t i = 0; i < array_size(obj->params); ++i) { + array_push(lambda->params, obj->params[i]); + } + + // Body. for (size_t i = 0; i < array_size(obj->body) - 1; i++) { compile_object(program, lambda, obj->body[i]); } @@ -469,6 +492,34 @@ compile_lambda(ProgramIr *program, Procedure *proc, Object *obj) { INST_ARG(proc, OP_PUSH, obj, obj->line, obj->col); } +void +compile_symbol(ProgramIr *program, Procedure *proc, Object *obj) { + ssize_t idx = -1; + + // Is a local variable? + idx = find_var_index(proc->locals, obj); + if (idx != -1) { + INST_VAR(proc, OP_LOAD_LOCAL, idx, obj->line, obj->col); + return; + } + + // Is a captured variable? + idx = find_var_index(proc->captured, obj); + if (idx != -1) { + INST_VAR(proc, OP_LOAD_CAPTURED, idx, obj->line, obj->col); + return; + } + + // Is a function parameter? + idx = find_var_index(proc->params, obj); + if (idx != -1) { + INST_VAR(proc, OP_LOAD_PARAM, idx, obj->line, obj->col); + return; + } + + assert(idx != -1 && "unexpected index"); +} + void compile_object(ProgramIr *program, Procedure *proc, Object *obj) { switch (obj->type) { @@ -481,7 +532,7 @@ compile_object(ProgramIr *program, Procedure *proc, Object *obj) { case OBJ_TYPE_IF: { compile_if(program, proc, obj); } break; case OBJ_TYPE_LAMBDA: { compile_lambda(program, proc, obj); } break; case OBJ_TYPE_DEF: { compile_def(program, proc, obj); } break; - // case OBJ_TYPE_SYMBOL: { compile_symbol(obj); } break; + case OBJ_TYPE_SYMBOL: { compile_symbol(program, proc, obj); } break; default: { // TODO: assert? fprintf(stderr, "NOT IMPLEMENTED: compile_object for "); -- cgit v1.2.1