aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-12-30 14:33:11 +0100
committerBad Diode <bd@badd10de.dev>2021-12-30 14:33:11 +0100
commite8a30ba744982f1f00db6a962bd849ef53514bff (patch)
tree6345e9d6c8d54b91b35908e162670917860e9533
parent97b0a3dcdf750ae36eb40cdc57b30b1ee021d3d3 (diff)
downloadbdl-e8a30ba744982f1f00db6a962bd849ef53514bff.tar.gz
bdl-e8a30ba744982f1f00db6a962bd849ef53514bff.zip
Add `def` builtin and local var load/store ops
-rw-r--r--src/ir.h44
1 files 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 {
49 OP_JUMP_IF_LT, 49 OP_JUMP_IF_LT,
50 OP_JUMP_IF_GE, 50 OP_JUMP_IF_GE,
51 OP_JUMP_IF_LE, 51 OP_JUMP_IF_LE,
52 // Variable access.
53 // - Require an index corresponding to the local variable to store.
54 // - Consume the last item in the stack.
55 OP_STORE_LOCAL,
56 // - Require an index corresponding to the local variable to load.
57 // - The loaded value is pushed into the stack.
58 OP_LOAD_LOCAL,
52 // Primitive complex commands. 59 // Primitive complex commands.
53 // - Prints the last object in the stack. 60 // - Prints the last object in the stack.
54 OP_PRINT, 61 OP_PRINT,
@@ -83,6 +90,8 @@ static const char* ops_str[] = {
83 [OP_JUMP_IF_LT] = "OP_JUMP_IF_LT", 90 [OP_JUMP_IF_LT] = "OP_JUMP_IF_LT",
84 [OP_JUMP_IF_GE] = "OP_JUMP_IF_GE", 91 [OP_JUMP_IF_GE] = "OP_JUMP_IF_GE",
85 [OP_JUMP_IF_LE] = "OP_JUMP_IF_LE", 92 [OP_JUMP_IF_LE] = "OP_JUMP_IF_LE",
93 [OP_STORE_LOCAL] = "OP_STORE_LOCAL",
94 [OP_LOAD_LOCAL] = "OP_LOAD_LOCAL",
86 [OP_PRINT] = "OP_PRINT", 95 [OP_PRINT] = "OP_PRINT",
87 [OP_CALL] = "OP_CALL", 96 [OP_CALL] = "OP_CALL",
88 [OP_RETURN] = "OP_RETURN", 97 [OP_RETURN] = "OP_RETURN",
@@ -100,6 +109,10 @@ typedef struct Instruction {
100 // OP_JUMP 109 // OP_JUMP
101 // OP_JUMP_IF_xxx 110 // OP_JUMP_IF_xxx
102 size_t label_id; 111 size_t label_id;
112
113 // OP_STORE_LOCAL
114 // OP_LOAD_LOCAL
115 size_t index;
103 }; 116 };
104 117
105 // Original line/column for debugging purposes. 118 // Original line/column for debugging purposes.
@@ -114,6 +127,9 @@ typedef struct Procedure {
114 // Program code. 127 // Program code.
115 Instruction *instructions; 128 Instruction *instructions;
116 129
130 // Locals code.
131 Object **locals;
132
117 // Number of locals and parameters. 133 // Number of locals and parameters.
118 size_t n_params; 134 size_t n_params;
119 size_t n_locals; 135 size_t n_locals;
@@ -142,6 +158,12 @@ typedef struct ProgramIr {
142 array_push((PROC)->instructions, inst); \ 158 array_push((PROC)->instructions, inst); \
143 } while(false); 159 } while(false);
144 160
161#define INST_VAR(PROC, OP, ARG, LINE, COL) \
162 do { \
163 Instruction inst = (Instruction){(OP), .index = (ARG), (LINE), (COL)}; \
164 array_push((PROC)->instructions, inst); \
165 } while(false);
166
145void 167void
146print_instruction(Instruction *instruction) { 168print_instruction(Instruction *instruction) {
147 printf("%4ld:%-4ld ", instruction->line, instruction->col); 169 printf("%4ld:%-4ld ", instruction->line, instruction->col);
@@ -163,6 +185,10 @@ print_instruction(Instruction *instruction) {
163 case OP_LABEL: { 185 case OP_LABEL: {
164 printf("%-16s -> %zu\n", ops_str[op], instruction->label_id); 186 printf("%-16s -> %zu\n", ops_str[op], instruction->label_id);
165 } break; 187 } break;
188 case OP_STORE_LOCAL:
189 case OP_LOAD_LOCAL: {
190 printf("%-16s -> %zu\n", ops_str[op], instruction->index);
191 } break;
166 default: { 192 default: {
167 printf("%s\n", ops_str[op]); 193 printf("%s\n", ops_str[op]);
168 } break; 194 } break;
@@ -184,6 +210,7 @@ proc_alloc(ProgramIr *program, StringView name) {
184 array_init(proc->name, name.n); 210 array_init(proc->name, name.n);
185 array_insert(proc->name, name.start, name.n); 211 array_insert(proc->name, name.start, name.n);
186 array_init(proc->instructions, 0); 212 array_init(proc->instructions, 0);
213 array_init(proc->locals, 0);
187 array_push(program->procedures, proc); 214 array_push(program->procedures, proc);
188 return proc; 215 return proc;
189} 216}
@@ -352,19 +379,28 @@ compile_if(ProgramIr *program, Procedure *proc, Object *obj) {
352} 379}
353 380
354void 381void
382compile_def(ProgramIr *program, Procedure *proc, Object *obj) {
383 ssize_t idx = find_var_index(proc->locals, obj->var_name);
384 if (idx == -1) {
385 array_push(proc->locals, obj->var_name);
386 idx = array_size(proc->locals) - 1;
387 }
388 compile_object(program, proc, obj->var_expr);
389 INST_VAR(proc, OP_STORE_LOCAL, idx, obj->line, obj->col);
390}
391
392void
355compile_object(ProgramIr *program, Procedure *proc, Object *obj) { 393compile_object(ProgramIr *program, Procedure *proc, Object *obj) {
356 switch (obj->type) { 394 switch (obj->type) {
357 case OBJ_TYPE_NIL: 395 case OBJ_TYPE_NIL:
358 case OBJ_TYPE_TRUE: 396 case OBJ_TYPE_TRUE:
359 case OBJ_TYPE_FALSE: 397 case OBJ_TYPE_FALSE:
360 case OBJ_TYPE_STRING: 398 case OBJ_TYPE_STRING:
361 case OBJ_TYPE_FIXNUM: { 399 case OBJ_TYPE_FIXNUM: { INST_ARG(proc, OP_PUSH, obj, obj->line, obj->col); } break;
362 INST_ARG(proc, OP_PUSH, obj, obj->line, obj->col);
363 } break;
364 case OBJ_TYPE_PAIR: { compile_proc_call(program, proc, obj); } break; 400 case OBJ_TYPE_PAIR: { compile_proc_call(program, proc, obj); } break;
365 case OBJ_TYPE_IF: { compile_if(program, proc, obj); } break; 401 case OBJ_TYPE_IF: { compile_if(program, proc, obj); } break;
366 // case OBJ_TYPE_LAMBDA: { compile_lambda(obj); } break; 402 // case OBJ_TYPE_LAMBDA: { compile_lambda(obj); } break;
367 // case OBJ_TYPE_DEF: { compile_def(obj); } break; 403 case OBJ_TYPE_DEF: { compile_def(program, proc, obj); } break;
368 // case OBJ_TYPE_SYMBOL: { compile_symbol(obj); } break; 404 // case OBJ_TYPE_SYMBOL: { compile_symbol(obj); } break;
369 default: { 405 default: {
370 // TODO: assert? 406 // TODO: assert?