diff options
Diffstat (limited to 'vm.c')
-rw-r--r-- | vm.c | 24 |
1 files changed, 21 insertions, 3 deletions
@@ -3,6 +3,7 @@ #include <stdlib.h> #include <stdbool.h> #include <stdio.h> +#include <math.h> #include "val.h" #include "vm.h" @@ -130,7 +131,7 @@ int runvm(State *S) { break; } -#define ARITH_OP(opcode, OP) \ +#define BINARY_OP(opcode, OP, RET_TYPE) \ case opcode: { \ Val b = POP(); \ Val a = POP(); \ @@ -139,15 +140,32 @@ int runvm(State *S) { typename_str(a), typename_str(b)); \ goto done; \ } \ - PUSH(VAL_NUM(AS_NUM(a) OP AS_NUM(b))); \ + PUSH(RET_TYPE(AS_NUM(a) OP AS_NUM(b))); \ } \ break; - +#define ARITH_OP(opcode, OP) BINARY_OP(opcode, OP, VAL_NUM) +#define BOOL_OP(opcode, OP) BINARY_OP(opcode, OP, VAL_BOOL) ARITH_OP(OP_ADD, +) ARITH_OP(OP_SUB, -) ARITH_OP(OP_MUL, *) ARITH_OP(OP_DIV, /) + BOOL_OP(OP_EQU, ==) + BOOL_OP(OP_CMP, <) +#undef BINARY_OP #undef ARITH_OP +#undef BOOL_OP + case OP_MOD: { + Val b = POP(); + Val a = POP(); + if (!IS_NUM(a) || !IS_NUM(b)) { + printf("can't do arithmetic on %s and %s", + typename_str(a), typename_str(b)); + goto done; + } + PUSH(VAL_NUM(fmod(AS_NUM(a), AS_NUM(b)))); + } + break; + case OP_NIL: PUSH(VAL_NIL); break; case OP_TRUE: PUSH(VAL_TRUE); break; |