diff --git a/src/compiler.c b/src/compiler.c index 524247e..719d926 100644 --- a/src/compiler.c +++ b/src/compiler.c @@ -1044,20 +1044,27 @@ static void function(FunctionType type, size_t blockWidth) { if (isMethod(type)) current->codeobject->requiredArgs = 1; int hasCollectors = 0; + KrkToken self = syntheticToken("self"); consume(TOKEN_LEFT_PAREN, "Expected start of parameter list after function name."); startEatingWhitespace(); if (!check(TOKEN_RIGHT_PAREN)) { do { - if (match(TOKEN_SELF)) { - if (!isMethod(type)) { - error("Invalid use of `self` as a function paramenter."); + if (isMethod(type) && check(TOKEN_IDENTIFIER) && + identifiersEqual(&parser.current, &self)) { + if (hasCollectors || current->codeobject->requiredArgs != 1) { + errorAtCurrent("Argument name `self` in a method signature is reserved for the implicit first argument."); + break; } + advance(); if (check(TOKEN_COLON)) { KrkToken name = parser.previous; match(TOKEN_COLON); typeHint(name); } + if (check(TOKEN_EQUAL)) { + errorAtCurrent("`self` can not be a keyword argument."); + } continue; } if (match(TOKEN_ASTERISK) || check(TOKEN_POW)) { @@ -2358,14 +2365,6 @@ static void variable(int canAssign) { namedVariable(parser.previous, canAssign); } -static void self(int canAssign) { - if (currentClass == NULL) { - error("Invalid reference to `self` outside of a class method."); - return; - } - variable(0); -} - static void super_(int canAssign) { if (currentClass == NULL) { error("Invalid reference to `super` outside of a class."); @@ -2375,7 +2374,7 @@ static void super_(int canAssign) { consume(TOKEN_DOT, "Expected a field of `super()` to be referenced."); consume(TOKEN_IDENTIFIER, "Expected a field name."); size_t ind = identifierConstant(&parser.previous); - namedVariable(syntheticToken("self"), 0); + EMIT_CONSTANT_OP(OP_GET_LOCAL, 0); namedVariable(syntheticToken("super"), 0); EMIT_CONSTANT_OP(OP_GET_SUPER, ind); } @@ -2726,7 +2725,6 @@ ParseRule krk_parseRules[] = { RULE(TOKEN_NONE, literal, NULL, PREC_NONE), RULE(TOKEN_OR, NULL, or_, PREC_OR), RULE(TOKEN_RETURN, NULL, NULL, PREC_NONE), - RULE(TOKEN_SELF, self, NULL, PREC_NONE), RULE(TOKEN_SUPER, super_, NULL, PREC_NONE), RULE(TOKEN_TRUE, literal, NULL, PREC_NONE), RULE(TOKEN_WHILE, NULL, NULL, PREC_NONE), diff --git a/src/kuroko/scanner.h b/src/kuroko/scanner.h index d15bfe2..7832eed 100644 --- a/src/kuroko/scanner.h +++ b/src/kuroko/scanner.h @@ -81,7 +81,6 @@ typedef enum { TOKEN_ELIF, TOKEN_PASS, TOKEN_RETURN, - TOKEN_SELF, TOKEN_SUPER, TOKEN_TRUE, TOKEN_WHILE, diff --git a/src/scanner.c b/src/scanner.c index 08a0484..fb906f9 100644 --- a/src/scanner.c +++ b/src/scanner.c @@ -248,10 +248,7 @@ static KrkTokenType identifierType() { case 'e': return checkKeyword(2, "turn", TOKEN_RETURN); case 'a': return checkKeyword(2, "ise", TOKEN_RAISE); } break; - case 's': if (MORE(1)) switch(scanner.start[1]) { - case 'e': return checkKeyword(2, "lf", TOKEN_SELF); - case 'u': return checkKeyword(2, "per", TOKEN_SUPER); - } break; + case 's': return checkKeyword(1, "uper", TOKEN_SUPER); case 't': return checkKeyword(1, "ry", TOKEN_TRY); case 'T': return checkKeyword(1, "rue", TOKEN_TRUE); case 'w': if (MORE(1)) switch(scanner.start[1]) {