Skip to content

Commit

Permalink
Improved reporting of type errors in calls
Browse files Browse the repository at this point in the history
  • Loading branch information
PaulKlint committed Mar 20, 2024
1 parent d06ba9c commit d421576
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -646,16 +646,35 @@ void collect(current: (Expression) `<Expression expression> ( <{Expression ","}*
void reportCallError(Expression current, Expression callee, list[Expression] actuals, (KeywordArguments[Expression]) `<KeywordArguments[Expression] keywordArguments>`, Solver s){
kwactuals = keywordArguments is \default ? [ kwa.expression | kwa <- keywordArguments.keywordArgumentList] : [];
arguments = size(actuals) > 1 ? "arguments of types" : "argument of type";
kwarguments = size(kwactuals) > 1 ? "keyword arguments" : "keyword argument";
calleeType = s.getType(callee);
argumentsTypes = [s.getType(a)| a <- actuals];
argumentsTypesText = intercalate(", ", ["`<prettyAType(at)>`" | at <- argumentsTypes]);
argumentsText = "arguments of type<size(actuals) > 0 ? "s" : "">";
kwargumentsText = "keyword argument<size(kwactuals) > 1 ? "s" : "">";
if(isEmpty(kwactuals)){
s.report(error(current, "%q is defined as %t and cannot be applied to %v %v", "<callee>", callee, arguments, actuals));
someArityOk
= overloadedAType(rel[loc l, IdRole idRole, AType ftype] overloads) := calleeType
&& any(ovl <- overloads, size(argumentsTypes) == size(getFunctionArgumentTypes(ovl.ftype)));
wrongArity = someArityOk ? "" : " with <size(argumentsTypes)> ";
if(someArityOk){
s.report(error(current, "Cannot call %q with %v %v, given definitions %t", "<callee>", argumentsText, argumentsTypesText, callee));
} else {
s.report(error(current, "Cannot call %q with %v argument(s), given definitions %t", "<callee>", size(argumentsTypes), callee));
}
} else {
kwargs = keywordArguments is \default ? [ kwa | kwa <- keywordArguments.keywordArgumentList] : [];
kws = [ "`<kwa.name>` of type `<prettyAType(s.getType(kwa.expression))>`" | kwa <- kwargs ];
s.report(error(current, "%q is defined as %t and cannot be applied to %v `%v` and %v %v",
"<callee>", callee, arguments, actuals, kwarguments,
kws));
someOverloadsPositionalOk
= overloadedAType(rel[loc l, IdRole idRole, AType ftype] overloads) := calleeType
&& any(ovl <- overloads, asubtypeList(argumentsTypes, getFunctionArgumentTypes(ovl.ftype)));
if(someOverloadsPositionalOk){
s.report(error(current, "Cannot call %q with %v %v, given definitions %t",
"<callee>", kwargumentsText, kws, callee));
} else {
s.report(error(current, "Cannot call %q with %v %v and %v %v, given definitions %t",
"<callee>", argumentsText, argumentsTypesText, kwargumentsText, kws, callee));
}
}
}
Expand Down Expand Up @@ -725,8 +744,6 @@ private tuple[rel[loc, IdRole, AType], list[bool]] filterOverloads(rel[loc, IdRo
return <filteredOverloads, identicalFormals>;
}
// TODO: in order to reuse the function below `keywordArguments` is passed as where `keywordArguments[&T] keywordArguments` would make more sense.
// The interpreter does not handle this well, so revisit this later
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@ AType computeADTReturnType(Tree current, str adtName, loc scope, list[AType] for
void checkExpressionKwArgs(list[Keyword] kwFormals, (KeywordArguments[Expression]) `<KeywordArguments[Expression] keywordArgumentsExp>`, Bindings bindings, Solver s){
if(keywordArgumentsExp is none) return;

msgs = [];
next_arg:
for(kwa <- keywordArgumentsExp.keywordArgumentList){
kwName = prettyPrintName(kwa.name);
Expand Down Expand Up @@ -327,12 +328,15 @@ void checkExpressionKwArgs(list[Keyword] kwFormals, (KeywordArguments[Expression
availableKws = "; available keyword parameters: <availableKws>";
}

s.report(error(kwa, "Undefined keyword argument %q%v", kwName, availableKws));
msgs += error(kwa, "Undefined keyword argument %q%v", kwName, availableKws);
}
s.reports(msgs);
}

void checkPatternKwArgs(list[Keyword] kwFormals, (KeywordArguments[Pattern]) `<KeywordArguments[Pattern] keywordArgumentsPat>`, Bindings bindings, loc scope, Solver s){
if(keywordArgumentsPat is none) return;

msgs = [];
next_arg:
for(kwa <- keywordArgumentsPat.keywordArgumentList){
kwName = prettyPrintName(kwa.name);
Expand Down Expand Up @@ -360,8 +364,9 @@ void checkPatternKwArgs(list[Keyword] kwFormals, (KeywordArguments[Pattern]) `<K
availableKws = "; available keyword parameters: <availableKws>";
}

s.report(error(kwa, "Undefined keyword argument %q%v", kwName, availableKws));
msgs += error(kwa, "Undefined keyword argument %q%v", kwName, availableKws);
}
s.reports(msgs);
}

list[Keyword] computeKwFormals(list[KeywordFormal] kwFormals, Solver s){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ void checkOverloading(map[str,Tree] namedTrees, Solver s){
if(t1_kwNames != t2_kwNames){
diffkws = t2_kwNames - t1_kwNames;
plural = size(diffkws) > 1 ? "s" : "";
msgs = [ error("Declaration clashes with other declaration of function `<id>` with different keyword parameter<plural> <intercalate(",", [ "`<k>`" | k <- diffkws])> at <d2.defined>", d1.defined) ];
msgs = [ error("Other declaration of function `<id>` has different keyword parameter<plural> <intercalate(",", [ "`<k>`" | k <- diffkws])> at <d2.defined>", d1.defined) ];
s.addMessages(msgs);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
module lang::rascalcore::compile::Examples::Tst5


int f(int a, int b, int c=1, int d=2) = a+b+c+d;

str f(str a, int b, int x = 1, int y = 2) = "<a><b + x + y>";

str f(str a, str b, int x = 1, int y = 2) = "<a><b><x+y>";

value main(){
return f("a",2,x="a");
}



//MH
//public void showUsageCounts(Corpus corpus, lrel[str p, str v, QueryResult qr] res) {
// mr = ( p : size([ e | <p,_,e> <- res ]) | p <- corpus );
Expand All @@ -25,14 +38,4 @@ module lang::rascalcore::compile::Examples::Tst5
// && x == "x" && y == "y";
//}

import util::Memo;

@memo=expireAfter(minutes=10)
void foo() { }

//value main(){
// if([1, int x] !:= [1]) return x;
// return -1;
//}


0 comments on commit d421576

Please sign in to comment.