Chapter 29.1
This commit is contained in:
parent
62858b60e4
commit
726803c9d0
4 changed files with 30 additions and 4 deletions
|
@ -38,6 +38,7 @@ typedef enum {
|
||||||
OP_CLOSE_UPVALUE,
|
OP_CLOSE_UPVALUE,
|
||||||
OP_RETURN,
|
OP_RETURN,
|
||||||
OP_CLASS,
|
OP_CLASS,
|
||||||
|
OP_INHERIT,
|
||||||
OP_METHOD,
|
OP_METHOD,
|
||||||
} OpCode;
|
} OpCode;
|
||||||
|
|
||||||
|
|
|
@ -474,6 +474,10 @@ static void namedVariable(Token name, bool canAssign) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void variable(bool canAssign) {
|
||||||
|
namedVariable(parser.previous, canAssign);
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
@ -487,6 +491,18 @@ static void classDeclaration() {
|
||||||
classCompiler.enclosing = currentClass;
|
classCompiler.enclosing = currentClass;
|
||||||
currentClass = &classCompiler;
|
currentClass = &classCompiler;
|
||||||
|
|
||||||
|
if (match(TOKEN_LESS)) {
|
||||||
|
consume(TOKEN_IDENTIFIER, "Expect superclass name.");
|
||||||
|
variable(false);
|
||||||
|
|
||||||
|
if (identifiersEqual(&className, &parser.previous)) {
|
||||||
|
error("A class can't inherit from itself.");
|
||||||
|
}
|
||||||
|
|
||||||
|
namedVariable(className, false);
|
||||||
|
emitByte(OP_INHERIT);
|
||||||
|
}
|
||||||
|
|
||||||
namedVariable(className, false);
|
namedVariable(className, false);
|
||||||
consume(TOKEN_LEFT_BRACE, "Expect '{' before class body.");
|
consume(TOKEN_LEFT_BRACE, "Expect '{' before class body.");
|
||||||
while (!check(TOKEN_RIGHT_BRACE) && !check(TOKEN_EOF)) {
|
while (!check(TOKEN_RIGHT_BRACE) && !check(TOKEN_EOF)) {
|
||||||
|
@ -722,10 +738,6 @@ static void string(bool canAssign) {
|
||||||
copyString(parser.previous.start + 1, parser.previous.length - 2)));
|
copyString(parser.previous.start + 1, parser.previous.length - 2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void variable(bool canAssign) {
|
|
||||||
namedVariable(parser.previous, canAssign);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void this_(bool canAssign) {
|
static void this_(bool canAssign) {
|
||||||
if (currentClass == NULL) {
|
if (currentClass == NULL) {
|
||||||
error("Can't use 'this' outside of a class.");
|
error("Can't use 'this' outside of a class.");
|
||||||
|
|
|
@ -139,6 +139,8 @@ int disassembleInstruction(Chunk *chunk, int offset) {
|
||||||
return simpleInstruction("OP_RETURN", offset);
|
return simpleInstruction("OP_RETURN", offset);
|
||||||
case OP_CLASS:
|
case OP_CLASS:
|
||||||
return constantInstruction("OP_CLASS", chunk, offset);
|
return constantInstruction("OP_CLASS", chunk, offset);
|
||||||
|
case OP_INHERIT:
|
||||||
|
return simpleInstruction("OP_INHERIT", offset);
|
||||||
case OP_METHOD:
|
case OP_METHOD:
|
||||||
return constantInstruction("OP_METHOD", chunk, offset);
|
return constantInstruction("OP_METHOD", chunk, offset);
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -496,6 +496,17 @@ static InterpretResult run() {
|
||||||
case OP_CLASS:
|
case OP_CLASS:
|
||||||
push(OBJ_VAL(newClass(READ_STRING())));
|
push(OBJ_VAL(newClass(READ_STRING())));
|
||||||
break;
|
break;
|
||||||
|
case OP_INHERIT: {
|
||||||
|
Value superclass = peek(1);
|
||||||
|
if (!IS_CLASS(superclass)) {
|
||||||
|
runtimeError("Superclass must be a class.");
|
||||||
|
return INTERPRET_RUNTIME_ERROR;
|
||||||
|
}
|
||||||
|
ObjClass *subclass = AS_CLASS(peek(0));
|
||||||
|
tableAddAll(&AS_CLASS(superclass)->methods, &subclass->methods);
|
||||||
|
pop(); /* Subclass. */
|
||||||
|
break;
|
||||||
|
}
|
||||||
case OP_METHOD:
|
case OP_METHOD:
|
||||||
defineMethod(READ_STRING());
|
defineMethod(READ_STRING());
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in a new issue