aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Tom Willemse2021-09-07 22:54:12 -0700
committerGravatar Tom Willemse2021-09-07 22:54:12 -0700
commitd5f352e577acf1f472150df5578ff6d693258ae3 (patch)
treec36477b94d2c3a88b919edd789acff935eaf9a92
parent60e752c0c5ae3798105919a43ee194e1e897d429 (diff)
downloadcrafting-interpreters-d5f352e577acf1f472150df5578ff6d693258ae3.tar.gz
crafting-interpreters-d5f352e577acf1f472150df5578ff6d693258ae3.zip
Chapter 19.4
-rw-r--r--clox/src/object.h2
-rw-r--r--clox/src/value.c11
-rw-r--r--clox/src/vm.c31
3 files changed, 42 insertions, 2 deletions
diff --git a/clox/src/object.h b/clox/src/object.h
index 2a87a51..a26077f 100644
--- a/clox/src/object.h
+++ b/clox/src/object.h
@@ -25,7 +25,9 @@ struct ObjString {
char *chars;
};
+ObjString *takeString(char *chars, int length);
ObjString *copyString(const char *chars, int length);
+void printObject(Value value);
static inline bool isObjType(Value value, ObjType type) {
return IS_OBJ(value) && AS_OBJ(value)->type == type;
diff --git a/clox/src/value.c b/clox/src/value.c
index 34e55b8..a5f8540 100644
--- a/clox/src/value.c
+++ b/clox/src/value.c
@@ -1,6 +1,8 @@
#include <stdio.h>
+#include <string.h>
#include "memory.h"
+#include "object.h"
#include "value.h"
void initValueArray(ValueArray *array) {
@@ -37,6 +39,9 @@ void printValue(Value value) {
case VAL_NUMBER:
printf("%g", AS_NUMBER(value));
break;
+ case VAL_OBJ:
+ printObject(value);
+ break;
}
}
@@ -50,6 +55,12 @@ bool valuesEqual(Value a, Value b) {
return true;
case VAL_NUMBER:
return AS_NUMBER(a) == AS_NUMBER(b);
+ case VAL_OBJ: {
+ ObjString *aString = AS_STRING(a);
+ ObjString *bString = AS_STRING(b);
+ return aString->length == bString->length &&
+ memcmp(aString->chars, bString->chars, aString->length) == 0;
+ }
default:
return false; /* Unreachable */
}
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;