Chapter 29.3
This commit is contained in:
parent
1bba129074
commit
69a9a95483
4 changed files with 49 additions and 1 deletions
|
@ -19,6 +19,7 @@ typedef enum {
|
|||
OP_SET_UPVALUE,
|
||||
OP_GET_PROPERTY,
|
||||
OP_SET_PROPERTY,
|
||||
OP_GET_SUPER,
|
||||
OP_EQUAL,
|
||||
OP_GREATER,
|
||||
OP_LESS,
|
||||
|
@ -34,6 +35,7 @@ typedef enum {
|
|||
OP_LOOP,
|
||||
OP_CALL,
|
||||
OP_INVOKE,
|
||||
OP_SUPER_INVOKE,
|
||||
OP_CLOSURE,
|
||||
OP_CLOSE_UPVALUE,
|
||||
OP_RETURN,
|
||||
|
|
|
@ -486,6 +486,29 @@ static Token syntheticToken(const char *text) {
|
|||
return token;
|
||||
}
|
||||
|
||||
static void super_(bool canAssign) {
|
||||
if (currentClass == NULL) {
|
||||
error("Can't use 'super' outside of a class.");
|
||||
} else if (!currentClass->hasSuperclass) {
|
||||
error("Can't use 'super' in a class with no superclass.");
|
||||
}
|
||||
|
||||
consume(TOKEN_DOT, "Expect '.' after 'super'.");
|
||||
consume(TOKEN_IDENTIFIER, "Expect superclass method name.");
|
||||
uint8_t name = identifierConstant(&parser.previous);
|
||||
|
||||
namedVariable(syntheticToken("this"), false);
|
||||
if (match(TOKEN_LEFT_PAREN)) {
|
||||
uint8_t argCount = argumentList();
|
||||
namedVariable(syntheticToken("super"), false);
|
||||
emitBytes(OP_SUPER_INVOKE, name);
|
||||
emitByte(argCount);
|
||||
} else {
|
||||
namedVariable(syntheticToken("super"), false);
|
||||
emitBytes(OP_GET_SUPER, name);
|
||||
}
|
||||
}
|
||||
|
||||
static void classDeclaration() {
|
||||
consume(TOKEN_IDENTIFIER, "Expect class name");
|
||||
Token className = parser.previous;
|
||||
|
@ -823,7 +846,7 @@ ParseRule rules[] = {
|
|||
[TOKEN_OR] = {NULL, or_, PREC_OR},
|
||||
[TOKEN_PRINT] = {NULL, NULL, PREC_NONE},
|
||||
[TOKEN_RETURN] = {NULL, NULL, PREC_NONE},
|
||||
[TOKEN_SUPER] = {NULL, NULL, PREC_NONE},
|
||||
[TOKEN_SUPER] = {super_, NULL, PREC_NONE},
|
||||
[TOKEN_THIS] = {this_, NULL, PREC_NONE},
|
||||
[TOKEN_TRUE] = {literal, NULL, PREC_NONE},
|
||||
[TOKEN_VAR] = {NULL, NULL, PREC_NONE},
|
||||
|
|
|
@ -86,6 +86,8 @@ int disassembleInstruction(Chunk *chunk, int offset) {
|
|||
return constantInstruction("OP_GET_PROPERTY", chunk, offset);
|
||||
case OP_SET_PROPERTY:
|
||||
return constantInstruction("OP_SET_PROPERTY", chunk, offset);
|
||||
case OP_GET_SUPER:
|
||||
return constantInstruction("OP_GET_SUPER", chunk, offset);
|
||||
case OP_EQUAL:
|
||||
return simpleInstruction("OP_EQUAL", offset);
|
||||
case OP_GREATER:
|
||||
|
@ -116,6 +118,8 @@ int disassembleInstruction(Chunk *chunk, int offset) {
|
|||
return byteInstruction("OP_CALL", chunk, offset);
|
||||
case OP_INVOKE:
|
||||
return invokeInstruction("OP_INVOKE", chunk, offset);
|
||||
case OP_SUPER_INVOKE:
|
||||
return invokeInstruction("OP_SUPER_INVOKE", chunk, offset);
|
||||
case OP_CLOSURE: {
|
||||
offset++;
|
||||
uint8_t constant = chunk->code[offset++];
|
||||
|
|
|
@ -379,6 +379,15 @@ static InterpretResult run() {
|
|||
push(value);
|
||||
break;
|
||||
}
|
||||
case OP_GET_SUPER: {
|
||||
ObjString *name = READ_STRING();
|
||||
ObjClass *superclass = AS_CLASS(pop());
|
||||
|
||||
if (!bindMethod(superclass, name)) {
|
||||
return INTERPRET_RUNTIME_ERROR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OP_EQUAL: {
|
||||
Value b = pop();
|
||||
Value a = pop();
|
||||
|
@ -460,6 +469,16 @@ static InterpretResult run() {
|
|||
frame = &vm.frames[vm.frameCount - 1];
|
||||
break;
|
||||
}
|
||||
case OP_SUPER_INVOKE: {
|
||||
ObjString *method = READ_STRING();
|
||||
int argCount = READ_BYTE();
|
||||
ObjClass *superclass = AS_CLASS(pop());
|
||||
if (!invokeFromClass(superclass, method, argCount)) {
|
||||
return INTERPRET_RUNTIME_ERROR;
|
||||
}
|
||||
frame = &vm.frames[vm.frameCount - 1];
|
||||
break;
|
||||
}
|
||||
case OP_CLOSURE: {
|
||||
ObjFunction *function = AS_FUNCTION(READ_CONSTANT());
|
||||
ObjClosure *closure = newClosure(function);
|
||||
|
|
Loading…
Reference in a new issue