From 726803c9d0c84bccc1d82d1c8aeadfc711752622 Mon Sep 17 00:00:00 2001 From: Tom Willemse Date: Sun, 14 Aug 2022 20:14:43 -0700 Subject: [PATCH] Chapter 29.1 --- clox/src/chunk.h | 1 + clox/src/compiler.c | 20 ++++++++++++++++---- clox/src/debug.c | 2 ++ clox/src/vm.c | 11 +++++++++++ 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;