Skip to content

Commit

Permalink
Added ignore reporting. Better analysis parameterized function decls
Browse files Browse the repository at this point in the history
- Every ignored declaration was printed; this has now become an info
messages

- The analysis of functions with a parametrized return type has been
improved: for each return expression the type parameters in the types of
all its subexpressions are collected and this set of type parameters
should cover all type parameters in the return type.
  • Loading branch information
PaulKlint committed Mar 16, 2024
1 parent 4111742 commit aeffdab
Show file tree
Hide file tree
Showing 9 changed files with 87 additions and 88 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -875,7 +875,7 @@ AType getTupleFieldType(AType t, str fn) {
@doc{Get the type of the tuple field at the given offset.}
AType getTupleFieldType(AType t, int fn) {
if (atuple(atypeList(tas)) := t) {
if (0 <= fn && fn < size(tas)) return unwrapAType(tas[fn]);
if (0 <= fn && fn < size(tas)) return tas[fn]; // unwrapAType(tas[fn]);
throw rascalCheckerInternalError("Tuple <prettyAType(t)> does not have field <fn>");
}
throw rascalCheckerInternalError("getTupleFieldType given unexpected type <prettyAType(t)>");
Expand Down Expand Up @@ -1004,10 +1004,10 @@ list[str] getMapFieldNames(AType t) {
str getMapFieldName(AType t, int idx) = getMapFieldNames(t)[idx];

@doc{Get the domain type of the map.}
AType getMapDomainType(AType t) = unwrapAType(getMapFields(t)[0]);
AType getMapDomainType(AType t) = getMapFields(t)[0]; //unwrapAType(getMapFields(t)[0]);

@doc{Get the range type of the map.}
AType getMapRangeType(AType t) = unwrapAType(getMapFields(t)[1]);
AType getMapRangeType(AType t) = getMapFields(t)[1]; //unwrapAType(getMapFields(t)[1]);

// ---- bag

Expand Down Expand Up @@ -1115,7 +1115,7 @@ list[AType] getFunctionArgumentTypes(AType ft) {

set[AType] getFunctionTypeParameters(AType ft){
if (af: afunc(_, _, _) := unwrapAType(ft)){
return {p | /p:aparameter(_,_) := af };
return {unsetRec(p, "alabel") | /p:aparameter(_,_) := af };
}
throw rascalCheckerInternalError("Cannot get Type parameters from non-function type, got <prettyAType(ft)>");
}
Expand Down Expand Up @@ -1173,7 +1173,7 @@ AType getFunctionArgumentTypesAsTuple(AType ft) {
AType getFunctionReturnType(AType ft) {
if (afunc(rt, _, _) := unwrapAType(ft)) return rt;
if(overloadedAType(rel[loc, IdRole, AType] _) := unwrapAType(ft)) {
return getResult( unwrapAType(ft));
return getResult(ft); //getResult( unwrapAType(ft));
}
throw rascalCheckerInternalError("Cannot get function return type from non-function type, got <prettyAType(ft)>");
}
Expand Down
29 changes: 15 additions & 14 deletions src/org/rascalmpl/core/library/lang/rascalcore/check/Checker.rsc
Original file line number Diff line number Diff line change
Expand Up @@ -224,13 +224,8 @@ ModuleStatus rascalTModelForLocs(
topModuleNames = {};

for(mloc <- mlocs){
//try {
m = getModuleName(mloc, pcfg);
topModuleNames += {m};
//} catch str e: {
// ms.messages += [ error("Cannot get module name for <mloc>, reason: <e>", mloc) ];
// return ms;
//}
}

try {
Expand Down Expand Up @@ -279,9 +274,6 @@ ModuleStatus rascalTModelForLocs(
if(found){
ms.status[m] += {tpl_uptodate(), checked()};
}
//else {
// ms.status[m] += not_found();
//}
}
}
}
Expand All @@ -291,7 +283,7 @@ ModuleStatus rascalTModelForLocs(
map[str,TModel] tmodels_for_component = ();
map[str,set[str]] m_imports = ();
map[str,set[str]] m_extends = ();
for(m <- component, not_found() notin ms.status[m]){
for(m <- component, not_found() notin ms.status[m], MStatus::ignored() notin ms.status[m]){
imports = { imp | <m1, importPath(), imp> <- ms.strPaths, m1 == m };
m_imports[m] = imports;
extends = { ext | <m1, extendPath(), ext > <- ms.strPaths, m1 == m };
Expand Down Expand Up @@ -351,7 +343,7 @@ ModuleStatus rascalTModelForLocs(

// generate code for the modules in this component

for(str m <- component){
for(str m <- component, MStatus::ignored() notin ms.status[m]){
<success, pt, ms> = getModuleParseTree(m, ms);
if(success){
msgs = codgen(m, pt, ms, compilerConfig);
Expand Down Expand Up @@ -418,7 +410,14 @@ tuple[TModel, ModuleStatus] rascalTModelComponent(set[str] moduleNames, ModuleSt
for(str nm <- moduleNames){
<success, pt, ms> = getModuleParseTree(nm, ms);
if(success){
namedTrees[nm] = pt;
tagsMap = getTags(pt.header.tags);

if(ignoreCompiler(tagsMap)) {
ms.messages[nm] ? [] += [ Message::info("Ignoring module <nm>", pt@\loc) ];
ms.status[nm] += MStatus::ignored();
} else {
namedTrees[nm] = pt;
}
}
//else {
// ms.messages[nm] += error("Cannot get parse tree for module `<nm>`", ms.moduleLocs[nm]);
Expand All @@ -435,7 +434,7 @@ tuple[TModel, ModuleStatus] rascalTModelComponent(set[str] moduleNames, ModuleSt
rascalPreCollectInitialization(namedTrees, c);

added = {};
for(str nm <- moduleNames){
for(str nm <- domain(namedTrees)){
<a, ms> = loadImportsAndExtends(nm, ms, c, added);
added += a;
}
Expand All @@ -447,8 +446,10 @@ tuple[TModel, ModuleStatus] rascalTModelComponent(set[str] moduleNames, ModuleSt

tm.paths = ms.paths;

s = newSolver(namedTrees, tm);
tm = s.run();
if(!isEmpty(namedTrees)){
s = newSolver(namedTrees, tm);
tm = s.run();
}

check_time = (cpuTime() - start_check)/1000000;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,16 @@ void collect (current: (Declaration) `<Tags tags> <Visibility visibility> data <
= dataDeclaration(tags, current, [v | v <- variants], c);

void dataDeclaration(Tags tags, Declaration current, list[Variant] variants, Collector c){
tagsMap = getTags(tags);
if(ignoreCompiler(tagsMap)) { println("*** ignore: <current>"); return; }

userType = current.user;
adtName = prettyPrintName(userType.name);

tagsMap = getTags(tags);
if(ignoreCompiler(tagsMap)) {
c.report(info(current, "Ignoring declaration of `<adtName>`"));
return;
}


commonKeywordParameterList = getCommonKwFormals(current);

typeParameters = getTypeParameters(userType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@ void collect(Module current: (Module) `<Header header> <Body body>`, Collector c

tagsMap = getTags(header.tags);

//if(ignoreCompiler(tagsMap)) {println("*** ignore module <mname>"); return; }
if(ignoreCompiler(tagsMap)) {
c.report(info(current, "Ignoring module <mname>"));
return;
}
<deprecated, deprecationMessage> = getDeprecated(tagsMap);

tmod = deprecated ? amodule(mname, deprecationMessage=deprecationMessage) : amodule(mname);
Expand All @@ -55,7 +58,6 @@ void collect(Module current: (Module) `<Header header> <Body body>`, Collector c
c.enterScope(current);
collect(header, body, c);
c.leaveScope(current);
//c.pop(key_current_module); // leave it there for all following phases to see
}

void checkModuleName(loc mloc, QualifiedName qualifiedModuleName, Collector c){
Expand Down Expand Up @@ -149,11 +151,14 @@ void collect(Tag tg, Collector c){
// Deprecated
void collect(current: (Declaration) `<Tags tags> <Visibility visibility> anno <Type annoType> <Type onType> @ <Name name> ;`, Collector c){
c.report(warning(current, "Annotations are deprecated, use keyword parameters instead"));
pname = prettyPrintName(name);

tagsMap = getTags(tags);
if(ignoreCompiler(tagsMap)) { println("*** ignore: <current>"); return; }
if(ignoreCompiler(tagsMap)) {
c.report(info(current, "Ignoring anno declaration for `<pname>`"));
return;
}

pname = prettyPrintName(name);
dt = defType([annoType, onType], AType(Solver s) { return aanno(pname, s.getType(onType), s.getType(annoType)); });
dt.vis = getVis(current.visibility, publicVis());
dt.md5 = md5Hash("<current>");
Expand Down Expand Up @@ -194,7 +199,10 @@ void collect(current: (FunctionDeclaration) `<FunctionDeclaration decl>`, Collec
fname = signature.name;
modifiers = ["<m>" | m <- signature.modifiers.modifiers];
tagsMap = getTags(decl.tags);
if(ignoreCompiler(tagsMap)) { println("ignore: function <decl.signature.name>"); return; }
if(ignoreCompiler(tagsMap)) {
c.report(info(current, "Ignoring function declaration for `<decl.signature.name>`"));
return;
}

<expected, expectedTagString> = getExpected(decl.tags);
if(expected){
Expand Down Expand Up @@ -583,58 +591,34 @@ void collect(Parameters parameters, Collector c){
endPatternScope(c);
}
void(Solver) makeReturnRequirement(Tree returnExpr, Type declaredReturnType)
void(Solver) makeReturnRequirement(Tree returnExpr, Type returnType)
= void(Solver s){
theDeclaredReturnType = s.getType(declaredReturnType);
returnRequirement(returnExpr, theDeclaredReturnType, s);
returnRequirement(returnExpr, s.getType(returnType), s);
};
void(Solver) makeReturnRequirement(Tree returnExpr, AType declaredReturnAType)
void(Solver) makeReturnRequirement(Tree returnExpr, AType returnAType)
= void(Solver s){
returnRequirement(returnExpr, declaredReturnAType, s);
returnRequirement(returnExpr, returnAType, s);
};
bool isParameterized(AType t){
return /aparameter(_,_) := t;
}
void returnRequirement(Tree returnExpr, AType declaredReturnType, Solver s){
void returnRequirement(Tree returnExpr, AType declaredReturnType, Solver s){
returnExprType = s.getType(returnExpr);
allTypeParametersInReturnType = { unsetRec(p, "alabel") | /p:aparameter(_,_) := declaredReturnType };
allTypeParametersInExpr = { unsetRec(p, "alabel") | /Expression e := returnExpr, /p:aparameter(_,_) := s.getType(e) };
missingTypeParameters = allTypeParametersInReturnType - allTypeParametersInExpr;
if(!isEmpty(missingTypeParameters)){
s.report(error(returnExpr, "Return expression does not bind %v in return type", missingTypeParameters));
}
Bindings bindings = ();
try bindings = matchRascalTypeParams(returnExprType, declaredReturnType, bindings);
try bindings = matchRascalTypeParams(declaredReturnType, returnExprType, bindings);
catch invalidMatch(str reason):
s.report(error(returnExpr, reason));
if(isParameterized(returnExprType)){
if(!isParameterized(declaredReturnType)){
if(!s.subtype(returnExprType, declaredReturnType)){
s.report(error(returnExpr, "Cannot return a parameterized type %t, when declared return type %t is not parameterized", returnExprType, declaredReturnType));
}
}
} else if(isParameterized(declaredReturnType)){
if(!s.subtype(returnExprType, declaredReturnType)){
s.report(error(returnExpr, "Cannot return a non-parameterized type %t, when declared return type %t is parameterized", returnExprType, declaredReturnType));
}
}
actualReturnType = returnExprType;
try {
actualReturnType = instantiateRascalTypeParameters(returnExpr, returnExprType, bindings, s);
} catch invalidInstantiation(str reason):{
s.report(error(returnExpr, "Returned type %t does not match declared type %t: %v", returnExprType, declaredReturnType, reason));
}
if(s.isFullyInstantiated(actualReturnType)){
s.requireTrue(s.equal(actualReturnType, avoid()) ? s.equal(declaredReturnType, avoid())
: s.subtype(actualReturnType, declaredReturnType),
error(returnExpr, "Return type %t expected, found %t", declaredReturnType, actualReturnType));
} else
if(!s.unify(actualReturnType, declaredReturnType)){
s.requireTrue(s.equal(actualReturnType, avoid()) ? s.equal(declaredReturnType, avoid())
: s.subtype(actualReturnType, declaredReturnType),
error(returnExpr, "Return type %t expected, found %t", declaredReturnType, actualReturnType));
}
s.requireTrue(s.equal(returnExprType, avoid()) ? s.equal(declaredReturnType, avoid())
: s.subtype(returnExprType, declaredReturnType),
error(returnExpr, "Return type %t expected, found %t", declaredReturnType, returnExprType));
}
// ---- return statement (closely interacts with function declaration) --------
Expand All @@ -644,7 +628,7 @@ void collect(current: (Statement) `return <Statement statement>`, Collector c){
assert !isEmpty(functionScopes);
for(<_, scopeInfo> <- functionScopes){
if(returnInfo(Type returnType) := scopeInfo){
c.require("check return type", current, [returnType], makeReturnRequirement(statement, returnType));
c.require("check return type", current, [statement], makeReturnRequirement(statement, returnType));
c.fact(current, returnType); // Note that type of the return statement as a whole is the function's return type
collect(statement, c);
return;
Expand All @@ -658,22 +642,28 @@ void collect(current: (Statement) `return <Statement statement>`, Collector c){
// ---- alias declaration -----------------------------------------------------
void collect (current: (Declaration) `<Tags tags> <Visibility visibility> alias <QualifiedName name> = <Type base>;`, Collector c){
aliasName = prettyPrintName(name);
tagsMap = getTags(tags);
if(ignoreCompiler(tagsMap)) { println("*** ignore: <current>"); return; }
if(ignoreCompiler(tagsMap)) {
c.report(info(current, "Ignoring alias declaration for `<aliasName>`"));
return;
}
aliasName = prettyPrintName(name);
c.define(aliasName, aliasId(), current, defType([base], AType(Solver s) { return s.getType(base); })[md5 = md5Hash("<current>")]);
c.enterScope(current);
collect(base, c);
c.leaveScope(current);
}
void collect (current: (Declaration) `<Tags tags> <Visibility visibility> alias <QualifiedName name>[ <{Type ","}+ parameters> ] = <Type base>;`, Collector c){
aliasName = prettyPrintName(name);
tagsMap = getTags(tags);
if(ignoreCompiler(tagsMap)) { println("*** ignore: <current>"); return; }
aliasName = prettyPrintName(name);
if(ignoreCompiler(tagsMap)) {
c.report(info(current, "Ignoring alias declaration for `<aliasName>`"));
return;
}
typeVars = for(tp <- parameters){
if(!(tp has typeVar)) c.report(error(tp, "Only type parameter allowed"));
append tp.typeVar;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1010,7 +1010,6 @@ void collect(current:(Expression) `<Expression expression> \< <{Field ","}+ fiel
checkNonVoid(expression, s, "Base expression of field projection");
return computeFieldProjectionType(current, s.getType(expression), flds, s);
});
//collectParts(current, c);
collect(expression, fields, c);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ void collect(current: (Pattern) `[ <Type tp> ] <Pattern p>`, Collector c){

c.require("asType", current, [tp, p], void(Solver s){
if(!isStrAType(s.getType(p))){
s.requireSubType(p, tp, error(p, "Pattern should be subtype of %t, found %t", tp, p));
s.requireComparable(p, tp, error(p, "Pattern should be subtype of %t, found %t", tp, p));
}
});
collect(tp, c);
Expand Down
11 changes: 6 additions & 5 deletions src/org/rascalmpl/core/library/lang/rascalcore/check/Import.rsc
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ data MStatus =
| code_generated()
| tpl_uptodate()
| tpl_saved()
| ignored()
;

data ModuleStatus =
Expand Down Expand Up @@ -408,7 +409,7 @@ set[loc] getImportLocsOfModule(str qualifiedModuleName, set[Module] modules)
// ---- Save modules ----------------------------------------------------------

map[str, loc] getModuleScopes(TModel tm)
= (id: defined | <loc _, str id, str _orgId, moduleId(), /*int _,*/ loc defined, DefInfo _> <- tm.defines);
= (id: defined | <loc _, str id, str _orgId, moduleId(), loc defined, DefInfo _> <- tm.defines);

loc getModuleScope(str qualifiedModuleName, map[str, loc] moduleScopes, PathConfig pcfg){
if(moduleScopes[qualifiedModuleName]?){
Expand All @@ -427,12 +428,12 @@ ModuleStatus preSaveModule(set[str] component, map[str,set[str]] m_imports, map[
pcfg = ms.pathConfig;

dependencies_ok = true;
for(m <- component, not_found() notin ms.status[m]){
for(m <- component, not_found() notin ms.status[m], MStatus::ignored() notin ms.status[m]){
if(parse_error() in ms.status[m]){
ms.tmodels[m] = tmodel(modelName=m,messages=ms.messages[m]);
return ms;
}
for(imp <- m_imports[m] + m_extends[m], not_found() notin ms.status[imp]){
for(imp <- m_imports[m] + m_extends[m], not_found() notin ms.status[imp], MStatus::ignored() notin ms.status[m]){
imp_status = ms.status[imp];
if(parse_error() in imp_status || checked() notin imp_status){
dependencies_ok = false;
Expand All @@ -445,7 +446,7 @@ ModuleStatus preSaveModule(set[str] component, map[str,set[str]] m_imports, map[
return ms;
}
}
for(m <- component, not_found() notin ms.status[m]){
for(m <- component, not_found() notin ms.status[m], MStatus::ignored() notin ms.status[m]){
tm.modelName = m;
mScope = getModuleScope(m, moduleScopes, pcfg);
tm.moduleLocs = (m : mScope);
Expand All @@ -464,7 +465,7 @@ ModuleStatus doSaveModule(set[str] component, map[str,set[str]] m_imports, map[s
map[str,datetime] moduleLastModified = ms.moduleLastModified;
pcfg = ms.pathConfig;

if(any(c <- component, !isEmpty({parse_error(), not_found()} & ms.status[c]))){
if(any(c <- component, !isEmpty({parse_error(), not_found(), MStatus::ignored()} & ms.status[c]))){
return ms;
}
//println("doSaveModule: <qualifiedModuleName>, <imports>, <extends>, <moduleScopes>");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ bool unexpectedType(str stmts, list[str] importedModules = [], list[str] initial
"_ is defined as _ and cannot be applied to argument",
"Missing return statement",
"Return type _ expected, found _",
"Return expression does not bind _",
"Type of generator should be _, found _",
"Pattern should be comparable with _, found _",
"Argument of _ should be _, found _",
Expand Down
Loading

0 comments on commit aeffdab

Please sign in to comment.