diff options
-rw-r--r-- | src/compiler.c | 43 | ||||
-rw-r--r-- | src/vm.c | 16 | ||||
-rw-r--r-- | tests/compilation.bad | 3 |
3 files changed, 58 insertions, 4 deletions
diff --git a/src/compiler.c b/src/compiler.c index 51d7cd6..d16b335 100644 --- a/src/compiler.c +++ b/src/compiler.c | |||
@@ -104,6 +104,7 @@ typedef enum OpCode { | |||
104 | OP_GEI, // gek rx, ra, cb | 104 | OP_GEI, // gek rx, ra, cb |
105 | OP_ANDI, // andk rx, ra, cb | 105 | OP_ANDI, // andk rx, ra, cb |
106 | OP_ORI, // ork rx, ra, cb | 106 | OP_ORI, // ork rx, ra, cb |
107 | OP_NOTI, // noti rx, ra | ||
107 | OP_EQ, // eq rx, ra, rb | 108 | OP_EQ, // eq rx, ra, rb |
108 | OP_NEQ, // neq rx, ra, rb | 109 | OP_NEQ, // neq rx, ra, rb |
109 | OP_LT, // lt rx, ra, rb | 110 | OP_LT, // lt rx, ra, rb |
@@ -112,6 +113,7 @@ typedef enum OpCode { | |||
112 | OP_GE, // ge rx, ra, rb | 113 | OP_GE, // ge rx, ra, rb |
113 | OP_AND, // and rx, ra, rb | 114 | OP_AND, // and rx, ra, rb |
114 | OP_OR, // or rx, ra, rb | 115 | OP_OR, // or rx, ra, rb |
116 | OP_NOT, // not rx, ra | ||
115 | } OpCode; | 117 | } OpCode; |
116 | 118 | ||
117 | Str op_str[] = { | 119 | Str op_str[] = { |
@@ -171,12 +173,18 @@ Str op_str[] = { | |||
171 | [OP_GTI] = cstr("GTI "), | 173 | [OP_GTI] = cstr("GTI "), |
172 | [OP_LEI] = cstr("LEI "), | 174 | [OP_LEI] = cstr("LEI "), |
173 | [OP_GEI] = cstr("GEI "), | 175 | [OP_GEI] = cstr("GEI "), |
176 | [OP_ANDI] = cstr("ANDI "), | ||
177 | [OP_ORI] = cstr("ORI "), | ||
178 | [OP_NOTI] = cstr("NOTI "), | ||
174 | [OP_EQ] = cstr("EQ "), | 179 | [OP_EQ] = cstr("EQ "), |
175 | [OP_NEQ] = cstr("NEQ "), | 180 | [OP_NEQ] = cstr("NEQ "), |
176 | [OP_LT] = cstr("LT "), | 181 | [OP_LT] = cstr("LT "), |
177 | [OP_GT] = cstr("GT "), | 182 | [OP_GT] = cstr("GT "), |
178 | [OP_LE] = cstr("LE "), | 183 | [OP_LE] = cstr("LE "), |
179 | [OP_GE] = cstr("GE "), | 184 | [OP_GE] = cstr("GE "), |
185 | [OP_AND] = cstr("AND "), | ||
186 | [OP_OR] = cstr("OR "), | ||
187 | [OP_NOT] = cstr("NOT "), | ||
180 | }; | 188 | }; |
181 | 189 | ||
182 | typedef enum { | 190 | typedef enum { |
@@ -250,8 +258,8 @@ compile_binary(Chunk *chunk, Node *node) { | |||
250 | case NODE_GT: op = OP_GT; break; | 258 | case NODE_GT: op = OP_GT; break; |
251 | case NODE_LE: op = OP_LE; break; | 259 | case NODE_LE: op = OP_LE; break; |
252 | case NODE_GE: op = OP_GE; break; | 260 | case NODE_GE: op = OP_GE; break; |
253 | case NODE_AND: op = OP_EQ; break; | 261 | case NODE_AND: op = OP_AND; break; |
254 | case NODE_OR: op = OP_NEQ; break; | 262 | case NODE_OR: op = OP_OR; break; |
255 | default: break; | 263 | default: break; |
256 | } | 264 | } |
257 | CompResult comp_a = compile_expr(chunk, node->left); | 265 | CompResult comp_a = compile_expr(chunk, node->left); |
@@ -289,11 +297,40 @@ compile_binary(Chunk *chunk, Node *node) { | |||
289 | } | 297 | } |
290 | 298 | ||
291 | CompResult | 299 | CompResult |
300 | compile_unary(Chunk *chunk, Node *node) { | ||
301 | OpCode op = OP_HALT; | ||
302 | OpCode ldop = OP_LD64K; | ||
303 | switch (node->kind) { | ||
304 | case NODE_NOT: { | ||
305 | op = OP_NOT; | ||
306 | } break; | ||
307 | default: break; | ||
308 | } | ||
309 | CompResult comp_a = compile_expr(chunk, node->left); | ||
310 | sz reg_a; | ||
311 | switch (comp_a.type) { | ||
312 | case COMP_CONST: { | ||
313 | reg_a = chunk->reg_idx++; | ||
314 | EMIT_OP(ldop, reg_a, comp_a.idx, 0, node, chunk); | ||
315 | } break; | ||
316 | case COMP_REG: { | ||
317 | reg_a = comp_a.idx; | ||
318 | } break; | ||
319 | default: { | ||
320 | return (CompResult){.type = COMP_ERR}; | ||
321 | } break; | ||
322 | } | ||
323 | sz reg_dst = chunk->reg_idx++; | ||
324 | EMIT_OP(op, reg_dst, reg_a, 0, node, chunk); | ||
325 | return (CompResult){.type = COMP_REG, .idx = reg_dst}; | ||
326 | } | ||
327 | |||
328 | CompResult | ||
292 | compile_expr(Chunk *chunk, Node *node) { | 329 | compile_expr(Chunk *chunk, Node *node) { |
293 | switch (node->kind) { | 330 | switch (node->kind) { |
294 | // Logic. | 331 | // Logic. |
295 | // case NODE_NOT: | ||
296 | // case NODE_XOR: | 332 | // case NODE_XOR: |
333 | case NODE_NOT: return compile_unary(chunk, node); break; | ||
297 | case NODE_AND: | 334 | case NODE_AND: |
298 | case NODE_OR: | 335 | case NODE_OR: |
299 | case NODE_EQ: | 336 | case NODE_EQ: |
@@ -79,6 +79,14 @@ disassemble_instruction(Instruction instruction) { | |||
79 | println("%s r%d, r%d, r%d", op_str[instruction.op], instruction.dst, | 79 | println("%s r%d, r%d, r%d", op_str[instruction.op], instruction.dst, |
80 | instruction.a, instruction.b); | 80 | instruction.a, instruction.b); |
81 | break; | 81 | break; |
82 | case OP_NOTI: | ||
83 | println("%s r%d, c%d", op_str[instruction.op], instruction.dst, | ||
84 | instruction.a, instruction.b); | ||
85 | break; | ||
86 | case OP_NOT: | ||
87 | println("%s r%d, r%d", op_str[instruction.op], instruction.dst, | ||
88 | instruction.a, instruction.b); | ||
89 | break; | ||
82 | case OP_HALT: println("%s", op_str[instruction.op]); break; | 90 | case OP_HALT: println("%s", op_str[instruction.op]); break; |
83 | default: println("Unknown opcode %d", instruction.op); break; | 91 | default: println("Unknown opcode %d", instruction.op); break; |
84 | } | 92 | } |
@@ -130,6 +138,13 @@ vm_init(VM *vm, Chunk *chunk) { | |||
130 | vm->regs[dst].TYPE = vm->regs[src_a].TYPE OP vm->regs[src_b].TYPE; \ | 138 | vm->regs[dst].TYPE = vm->regs[src_a].TYPE OP vm->regs[src_b].TYPE; \ |
131 | } while (0); | 139 | } while (0); |
132 | 140 | ||
141 | #define OP_UNARY(OP, TYPE) \ | ||
142 | do { \ | ||
143 | u8 dst = instruction.dst; \ | ||
144 | u8 src_a = instruction.a; \ | ||
145 | vm->regs[dst].TYPE = OP vm->regs[src_a].TYPE; \ | ||
146 | } while (0); | ||
147 | |||
133 | #define OP_BINARY_CONST(OP, TYPE) \ | 148 | #define OP_BINARY_CONST(OP, TYPE) \ |
134 | do { \ | 149 | do { \ |
135 | u8 dst = instruction.dst; \ | 150 | u8 dst = instruction.dst; \ |
@@ -160,6 +175,7 @@ vm_run(VM *vm) { | |||
160 | u8 src_a = instruction.a; | 175 | u8 src_a = instruction.a; |
161 | vm->regs[dst].i = vm->chunk->constants[src_a].i; | 176 | vm->regs[dst].i = vm->chunk->constants[src_a].i; |
162 | } break; | 177 | } break; |
178 | case OP_NOT: OP_UNARY(!, i) break; | ||
163 | case OP_EQ: OP_BINARY(==, i) break; | 179 | case OP_EQ: OP_BINARY(==, i) break; |
164 | case OP_NEQ: OP_BINARY(!=, i) break; | 180 | case OP_NEQ: OP_BINARY(!=, i) break; |
165 | case OP_LT: OP_BINARY(<, i) break; | 181 | case OP_LT: OP_BINARY(<, i) break; |
diff --git a/tests/compilation.bad b/tests/compilation.bad index da6a6e3..90ed1ca 100644 --- a/tests/compilation.bad +++ b/tests/compilation.bad | |||
@@ -1,6 +1,7 @@ | |||
1 | ; 1 < 2 | 1 | ; 1 < 2 |
2 | ; !(1 == 0 || 1 <= 1) | ||
2 | ; 1 == 1 && 1 <= 1 | 3 | ; 1 == 1 && 1 <= 1 |
3 | 1 * 3 >= 3 && 4 != 3 + 2 | 4 | !(1 * 3 >= 3 && 4 != 3 + 2) |
4 | ; 1 + 2 * 3 | 5 | ; 1 + 2 * 3 |
5 | ; 1.0 + 2.0 * 3.0 | 6 | ; 1.0 + 2.0 * 3.0 |
6 | ; true | 7 | ; true |