aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clox/src/chunk.h2
-rw-r--r--clox/src/compiler.c14
-rw-r--r--clox/src/debug.c4
-rw-r--r--clox/src/vm.c32
4 files changed, 51 insertions, 1 deletions
diff --git a/clox/src/chunk.h b/clox/src/chunk.h
index ae0ab72..9fff535 100644
--- a/clox/src/chunk.h
+++ b/clox/src/chunk.h
@@ -17,6 +17,8 @@ typedef enum {
OP_SET_GLOBAL,
OP_GET_UPVALUE,
OP_SET_UPVALUE,
+ OP_GET_PROPERTY,
+ OP_SET_PROPERTY,
OP_EQUAL,
OP_GREATER,
OP_LESS,
diff --git a/clox/src/compiler.c b/clox/src/compiler.c
index b21a53d..6ab4855 100644
--- a/clox/src/compiler.c
+++ b/clox/src/compiler.c
@@ -307,6 +307,18 @@ static void call(bool canAssign) {
emitBytes(OP_CALL, argCount);
}
+static void dot(bool canAssign) {
+ consume(TOKEN_IDENTIFIER, "Expect property name after '.'.");
+ uint8_t name = identifierConstant(&parser.previous);
+
+ if (canAssign && match(TOKEN_EQUAL)) {
+ expression();
+ emitBytes(OP_SET_PROPERTY, name);
+ } else {
+ emitBytes(OP_GET_PROPERTY, name);
+ }
+}
+
static void literal(bool canAssign) {
switch (parser.previous.type) {
case TOKEN_FALSE:
@@ -689,7 +701,7 @@ ParseRule rules[] = {
[TOKEN_LEFT_BRACE] = {NULL, NULL, PREC_NONE},
[TOKEN_RIGHT_BRACE] = {NULL, NULL, PREC_NONE},
[TOKEN_COMMA] = {NULL, NULL, PREC_NONE},
- [TOKEN_DOT] = {NULL, NULL, PREC_NONE},
+ [TOKEN_DOT] = {NULL, dot, PREC_CALL},
[TOKEN_MINUS] = {unary, binary, PREC_TERM},
[TOKEN_PLUS] = {NULL, binary, PREC_TERM},
[TOKEN_SEMICOLON] = {NULL, NULL, PREC_NONE},
diff --git a/clox/src/debug.c b/clox/src/debug.c
index a2c2c53..fe96c3d 100644
--- a/clox/src/debug.c
+++ b/clox/src/debug.c
@@ -73,6 +73,10 @@ int disassembleInstruction(Chunk *chunk, int offset) {
return byteInstruction("OP_GET_UPVALUE", chunk, offset);
case OP_SET_UPVALUE:
return byteInstruction("OP_SET_UPVALUE", chunk, offset);
+ case OP_GET_PROPERTY:
+ return constantInstruction("OP_GET_PROPERTY", chunk, offset);
+ case OP_SET_PROPERTY:
+ return constantInstruction("OP_SET_PROPERTY", chunk, offset);
case OP_EQUAL:
return simpleInstruction("OP_EQUAL", offset);
case OP_GREATER:
diff --git a/clox/src/vm.c b/clox/src/vm.c
index c1f0b90..1d82dd1 100644
--- a/clox/src/vm.c
+++ b/clox/src/vm.c
@@ -282,6 +282,38 @@ static InterpretResult run() {
*frame->closure->upvalues[slot]->location = peek(0);
break;
}
+ case OP_GET_PROPERTY: {
+ if (!IS_INSTANCE(peek(0))) {
+ runtimeError("Only instances have properties.");
+ return INTERPRET_RUNTIME_ERROR;
+ }
+
+ ObjInstance *instance = AS_INSTANCE(peek(0));
+ ObjString *name = READ_STRING();
+
+ Value value;
+ if (tableGet(&instance->fields, name, &value)) {
+ pop(); /* Instance */
+ push(value);
+ break;
+ }
+
+ runtimeError("Undefined property '%s'.", name->chars);
+ return INTERPRET_RUNTIME_ERROR;
+ }
+ case OP_SET_PROPERTY: {
+ if (!IS_INSTANCE(peek(1))) {
+ runtimeError("Only instances have fields.");
+ return INTERPRET_RUNTIME_ERROR;
+ }
+
+ ObjInstance *instance = AS_INSTANCE(peek(1));
+ tableSet(&instance->fields, READ_STRING(), peek(0));
+ Value value = pop();
+ pop();
+ push(value);
+ break;
+ }
case OP_EQUAL: {
Value b = pop();
Value a = pop();