Chapter 19.4
This commit is contained in:
parent
60e752c0c5
commit
d5f352e577
3 changed files with 42 additions and 2 deletions
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue