aboutsummaryrefslogtreecommitdiffstats
path: root/clox/src/compiler.c
diff options
context:
space:
mode:
Diffstat (limited to 'clox/src/compiler.c')
-rw-r--r--clox/src/compiler.c25
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},