From aeffdabb77ad8aaad11c933f7ff2f869da74864c Mon Sep 17 00:00:00 2001 From: paulklint Date: Sat, 16 Mar 2024 15:42:31 +0100 Subject: [PATCH] Added ignore reporting. Better analysis parameterized function decls - 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. --- .../lang/rascalcore/check/ATypeUtils.rsc | 10 +- .../library/lang/rascalcore/check/Checker.rsc | 29 +++--- .../check/CollectDataDeclaration.rsc | 11 ++- .../rascalcore/check/CollectDeclaration.rsc | 94 +++++++++---------- .../rascalcore/check/CollectExpression.rsc | 1 - .../lang/rascalcore/check/CollectPattern.rsc | 2 +- .../library/lang/rascalcore/check/Import.rsc | 11 ++- .../check/tests/StaticTestingUtils.rsc | 1 + .../lang/rascalcore/compile/Examples/Tst5.rsc | 16 ++-- 9 files changed, 87 insertions(+), 88 deletions(-) diff --git a/src/org/rascalmpl/core/library/lang/rascalcore/check/ATypeUtils.rsc b/src/org/rascalmpl/core/library/lang/rascalcore/check/ATypeUtils.rsc index 5ca6ee00..d5dff58e 100644 --- a/src/org/rascalmpl/core/library/lang/rascalcore/check/ATypeUtils.rsc +++ b/src/org/rascalmpl/core/library/lang/rascalcore/check/ATypeUtils.rsc @@ -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 does not have field "); } throw rascalCheckerInternalError("getTupleFieldType given unexpected type "); @@ -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 @@ -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 "); } @@ -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 "); } diff --git a/src/org/rascalmpl/core/library/lang/rascalcore/check/Checker.rsc b/src/org/rascalmpl/core/library/lang/rascalcore/check/Checker.rsc index 310df5b2..5a72f8fa 100644 --- a/src/org/rascalmpl/core/library/lang/rascalcore/check/Checker.rsc +++ b/src/org/rascalmpl/core/library/lang/rascalcore/check/Checker.rsc @@ -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 , reason: ", mloc) ]; - // return ms; - //} } try { @@ -279,9 +274,6 @@ ModuleStatus rascalTModelForLocs( if(found){ ms.status[m] += {tpl_uptodate(), checked()}; } - //else { - // ms.status[m] += not_found(); - //} } } } @@ -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 | <- ms.strPaths, m1 == m }; m_imports[m] = imports; extends = { ext | <- ms.strPaths, m1 == m }; @@ -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]){ = getModuleParseTree(m, ms); if(success){ msgs = codgen(m, pt, ms, compilerConfig); @@ -418,7 +410,14 @@ tuple[TModel, ModuleStatus] rascalTModelComponent(set[str] moduleNames, ModuleSt for(str nm <- moduleNames){ = getModuleParseTree(nm, ms); if(success){ - namedTrees[nm] = pt; + tagsMap = getTags(pt.header.tags); + + if(ignoreCompiler(tagsMap)) { + ms.messages[nm] ? [] += [ Message::info("Ignoring module ", pt@\loc) ]; + ms.status[nm] += MStatus::ignored(); + } else { + namedTrees[nm] = pt; + } } //else { // ms.messages[nm] += error("Cannot get parse tree for module ``", ms.moduleLocs[nm]); @@ -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)){ = loadImportsAndExtends(nm, ms, c, added); added += a; } @@ -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; diff --git a/src/org/rascalmpl/core/library/lang/rascalcore/check/CollectDataDeclaration.rsc b/src/org/rascalmpl/core/library/lang/rascalcore/check/CollectDataDeclaration.rsc index 738077a7..f68a1153 100644 --- a/src/org/rascalmpl/core/library/lang/rascalcore/check/CollectDataDeclaration.rsc +++ b/src/org/rascalmpl/core/library/lang/rascalcore/check/CollectDataDeclaration.rsc @@ -25,11 +25,16 @@ void collect (current: (Declaration) ` 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: "); return; } - userType = current.user; adtName = prettyPrintName(userType.name); + + tagsMap = getTags(tags); + if(ignoreCompiler(tagsMap)) { + c.report(info(current, "Ignoring declaration of ``")); + return; + } + + commonKeywordParameterList = getCommonKwFormals(current); typeParameters = getTypeParameters(userType); diff --git a/src/org/rascalmpl/core/library/lang/rascalcore/check/CollectDeclaration.rsc b/src/org/rascalmpl/core/library/lang/rascalcore/check/CollectDeclaration.rsc index 63de5235..e3284679 100644 --- a/src/org/rascalmpl/core/library/lang/rascalcore/check/CollectDeclaration.rsc +++ b/src/org/rascalmpl/core/library/lang/rascalcore/check/CollectDeclaration.rsc @@ -42,7 +42,10 @@ void collect(Module current: (Module) `
`, Collector c tagsMap = getTags(header.tags); - //if(ignoreCompiler(tagsMap)) {println("*** ignore module "); return; } + if(ignoreCompiler(tagsMap)) { + c.report(info(current, "Ignoring module ")); + return; + } = getDeprecated(tagsMap); tmod = deprecated ? amodule(mname, deprecationMessage=deprecationMessage) : amodule(mname); @@ -55,7 +58,6 @@ void collect(Module current: (Module) `
`, 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){ @@ -149,11 +151,14 @@ void collect(Tag tg, Collector c){ // Deprecated void collect(current: (Declaration) ` anno @ ;`, Collector c){ c.report(warning(current, "Annotations are deprecated, use keyword parameters instead")); + pname = prettyPrintName(name); tagsMap = getTags(tags); - if(ignoreCompiler(tagsMap)) { println("*** ignore: "); return; } + if(ignoreCompiler(tagsMap)) { + c.report(info(current, "Ignoring anno declaration for ``")); + 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(""); @@ -194,7 +199,10 @@ void collect(current: (FunctionDeclaration) ``, Collec fname = signature.name; modifiers = ["" | m <- signature.modifiers.modifiers]; tagsMap = getTags(decl.tags); - if(ignoreCompiler(tagsMap)) { println("ignore: function "); return; } + if(ignoreCompiler(tagsMap)) { + c.report(info(current, "Ignoring function declaration for ``")); + return; + } = getExpected(decl.tags); if(expected){ @@ -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) -------- @@ -644,7 +628,7 @@ void collect(current: (Statement) `return `, 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; @@ -658,10 +642,13 @@ void collect(current: (Statement) `return `, Collector c){ // ---- alias declaration ----------------------------------------------------- void collect (current: (Declaration) ` alias = ;`, Collector c){ + aliasName = prettyPrintName(name); tagsMap = getTags(tags); - if(ignoreCompiler(tagsMap)) { println("*** ignore: "); return; } + if(ignoreCompiler(tagsMap)) { + c.report(info(current, "Ignoring alias declaration for ``")); + return; + } - aliasName = prettyPrintName(name); c.define(aliasName, aliasId(), current, defType([base], AType(Solver s) { return s.getType(base); })[md5 = md5Hash("")]); c.enterScope(current); collect(base, c); @@ -669,11 +656,14 @@ void collect (current: (Declaration) ` alias } void collect (current: (Declaration) ` alias [ <{Type ","}+ parameters> ] = ;`, Collector c){ + aliasName = prettyPrintName(name); tagsMap = getTags(tags); - if(ignoreCompiler(tagsMap)) { println("*** ignore: "); return; } - aliasName = prettyPrintName(name); - + if(ignoreCompiler(tagsMap)) { + c.report(info(current, "Ignoring alias declaration for ``")); + return; + } + typeVars = for(tp <- parameters){ if(!(tp has typeVar)) c.report(error(tp, "Only type parameter allowed")); append tp.typeVar; diff --git a/src/org/rascalmpl/core/library/lang/rascalcore/check/CollectExpression.rsc b/src/org/rascalmpl/core/library/lang/rascalcore/check/CollectExpression.rsc index 6a0f5b58..6d3b8814 100644 --- a/src/org/rascalmpl/core/library/lang/rascalcore/check/CollectExpression.rsc +++ b/src/org/rascalmpl/core/library/lang/rascalcore/check/CollectExpression.rsc @@ -1010,7 +1010,6 @@ void collect(current:(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); } diff --git a/src/org/rascalmpl/core/library/lang/rascalcore/check/CollectPattern.rsc b/src/org/rascalmpl/core/library/lang/rascalcore/check/CollectPattern.rsc index 7bef0031..ef54c6d0 100644 --- a/src/org/rascalmpl/core/library/lang/rascalcore/check/CollectPattern.rsc +++ b/src/org/rascalmpl/core/library/lang/rascalcore/check/CollectPattern.rsc @@ -348,7 +348,7 @@ void collect(current: (Pattern) `[ ] `, 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); diff --git a/src/org/rascalmpl/core/library/lang/rascalcore/check/Import.rsc b/src/org/rascalmpl/core/library/lang/rascalcore/check/Import.rsc index e4c3ec91..7c2e02ab 100644 --- a/src/org/rascalmpl/core/library/lang/rascalcore/check/Import.rsc +++ b/src/org/rascalmpl/core/library/lang/rascalcore/check/Import.rsc @@ -215,6 +215,7 @@ data MStatus = | code_generated() | tpl_uptodate() | tpl_saved() + | ignored() ; data ModuleStatus = @@ -408,7 +409,7 @@ set[loc] getImportLocsOfModule(str qualifiedModuleName, set[Module] modules) // ---- Save modules ---------------------------------------------------------- map[str, loc] getModuleScopes(TModel tm) - = (id: defined | <- tm.defines); + = (id: defined | <- tm.defines); loc getModuleScope(str qualifiedModuleName, map[str, loc] moduleScopes, PathConfig pcfg){ if(moduleScopes[qualifiedModuleName]?){ @@ -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; @@ -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); @@ -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: , , , "); diff --git a/src/org/rascalmpl/core/library/lang/rascalcore/check/tests/StaticTestingUtils.rsc b/src/org/rascalmpl/core/library/lang/rascalcore/check/tests/StaticTestingUtils.rsc index 46032199..b817b96f 100644 --- a/src/org/rascalmpl/core/library/lang/rascalcore/check/tests/StaticTestingUtils.rsc +++ b/src/org/rascalmpl/core/library/lang/rascalcore/check/tests/StaticTestingUtils.rsc @@ -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 _", diff --git a/src/org/rascalmpl/core/library/lang/rascalcore/compile/Examples/Tst5.rsc b/src/org/rascalmpl/core/library/lang/rascalcore/compile/Examples/Tst5.rsc index e32c2466..6f58adc7 100644 --- a/src/org/rascalmpl/core/library/lang/rascalcore/compile/Examples/Tst5.rsc +++ b/src/org/rascalmpl/core/library/lang/rascalcore/compile/Examples/Tst5.rsc @@ -1,6 +1,14 @@ module lang::rascalcore::compile::Examples::Tst5 - + +&T <: num makeSmallerThan(&T <: num n) { + &T <: num res; + if (int i := n) { + res = i; + return res; + } + return n; +} //import List; // //value main(){ @@ -14,9 +22,3 @@ module lang::rascalcore::compile::Examples::Tst5 //} - -//import util::Maybe; -// -// &T testFunction(Maybe[&T] _, &T x) = x; -// -// value main() = testFunction(just(3), 5);