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.c31
1 files changed, 29 insertions, 2 deletions
diff --git a/clox/src/vm.c b/clox/src/vm.c
index df9f490..fae0092 100644
--- a/clox/src/vm.c
+++ b/clox/src/vm.c
@@ -1,9 +1,12 @@
#include <stdarg.h>
#include <stdio.h>
+#include <string.h>
#include "common.h"
#include "compiler.h"
#include "debug.h"
+#include "memory.h"
+#include "object.h"
#include "vm.h"
VM vm;
@@ -43,6 +46,20 @@ static bool isFalsey(Value value) {
return IS_NIL(value) || (IS_BOOL(value) && !AS_BOOL(value));
}
+static void concatenate() {
+ ObjString *b = AS_STRING(pop());
+ ObjString *a = AS_STRING(pop());
+
+ int length = a->length + b->length;
+ char *chars = ALLOCATE(char, length + 1);
+ memcpy(chars, a->chars, a->length);
+ memcpy(chars + a->length, b->chars, b->length);
+ chars[length] = '\0';
+
+ ObjString *result = takeString(chars, length);
+ push(OBJ_VAL(result));
+}
+
static InterpretResult run() {
#define READ_BYTE() (*vm.ip++)
#define READ_CONSTANT() (vm.chunk->constants.values[READ_BYTE()])
@@ -96,9 +113,19 @@ static InterpretResult run() {
case OP_LESS:
BINARY_OP(BOOL_VAL, <);
break;
- case OP_ADD:
- BINARY_OP(NUMBER_VAL, +);
+ case OP_ADD: {
+ if (IS_STRING(peek(0)) && IS_STRING(peek(1))) {
+ concatenate();
+ } else if (IS_NUMBER(peek(0)) && IS_NUMBER(peek(1))) {
+ double b = AS_NUMBER(pop());
+ double a = AS_NUMBER(pop());
+ push(NUMBER_VAL(a + b));
+ } else {
+ runtimeError("Operands must be two numbers or two strings.");
+ return INTERPRET_RUNTIME_ERROR;
+ }
break;
+ }
case OP_SUBTRACT:
BINARY_OP(NUMBER_VAL, -);
break;