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_SET_UPVALUE,
|
||||||
OP_GET_PROPERTY,
|
OP_GET_PROPERTY,
|
||||||
OP_SET_PROPERTY,
|
OP_SET_PROPERTY,
|
||||||
|
OP_GET_SUPER,
|
||||||
OP_EQUAL,
|
OP_EQUAL,
|
||||||
OP_GREATER,
|
OP_GREATER,
|
||||||
OP_LESS,
|
OP_LESS,
|
||||||
|
@ -34,6 +35,7 @@ typedef enum {
|
||||||
OP_LOOP,
|
OP_LOOP,
|
||||||
OP_CALL,
|
OP_CALL,
|
||||||
OP_INVOKE,
|
OP_INVOKE,
|
||||||
|
OP_SUPER_INVOKE,
|
||||||
OP_CLOSURE,
|
OP_CLOSURE,
|
||||||
OP_CLOSE_UPVALUE,
|
OP_CLOSE_UPVALUE,
|
||||||
OP_RETURN,
|
OP_RETURN,
|
||||||
|
|
|
@ -486,6 +486,29 @@ static Token syntheticToken(const char *text) {
|
||||||
return token;
|
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() {
|
static void classDeclaration() {
|
||||||
consume(TOKEN_IDENTIFIER, "Expect class name");
|
consume(TOKEN_IDENTIFIER, "Expect class name");
|
||||||
Token className = parser.previous;
|
Token className = parser.previous;
|
||||||
|
@ -823,7 +846,7 @@ ParseRule rules[] = {
|
||||||
[TOKEN_OR] = {NULL, or_, PREC_OR},
|
[TOKEN_OR] = {NULL, or_, PREC_OR},
|
||||||
[TOKEN_PRINT] = {NULL, NULL, PREC_NONE},
|
[TOKEN_PRINT] = {NULL, NULL, PREC_NONE},
|
||||||
[TOKEN_RETURN] = {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_THIS] = {this_, NULL, PREC_NONE},
|
||||||
[TOKEN_TRUE] = {literal, NULL, PREC_NONE},
|
[TOKEN_TRUE] = {literal, NULL, PREC_NONE},
|
||||||
[TOKEN_VAR] = {NULL, 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);
|
return constantInstruction("OP_GET_PROPERTY", chunk, offset);
|
||||||
case OP_SET_PROPERTY:
|
case OP_SET_PROPERTY:
|
||||||
return constantInstruction("OP_SET_PROPERTY", chunk, offset);
|
return constantInstruction("OP_SET_PROPERTY", chunk, offset);
|
||||||
|
case OP_GET_SUPER:
|
||||||
|
return constantInstruction("OP_GET_SUPER", chunk, offset);
|
||||||
case OP_EQUAL:
|
case OP_EQUAL:
|
||||||
return simpleInstruction("OP_EQUAL", offset);
|
return simpleInstruction("OP_EQUAL", offset);
|
||||||
case OP_GREATER:
|
case OP_GREATER:
|
||||||
|
@ -116,6 +118,8 @@ int disassembleInstruction(Chunk *chunk, int offset) {
|
||||||
return byteInstruction("OP_CALL", chunk, offset);
|
return byteInstruction("OP_CALL", chunk, offset);
|
||||||
case OP_INVOKE:
|
case OP_INVOKE:
|
||||||
return invokeInstruction("OP_INVOKE", chunk, offset);
|
return invokeInstruction("OP_INVOKE", chunk, offset);
|
||||||
|
case OP_SUPER_INVOKE:
|
||||||
|
return invokeInstruction("OP_SUPER_INVOKE", chunk, offset);
|
||||||
case OP_CLOSURE: {
|
case OP_CLOSURE: {
|
||||||
offset++;
|
offset++;
|
||||||
uint8_t constant = chunk->code[offset++];
|
uint8_t constant = chunk->code[offset++];
|
||||||
|
|
|
@ -379,6 +379,15 @@ static InterpretResult run() {
|
||||||
push(value);
|
push(value);
|
||||||
break;
|
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: {
|
case OP_EQUAL: {
|
||||||
Value b = pop();
|
Value b = pop();
|
||||||
Value a = pop();
|
Value a = pop();
|
||||||
|
@ -460,6 +469,16 @@ static InterpretResult run() {
|
||||||
frame = &vm.frames[vm.frameCount - 1];
|
frame = &vm.frames[vm.frameCount - 1];
|
||||||
break;
|
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: {
|
case OP_CLOSURE: {
|
||||||
ObjFunction *function = AS_FUNCTION(READ_CONSTANT());
|
ObjFunction *function = AS_FUNCTION(READ_CONSTANT());
|
||||||
ObjClosure *closure = newClosure(function);
|
ObjClosure *closure = newClosure(function);
|
||||||
|
|
Loading…
Reference in a new issue