Chapter 27.4
This commit is contained in:
parent
f4185577e5
commit
4e77cfa612
4 changed files with 51 additions and 1 deletions
|
@ -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,
|
||||
|
|
|
@ -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},
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue