aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/compiler.c43
-rw-r--r--src/vm.c16
-rw-r--r--tests/compilation.bad3
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
117Str op_str[] = { 119Str 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
182typedef enum { 190typedef 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
291CompResult 299CompResult
300compile_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
328CompResult
292compile_expr(Chunk *chunk, Node *node) { 329compile_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:
diff --git a/src/vm.c b/src/vm.c
index 08a9ec3..338c364 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -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
31 * 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