Chapter 19.4

This commit is contained in:
Tom Willemse 2021-09-07 22:54:12 -07:00
parent 60e752c0c5
commit d5f352e577
Signed by: ryuslash
GPG key ID: 7D5C407B435025C1
3 changed files with 42 additions and 2 deletions

View file

@ -25,7 +25,9 @@ struct ObjString {
char *chars; char *chars;
}; };
ObjString *takeString(char *chars, int length);
ObjString *copyString(const char *chars, int length); ObjString *copyString(const char *chars, int length);
void printObject(Value value);
static inline bool isObjType(Value value, ObjType type) { static inline bool isObjType(Value value, ObjType type) {
return IS_OBJ(value) && AS_OBJ(value)->type == type; return IS_OBJ(value) && AS_OBJ(value)->type == type;

View file

@ -1,6 +1,8 @@
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include "memory.h" #include "memory.h"
#include "object.h"
#include "value.h" #include "value.h"
void initValueArray(ValueArray *array) { void initValueArray(ValueArray *array) {
@ -37,6 +39,9 @@ void printValue(Value value) {
case VAL_NUMBER: case VAL_NUMBER:
printf("%g", AS_NUMBER(value)); printf("%g", AS_NUMBER(value));
break; break;
case VAL_OBJ:
printObject(value);
break;
} }
} }
@ -50,6 +55,12 @@ bool valuesEqual(Value a, Value b) {
return true; return true;
case VAL_NUMBER: case VAL_NUMBER:
return AS_NUMBER(a) == AS_NUMBER(b); 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: default:
return false; /* Unreachable */ return false; /* Unreachable */
} }

View file

@ -1,9 +1,12 @@
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include "common.h" #include "common.h"
#include "compiler.h" #include "compiler.h"
#include "debug.h" #include "debug.h"
#include "memory.h"
#include "object.h"
#include "vm.h" #include "vm.h"
VM vm; VM vm;
@ -43,6 +46,20 @@ static bool isFalsey(Value value) {
return IS_NIL(value) || (IS_BOOL(value) && !AS_BOOL(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() { static InterpretResult run() {
#define READ_BYTE() (*vm.ip++) #define READ_BYTE() (*vm.ip++)
#define READ_CONSTANT() (vm.chunk->constants.values[READ_BYTE()]) #define READ_CONSTANT() (vm.chunk->constants.values[READ_BYTE()])
@ -96,9 +113,19 @@ static InterpretResult run() {
case OP_LESS: case OP_LESS:
BINARY_OP(BOOL_VAL, <); BINARY_OP(BOOL_VAL, <);
break; break;
case OP_ADD: case OP_ADD: {
BINARY_OP(NUMBER_VAL, +); 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; break;
}
case OP_SUBTRACT: case OP_SUBTRACT:
BINARY_OP(NUMBER_VAL, -); BINARY_OP(NUMBER_VAL, -);
break; break;