aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-12-23 13:18:46 +0100
committerBad Diode <bd@badd10de.dev>2021-12-23 13:18:46 +0100
commitd22ba5b4f2758e5700d7cc32e3d20a75f1f3c9df (patch)
tree7cc500f9cc7ff7a47cfcc4aa49895d8db66bb0e1
parentb2afd9e4a0389d824421b7dfe6b4db522b7a722b (diff)
downloadbdl-d22ba5b4f2758e5700d7cc32e3d20a75f1f3c9df.tar.gz
bdl-d22ba5b4f2758e5700d7cc32e3d20a75f1f3c9df.zip
Add compilation of numerical comparison ops for ir
-rw-r--r--src/ir.h69
1 files changed, 69 insertions, 0 deletions
diff --git a/src/ir.h b/src/ir.h
index c1cdae4..514a3ac 100644
--- a/src/ir.h
+++ b/src/ir.h
@@ -22,6 +22,13 @@ typedef enum Op {
22 OP_PUSH, 22 OP_PUSH,
23 // - Discards the last value in the stack. 23 // - Discards the last value in the stack.
24 OP_DROP, 24 OP_DROP,
25 // - Duplicates the last value in the stack.
26 OP_DUP,
27 // - Rotates the last three elements in the stack.
28 // - Right: [ a b c -> c a b ]
29 // - Left: [ a b c -> b c a]
30 OP_ROT_RIGHT,
31 OP_ROT_LEFT,
25 // A label for memory access. 32 // A label for memory access.
26 // - The argument should be a unique value. 33 // - The argument should be a unique value.
27 OP_LABEL, 34 OP_LABEL,
@@ -31,6 +38,15 @@ typedef enum Op {
31 OP_JUMP, 38 OP_JUMP,
32 OP_JUMP_IF_TRUE, 39 OP_JUMP_IF_TRUE,
33 OP_JUMP_IF_FALSE, 40 OP_JUMP_IF_FALSE,
41 // - These require numerical objects on the stack.
42 // - Consume two items in the stack.
43 // - Jumps to the given label as argument when appropriate.
44 OP_JUMP_IF_EQ,
45 OP_JUMP_IF_NEQ,
46 OP_JUMP_IF_GT,
47 OP_JUMP_IF_LT,
48 OP_JUMP_IF_GE,
49 OP_JUMP_IF_LE,
34 // Primitive complex commands. 50 // Primitive complex commands.
35 // - Prints the last object in the stack. 51 // - Prints the last object in the stack.
36 OP_PRINT, 52 OP_PRINT,
@@ -52,10 +68,19 @@ static const char* ops_str[] = {
52 [OP_NOT] = "OP_NOT", 68 [OP_NOT] = "OP_NOT",
53 [OP_PUSH] = "OP_PUSH", 69 [OP_PUSH] = "OP_PUSH",
54 [OP_DROP] = "OP_DROP", 70 [OP_DROP] = "OP_DROP",
71 [OP_DUP] = "OP_DUP",
72 [OP_ROT_RIGHT] = "OP_ROT_RIGHT",
73 [OP_ROT_LEFT] = "OP_ROT_LEFT",
55 [OP_LABEL] = "OP_LABEL", 74 [OP_LABEL] = "OP_LABEL",
56 [OP_JUMP] = "OP_JUMP", 75 [OP_JUMP] = "OP_JUMP",
57 [OP_JUMP_IF_TRUE] = "OP_JUMP_IF_TRUE", 76 [OP_JUMP_IF_TRUE] = "OP_JUMP_IF_TRUE",
58 [OP_JUMP_IF_FALSE] = "OP_JUMP_IF_FALSE", 77 [OP_JUMP_IF_FALSE] = "OP_JUMP_IF_FALSE",
78 [OP_JUMP_IF_EQ] = "OP_JUMP_IF_EQ",
79 [OP_JUMP_IF_NEQ] = "OP_JUMP_IF_NEQ",
80 [OP_JUMP_IF_GT] = "OP_JUMP_IF_GT",
81 [OP_JUMP_IF_LT] = "OP_JUMP_IF_LT",
82 [OP_JUMP_IF_GE] = "OP_JUMP_IF_GE",
83 [OP_JUMP_IF_LE] = "OP_JUMP_IF_LE",
59 [OP_PRINT] = "OP_PRINT", 84 [OP_PRINT] = "OP_PRINT",
60 [OP_CALL] = "OP_CALL", 85 [OP_CALL] = "OP_CALL",
61 [OP_RETURN] = "OP_RETURN", 86 [OP_RETURN] = "OP_RETURN",
@@ -121,6 +146,12 @@ print_instruction(Instruction *instruction) {
121 case OP_JUMP: 146 case OP_JUMP:
122 case OP_JUMP_IF_TRUE: 147 case OP_JUMP_IF_TRUE:
123 case OP_JUMP_IF_FALSE: 148 case OP_JUMP_IF_FALSE:
149 case OP_JUMP_IF_EQ:
150 case OP_JUMP_IF_NEQ:
151 case OP_JUMP_IF_GT:
152 case OP_JUMP_IF_LT:
153 case OP_JUMP_IF_GE:
154 case OP_JUMP_IF_LE:
124 case OP_LABEL: { 155 case OP_LABEL: {
125 printf("%-16s -> %zu\n", ops_str[op], instruction->label_id); 156 printf("%-16s -> %zu\n", ops_str[op], instruction->label_id);
126 } break; 157 } break;
@@ -164,6 +195,29 @@ compile_arithmetic(ProgramIr *program, Procedure *proc, Op op,
164} 195}
165 196
166void 197void
198compile_numeric_cmp(ProgramIr *program, Procedure *proc, Op op,
199 size_t line, size_t col, Object *args) {
200 size_t label_false = program->labels++;
201 size_t label_exit = program->labels++;
202 compile_object(program, proc, args->head);
203 args = args->tail;
204 while (args != NULL) {
205 compile_object(program, proc, args->head);
206 args = args->tail;
207 INST_SIMPLE(proc, OP_DUP, line, col);
208 INST_SIMPLE(proc, OP_ROT_RIGHT, line, col);
209 INST_ARG(proc, op, label_false, line, col);
210 }
211 INST_SIMPLE(proc, OP_DROP, line, col);
212 INST_ARG(proc, OP_PUSH, &obj_true, line, col);
213 INST_ARG(proc, OP_JUMP, label_exit, line, col);
214 INST_ARG(proc, OP_LABEL, label_false, line, col);
215 INST_SIMPLE(proc, OP_DROP, line, col);
216 INST_ARG(proc, OP_PUSH, &obj_false, line, col);
217 INST_ARG(proc, OP_LABEL, label_exit, line, col);
218}
219
220void
167compile_print(ProgramIr *program, Procedure *proc, 221compile_print(ProgramIr *program, Procedure *proc,
168 size_t line, size_t col, Object *args) { 222 size_t line, size_t col, Object *args) {
169 while (args != NULL) { 223 while (args != NULL) {
@@ -247,6 +301,21 @@ compile_proc_call(ProgramIr *program, Procedure *proc, Object *obj) {
247 case BUILTIN_OR: { 301 case BUILTIN_OR: {
248 compile_or(program, proc, line, col, obj->tail); 302 compile_or(program, proc, line, col, obj->tail);
249 } break; 303 } break;
304 case BUILTIN_EQ: {
305 compile_numeric_cmp(program, proc, OP_JUMP_IF_NEQ, line, col, obj->tail);
306 } break;
307 case BUILTIN_GT: {
308 compile_numeric_cmp(program, proc, OP_JUMP_IF_LE, line, col, obj->tail);
309 } break;
310 case BUILTIN_LT: {
311 compile_numeric_cmp(program, proc, OP_JUMP_IF_GE, line, col, obj->tail);
312 } break;
313 case BUILTIN_GE: {
314 compile_numeric_cmp(program, proc, OP_JUMP_IF_LT, line, col, obj->tail);
315 } break;
316 case BUILTIN_LE: {
317 compile_numeric_cmp(program, proc, OP_JUMP_IF_GT, line, col, obj->tail);
318 } break;
250 default: { 319 default: {
251 assert(false && "builtin not implemented"); 320 assert(false && "builtin not implemented");
252 } break; 321 } break;