aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Tom Willemse2022-08-14 20:14:43 -0700
committerGravatar Tom Willemse2022-08-14 20:14:43 -0700
commit726803c9d0c84bccc1d82d1c8aeadfc711752622 (patch)
tree2f90b75390ceb2a66133cbebce805086175fbeda
parent62858b60e43803477e898c7993e109a94701ce70 (diff)
downloadcrafting-interpreters-726803c9d0c84bccc1d82d1c8aeadfc711752622.tar.gz
crafting-interpreters-726803c9d0c84bccc1d82d1c8aeadfc711752622.zip
Chapter 29.1
-rw-r--r--clox/src/chunk.h1
-rw-r--r--clox/src/compiler.c20
-rw-r--r--clox/src/debug.c2
-rw-r--r--clox/src/vm.c11
4 files changed, 30 insertions, 4 deletions
diff --git a/clox/src/chunk.h b/clox/src/chunk.h
index 690fffd..4810f38 100644
--- a/clox/src/chunk.h
+++ b/clox/src/chunk.h
@@ -38,6 +38,7 @@ typedef enum {
OP_CLOSE_UPVALUE,
OP_RETURN,
OP_CLASS,
+ OP_INHERIT,
OP_METHOD,
} OpCode;
diff --git a/clox/src/compiler.c b/clox/src/compiler.c
index bfa0a96..f14666c 100644
--- a/clox/src/compiler.c
+++ b/clox/src/compiler.c
@@ -474,6 +474,10 @@ static void namedVariable(Token name, bool canAssign) {
}
}
+static void variable(bool canAssign) {
+ namedVariable(parser.previous, canAssign);
+}
+
static void classDeclaration() {
consume(TOKEN_IDENTIFIER, "Expect class name");
Token className = parser.previous;
@@ -487,6 +491,18 @@ static void classDeclaration() {
classCompiler.enclosing = currentClass;
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);
consume(TOKEN_LEFT_BRACE, "Expect '{' before class body.");
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)));
}
-static void variable(bool canAssign) {
- namedVariable(parser.previous, canAssign);
-}
-
static void this_(bool canAssign) {
if (currentClass == NULL) {
error("Can't use 'this' outside of a class.");
diff --git a/clox/src/debug.c b/clox/src/debug.c
index 079f0e9..4a39811 100644
--- a/clox/src/debug.c
+++ b/clox/src/debug.c
@@ -139,6 +139,8 @@ int disassembleInstruction(Chunk *chunk, int offset) {
return simpleInstruction("OP_RETURN", offset);
case OP_CLASS:
return constantInstruction("OP_CLASS", chunk, offset);
+ case OP_INHERIT:
+ return simpleInstruction("OP_INHERIT", offset);
case OP_METHOD:
return constantInstruction("OP_METHOD", chunk, offset);
default:
diff --git a/clox/src/vm.c b/clox/src/vm.c
index b5cb1cc..8a6847e 100644
--- a/clox/src/vm.c
+++ b/clox/src/vm.c
@@ -496,6 +496,17 @@ static InterpretResult run() {
case OP_CLASS:
push(OBJ_VAL(newClass(READ_STRING())));
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:
defineMethod(READ_STRING());
break;