diff options
Diffstat (limited to 'clox/src/compiler.c')
-rw-r--r-- | clox/src/compiler.c | 25 |
1 files changed, 24 insertions, 1 deletions
diff --git a/clox/src/compiler.c b/clox/src/compiler.c index 599ad1b..fd435d5 100644 --- a/clox/src/compiler.c +++ b/clox/src/compiler.c @@ -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}, |