summaryrefslogtreecommitdiff
path: root/vm.c
diff options
context:
space:
mode:
Diffstat (limited to 'vm.c')
-rw-r--r--vm.c24
1 files changed, 21 insertions, 3 deletions
diff --git a/vm.c b/vm.c
index 70aca3d..e969692 100644
--- a/vm.c
+++ b/vm.c
@@ -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;