diff options
Diffstat (limited to 'src/ir.h')
-rw-r--r-- | src/ir.h | 44 |
1 files changed, 40 insertions, 4 deletions
@@ -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 | |||
145 | void | 167 | void |
146 | print_instruction(Instruction *instruction) { | 168 | print_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 | ||
354 | void | 381 | void |
382 | compile_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 | |||
392 | void | ||
355 | compile_object(ProgramIr *program, Procedure *proc, Object *obj) { | 393 | compile_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? |