aboutsummaryrefslogtreecommitdiffstats
path: root/clox/src/vm.c
diff options
context:
space:
mode:
Diffstat (limited to 'clox/src/vm.c')
-rw-r--r--clox/src/vm.c41
1 files changed, 32 insertions, 9 deletions
diff --git a/clox/src/vm.c b/clox/src/vm.c
index eb79661..381c8c0 100644
--- a/clox/src/vm.c
+++ b/clox/src/vm.c
@@ -1,3 +1,4 @@
+#include <stdarg.h>
#include <stdio.h>
#include "common.h"
@@ -9,6 +10,19 @@ VM vm;
static void resetStack() { vm.stackTop = vm.stack; }
+static void runtimeError(const char *format, ...) {
+ va_list args;
+ va_start(args, format);
+ vfprintf(stderr, format, args);
+ va_end(args);
+ fputs("\n", stderr);
+
+ size_t instruction = vm.ip - vm.chunk->code - 1;
+ int line = vm.chunk->lines[instruction];
+ fprintf(stderr, "[line %d] in script\n", line);
+ resetStack();
+}
+
void initVM() { resetStack(); }
void freeVM() {}
@@ -23,14 +37,19 @@ Value pop() {
return *vm.stackTop;
}
+static Value peek(int distance) { return vm.stackTop[-1 - distance]; }
+
static InterpretResult run() {
#define READ_BYTE() (*vm.ip++)
#define READ_CONSTANT() (vm.chunk->constants.values[READ_BYTE()])
-#define BINARY_OP(op) \
+#define BINARY_OP(valueType, op) \
do { \
- double b = pop(); \
- double a = pop(); \
- push(a op b); \
+ if (!IS_NUMBER(peek(0)) || !IS_NUMBER(peek(1))) { \
+ runtimeError("Operands must be numbers."); \
+ } \
+ double b = AS_NUMBER(pop()); \
+ double a = AS_NUMBER(pop()); \
+ push(valueType(a op b)); \
} while (false)
for (;;) {
@@ -53,19 +72,23 @@ static InterpretResult run() {
break;
}
case OP_ADD:
- BINARY_OP(+);
+ BINARY_OP(NUMBER_VAL, +);
break;
case OP_SUBTRACT:
- BINARY_OP(-);
+ BINARY_OP(NUMBER_VAL, -);
break;
case OP_MULTIPLY:
- BINARY_OP(*);
+ BINARY_OP(NUMBER_VAL, *);
break;
case OP_DIVIDE:
- BINARY_OP(/);
+ BINARY_OP(NUMBER_VAL, /);
break;
case OP_NEGATE:
- push(-pop());
+ if (!IS_NUMBER(peek(0))) {
+ runtimeError("Operand must be a number.");
+ return INTERPRET_RUNTIME_ERROR;
+ }
+ push(NUMBER_VAL(-AS_NUMBER(pop())));
break;
case OP_RETURN: {
printValue(pop());