Make 'self' not a keyword

It's still implicitly the first argument to a method and can not be
used in a method signature outside of the first argument, which is
ignored in the compiler. Actually, we allowed 'self' to be quietly
stuck in other slots but now we should correctly error on it.
This commit is contained in:
K. Lange 2021-03-30 12:28:16 +09:00
parent 84817c45cf
commit 1c5c2577e9
3 changed files with 12 additions and 18 deletions

View File

@ -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),

View File

@ -81,7 +81,6 @@ typedef enum {
TOKEN_ELIF,
TOKEN_PASS,
TOKEN_RETURN,
TOKEN_SELF,
TOKEN_SUPER,
TOKEN_TRUE,
TOKEN_WHILE,

View File

@ -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]) {