diff --git a/src/org/rascalmpl/core/library/lang/rascalcore/check/BasicRascalConfig.rsc b/src/org/rascalmpl/core/library/lang/rascalcore/check/BasicRascalConfig.rsc index e284375f..fc2f95ef 100644 --- a/src/org/rascalmpl/core/library/lang/rascalcore/check/BasicRascalConfig.rsc +++ b/src/org/rascalmpl/core/library/lang/rascalcore/check/BasicRascalConfig.rsc @@ -6,7 +6,7 @@ module lang::rascalcore::check::BasicRascalConfig The checker itself is configure in RascalConfig. */ extend analysis::typepal::TypePal; - + import lang::rascal::\syntax::Rascal; import Location; import util::SemVer; @@ -36,14 +36,14 @@ data IdRole public set[IdRole] syntaxRoles = {aliasId(), nonterminalId(), lexicalId(), layoutId(), keywordId()}; public set[IdRole] dataOrSyntaxRoles = {dataId()} + syntaxRoles; -public set[IdRole] dataRoles = {aliasId(), dataId()}; +public set[IdRole] dataRoles = {aliasId(), dataId()}; public set[IdRole] outerFormalRoles = {formalId(), keywordFormalId()}; public set[IdRole] positionalFormalRoles = {formalId(), nestedFormalId()}; public set[IdRole] formalRoles = outerFormalRoles + {nestedFormalId()}; public set[IdRole] variableRoles = formalRoles + {variableId(), moduleVariableId(), patternVariableId()}; public set[IdRole] inferrableRoles = formalRoles + {variableId(), moduleVariableId(), patternVariableId()}; -public set[IdRole] keepInTModelRoles = dataOrSyntaxRoles + { moduleId(), constructorId(), functionId(), - fieldId(), keywordFieldId(), annoId(), +public set[IdRole] keepInTModelRoles = dataOrSyntaxRoles + { moduleId(), constructorId(), functionId(), + fieldId(), keywordFieldId(), annoId(), moduleVariableId(), productionId(), nonterminalId() }; public set[IdRole] assignableRoles = variableRoles; @@ -52,7 +52,7 @@ data PathRole = importPath() | extendPath() ; - + data ScopeRole = //moduleScope() functionScope() @@ -130,21 +130,22 @@ alias RascalCompilerConfig = TypePalConfig; data TypePalConfig( str rascalTplVersion = getCurrentRascalTplVersion(), - + // Control message level bool warnUnused = true, bool warnUnusedFormals = true, bool warnUnusedVariables = true, bool warnUnusedPatternFormals = true, - + bool infoModuleChecked = false, + loc reloc = |noreloc:///|, // Unused - + // Debugging options bool verbose = true, // for each compiled module, module name and compilation time bool logImports = false, // log all imported files bool logWrittenFiles = false, // log all files written by compiler bool logPathConfig = false, // log PathConfig that is used - + bool optimizeVisit = true, // Options for compiler developer bool enableAsserts = true, bool forceCompilationTopModule = false 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 58637f44..ba5da4b1 100644 --- a/src/org/rascalmpl/core/library/lang/rascalcore/check/Checker.rsc +++ b/src/org/rascalmpl/core/library/lang/rascalcore/check/Checker.rsc @@ -246,7 +246,9 @@ ModuleStatus rascalTModelForLocs( msgs = []; = getModuleParseTree(m, ms); if(success){ - msgs += [info("Checked ", pt.header.name@\loc)]; + if(compilerConfig.infoModuleChecked){ + msgs += [info("Checked ", pt.header.name@\loc)]; + } check_imports: for(imod <- pt.header.imports, imod has \module){ iname = unescape(""); diff --git a/src/org/rascalmpl/core/library/lang/rascalcore/check/RascalConfig.rsc b/src/org/rascalmpl/core/library/lang/rascalcore/check/RascalConfig.rsc index 79a53d33..3ac98b2a 100644 --- a/src/org/rascalmpl/core/library/lang/rascalcore/check/RascalConfig.rsc +++ b/src/org/rascalmpl/core/library/lang/rascalcore/check/RascalConfig.rsc @@ -43,15 +43,15 @@ bool rascalMayOverload(set[loc] defs, map[loc, Define] defines){ switch(defines[def].idRole){ case functionId(): { if(seenVAR) return false; seenFUNCTION = true; } - case variableId(): + case variableId(): { if(seenVAR || seenFUNCTION) return false; seenVAR = true;} - case moduleVariableId(): + case moduleVariableId(): { if(seenVAR || seenFUNCTION) return false; seenVAR = true;} - case formalId(): + case formalId(): { if(seenVAR || seenFUNCTION) return false; seenVAR = true;} - case keywordFormalId(): + case keywordFormalId(): { if(seenVAR || seenFUNCTION) return false; seenVAR = true;} - case patternVariableId(): + case patternVariableId(): { if(seenVAR || seenFUNCTION) return false; seenVAR = true;} case nonterminalId(): { if(seenLEX || seenLAY || seenKEY){ return false; } seenNT = true; } @@ -62,8 +62,8 @@ bool rascalMayOverload(set[loc] defs, map[loc, Define] defines){ case keywordId(): { if(seenNT || seenLAY || seenLEX) { return false; } seenKEY = true; } case aliasId(): - { if(seenALIAS) return false; seenALIAS = true; } - + { if(seenALIAS) return false; seenALIAS = true; } + } } return true; @@ -86,10 +86,10 @@ Accept rascalIsAcceptableSimple(loc def, Use use, Solver s){ } } return ignoreContinue(); - } else if(!isEmpty(use.idRoles & defBeforeUseRoles) // If we encounter a use before def + } else if(!isEmpty(use.idRoles & defBeforeUseRoles) // If we encounter a use before def && isContainedIn(def, use.scope) // in an idRole that requires def before use ){ // and the definition is in the same scope as the use - // then only allow this when inside explicitly defined areas (typically the result part of a comprehension) + // then only allow this when inside explicitly defined areas (typically the result part of a comprehension) if(lrel[loc,loc] allowedParts := s.getStack(key_allow_use_before_def)){ list[loc] parts = allowedParts[use.scope]; return !isEmpty(parts) && any(part <- parts, isContainedIn(use.occ, part)) ? acceptBinding() : ignoreContinue(); @@ -98,7 +98,7 @@ Accept rascalIsAcceptableSimple(loc def, Use use, Solver s){ } } } - + // Uses of a keyword formal inside its initializing expression are rejected if(d.idRole == keywordFormalId() && isContainedIn(use.occ, d.defined)){ return ignoreContinue(); @@ -109,35 +109,35 @@ Accept rascalIsAcceptableSimple(loc def, Use use, Solver s){ Accept rascalIsAcceptableQualified(loc def, Use use, Solver s){ // println("rascalIsAcceptableQualified: , "); atype = s.getType(def); - + defPath = def.path; qualAsPath = replaceAll(use.ids[0], "::", "/") + ".rsc"; - + // qualifier and proposed definition are the same? if(endsWith(defPath, qualAsPath)){ return acceptBinding(); } - + // Qualifier is a ADT name? - + if(acons(aadt(adtName, _, _), list[AType] _fields, list[Keyword] _kwFields) := atype){ return use.ids[0] == adtName ? acceptBinding() : ignoreContinue(); } - + // Qualifier is a Production? - + if(aprod(prod(aadt(adtName, _, _), list[AType] _atypes)) := atype){ return use.ids[0] == adtName ? acceptBinding() : ignoreContinue(); } - + // Is there another acceptable qualifier via an extend? - + extendedStarBy = { | <- s.getPaths()}*; - + if(!isEmpty(extendedStarBy) && any(p <- extendedStarBy[defPath]?{}, endsWith(p, defPath))){ return acceptBinding(); } - + return ignoreContinue(); } @@ -147,10 +147,10 @@ Accept rascalIsAcceptablePath(loc _defScope, loc def, Use _use, PathRole pathRol defIdRole = the_define.idRole; // Only data declarations, constructors and visible entities are visible if(!(defIdRole == dataId() || defIdRole == constructorId() || the_define.defInfo.vis == publicVis())){ - return ignoreContinue(); + return ignoreContinue(); } } - + return acceptBinding(); } @@ -158,7 +158,7 @@ AType rascalInstantiateTypeParameters(Tree selector, def:aadt(str adtName1, list[AType] formals, SyntaxRole syntaxRole1), ins:aadt(str adtName2, list[AType] actuals, SyntaxRole syntaxRole2), AType act, - Solver s){ + Solver s){ nformals = size(formals); nactuals = size(actuals); if(nformals != nactuals) s.report(error(selector, "Expected %v type parameters for %q, found %v", nformals, adtName1, nactuals)); @@ -197,25 +197,25 @@ AType rascalGetTypeInTypeFromDefine(Define containerDef, str selectorName, set[I //println("rascalGetTypeInTypeFromDefine: , "); //println("commonKeywordFields: "); containerType = s.getType(containerDef.defined); - if( fieldId() in idRolesSel - && selectorName == "top" + if( fieldId() in idRolesSel + && selectorName == "top" && isStartNonTerminalType(containerType) ){ return getStartNonTerminalType(containerType); } - if( fieldId() in idRolesSel - && selectorName == "top" + if( fieldId() in idRolesSel + && selectorName == "top" && isTreeType(containerType) ){ return containerType; } - if( keywordFieldId() in idRolesSel - && selectorName == "src" + if( keywordFieldId() in idRolesSel + && selectorName == "src" && (isTreeType(containerType) || isNonTerminalAType(containerType)) ){ return aloc(); } - + for(kwf <- containerDef.defInfo.commonKeywordFields){ if(prettyPrintName(kwf.name) == selectorName){ return s.getType(kwf.\type); @@ -252,18 +252,18 @@ bool isOverloadedFunction(loc fun, map[loc,Define] definitions, map[loc, AType] bool rascalReportUnused(loc def, TModel tm){ config = tm.config; if(!config.warnUnused) return false; - + definitions = tm.definitions; - + if(!definitions[def]? || !tm.moduleLocs[tm.modelName]?) return false; - + if(!isContainedIn(definitions[def].defined, tm.moduleLocs[tm.modelName])){ return false; } - + scopes = tm.scopes; facts = tm.facts; - + bool reportFormal(Define define){ if(!config.warnUnusedFormals || isWildCard(define.id[0])) return false; container = tm.definitions[findContainer(def, definitions, scopes)]; @@ -273,7 +273,7 @@ bool rascalReportUnused(loc def, TModel tm){ } return false; } - + define = definitions[def]; try { switch(define.idRole){ @@ -289,10 +289,10 @@ bool rascalReportUnused(loc def, TModel tm){ case constructorId(): return false; case fieldId(): return false; case keywordFieldId(): return false; - case formalId(): return reportFormal(define); - case nestedFormalId(): return reportFormal(define); - case keywordFormalId(): return reportFormal(define); - + case formalId(): return reportFormal(define); + case nestedFormalId(): return reportFormal(define); + case keywordFormalId(): return reportFormal(define); + case patternVariableId(): { if(!config.warnUnusedVariables) return false; return !isWildCard(define.id[0]); } @@ -311,7 +311,7 @@ bool rascalReportUnused(loc def, TModel tm){ case keywordId(): return false; } } catch NoSuchKey(_): return false; - + return true; } @@ -324,18 +324,18 @@ TModel rascalPreSolver(map[str,Tree] _namedTrees, TModel m){ void checkOverloading(map[str,Tree] namedTrees, Solver s){ if(s.reportedErrors()) return; - + set[Define] defines = s.getAllDefines(); facts = s.getFacts(); set[loc] actuallyUsedDefs = range(s.getUseDef()); moduleScopes = { t@\loc | t <- range(namedTrees) }; - + funDefs = { | define <- defines, define.idRole == functionId() }; funIds = domain(funDefs); for(id <- funIds){ set[Define] defs = funDefs[id]; if(size(defs) > 1){ - for(d1 <- defs, d2 <- defs, d1.defined != d2.defined, + for(d1 <- defs, d2 <- defs, d1.defined != d2.defined, t1 := facts[d1.defined]?afunc(avoid(),[],[]), t2 := facts[d2.defined]?afunc(avoid(),[],[]), d1.scope in moduleScopes, d2.scope in moduleScopes, size(t1.formals) == size(t2.formals) @@ -357,36 +357,36 @@ void checkOverloading(map[str,Tree] namedTrees, Solver s){ msgs = [ error("Return type `` of function `` is not comparable with return type `` of other declaration with comparable arguments", d1.defined) ]; s.addMessages(msgs); } - + list[str] getKwNames(list[Keyword] l) = [k.fieldType.alabel | Keyword k <- l]; - - if(comparableList(t1.formals, t2.formals)) { + + if(comparableList(t1.formals, t2.formals)) { t1_kwNames = getKwNames(t1.kwFormals); t2_kwNames = getKwNames(t2.kwFormals); - - if(t1_kwNames != t2_kwNames){ - diffkws = t2_kwNames - t1_kwNames; + + if(t1_kwNames != t2_kwNames){ + diffkws = t2_kwNames - t1_kwNames; plural = size(diffkws) > 1 ? "s" : ""; msgs = [ error("Other declaration of function `` has different keyword parameter `" | k <- diffkws])> at ", d1.defined) ]; s.addMessages(msgs); } } } - + if((t1 has isTest && t1.isTest) || (t2 has isTest && t2.isTest)){ msgs = [ error("Test name `` should not be overloaded", d.defined) | d <- defs ]; s.addMessages(msgs); } } - + defaults = { d | d <- defs, t := facts[d.defined]?afunc(avoid(),[],[]), t.isDefault }; if(size(defaults) > 1 && all(d1 <- defaults, d2 <- defaults, d1 != d2, d1.scope == d2.scope)){ msgs = [ info("Multiple defaults defined for function ``, refactor or manually check non-overlap", d.defined) | d <- defaults ]; s.addMessages(msgs); } - } + } } - + consNameDef = { | define <- defines, define.idRole == constructorId() }; @@ -394,7 +394,7 @@ void checkOverloading(map[str,Tree] namedTrees, Solver s){ for(id <- consIds){ defs = consNameDef[id]; allDefs = { d.defined | d <- defs }; - for(d1 <- defs, d2 <- defs, + for(d1 <- defs, d2 <- defs, d1.defined != d2.defined, t1 := facts[d1.defined]?acons(aadt("***DUMMY***", [], dataSyntax()),[],[]), t2 := facts[d2.defined]?acons(aadt("***DUMMY***", [], dataSyntax()),[],[]), @@ -404,7 +404,7 @@ void checkOverloading(map[str,Tree] namedTrees, Solver s){ msgs = []; if(t1.adt == t2.adt){ msgs = [ error("Constructor `` overlaps with other declaration for type ``, see ", d.defined) | d <- defs ]; - } + } // NOTE: After discussion about the relevance of the following checks they have been commented out // and will be removed later // else if(d1.defined in actuallyUsedDefs && d2.defined in actuallyUsedDefs){ @@ -413,7 +413,7 @@ void checkOverloading(map[str,Tree] namedTrees, Solver s){ // msgs = [ info("On use add a qualifier to constructor ``, it overlaps with other declaration, see ", d.defined) | d <- defs ]; // } s.addMessages(msgs); - } + } } try { matchingConds = [ | <_, Define d> <- consNameDef, d.scope in moduleScopes, t := s.getType(d)]; @@ -431,10 +431,10 @@ void checkOverloading(map[str,Tree] namedTrees, Solver s){ } void rascalPostSolver(map[str,Tree] namedTrees, Solver s){ - + if(!s.reportedErrors()){ checkOverloading(namedTrees, s); - + for(_mname <- namedTrees){ addADTsAndCommonKeywordFields(s); } @@ -443,7 +443,7 @@ void rascalPostSolver(map[str,Tree] namedTrees, Solver s){ bool isLogicalLoc(loc l) = startsWith(l.scheme, "rascal+"); - + loc rascalCreateLogicalLoc(Define def, str _modelName, PathConfig pcfg){ if(def.idRole in keepInTModelRoles){ if(isLogicalLoc(def.defined)) return def.defined; @@ -453,7 +453,7 @@ loc rascalCreateLogicalLoc(Define def, str _modelName, PathConfig pcfg){ if(def.idRole == moduleId()){ return |<"rascal+">:///|; } else { - return |<"rascal+">:////|; + return |<"rascal+">:////|; } } return def.defined; @@ -467,59 +467,61 @@ RascalCompilerConfig rascalCompilerConfig(PathConfig pcfg, bool warnUnusedFormals = true, bool warnUnusedVariables = true, bool warnUnusedPatternFormals = true, - + bool infoModuleChecked = false, + // Debugging bool verbose = false, // for each compiled module, log module name and compilation time bool logImports = false, bool logWrittenFiles = false, // log location of written files: .constants, .tpl, *.java bool logPathConfig = false, // log PathConfig that is used - + loc reloc = |noreloc:///|, // Currently unused - + bool optimizeVisit = true, // Options for compiler developer bool enableAsserts = true, bool forceCompilationTopModule= false ) = tconfig( rascalTplVersion = rascalTplVersion, - + // Compiler options warnUnused = warnUnused, warnUnusedFormals = warnUnusedFormals, warnUnusedVariables = warnUnusedVariables, warnUnusedPatternFormals = warnUnusedPatternFormals, warnUnusedPatternFormals = warnUnusedPatternFormals, - - verbose = verbose, + infoModuleChecked = infoModuleChecked, + + verbose = verbose, logImports = logImports, logWrittenFiles = logWrittenFiles, logPathConfig = logPathConfig, - - reloc = reloc, - optimizeVisit = optimizeVisit, + + reloc = reloc, + optimizeVisit = optimizeVisit, enableAsserts = enableAsserts, forceCompilationTopModule = forceCompilationTopModule, - + // Basic TypePalConfig options typepalPathConfig = pcfg, - + getMinAType = AType(){ return avoid(); }, getMaxAType = AType(){ return avalue(); }, isSubType = asubtype, getLub = alub, - + isInferrable = rascalIsInferrable, isAcceptableSimple = rascalIsAcceptableSimple, isAcceptableQualified = rascalIsAcceptableQualified, isAcceptablePath = rascalIsAcceptablePath, - + mayOverload = rascalMayOverload, - + getTypeNamesAndRole = rascalGetTypeNamesAndRole, getTypeInTypeFromDefine = rascalGetTypeInTypeFromDefine, getTypeInNamelessType = rascalGetTypeInNamelessType, instantiateTypeParameters = rascalInstantiateTypeParameters, - + preSolver = rascalPreSolver, postSolver = rascalPostSolver, reportUnused = rascalReportUnused, 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 2c6a0473..51b7b58c 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 @@ -86,7 +86,7 @@ set[Message] getAllMessages(ModuleStatus r) ModuleStatus checkStatements(str stmts) { mloc = composeModule(stmts); - return rascalTModelForLocs([mloc], rascalCompilerConfig(pathConfigForTesting()), dummy_compile1); + return rascalTModelForLocs([mloc], rascalCompilerConfig(pathConfigForTesting())[infoModuleChecked=true], dummy_compile1); } bool checkStatementsAndFilter(str stmts, list[str] expected) { @@ -105,7 +105,7 @@ bool checkModuleAndFilter(str moduleText, list[str] expected, bool matchAll = fa return checkModuleAndFilter(mloc, expected, matchAll=matchAll, errorsAllowed=errorsAllowed, pathConfig=pathConfig); } bool checkModuleAndFilter(loc mloc, list[str] expected, bool matchAll = false, bool errorsAllowed = true, PathConfig pathConfig = pathConfigForTesting()) { - msgs = getAllMessages(rascalTModelForLocs([mloc], rascalCompilerConfig(pathConfig), dummy_compile1)); + msgs = getAllMessages(rascalTModelForLocs([mloc], rascalCompilerConfig(pathConfig)[infoModuleChecked=true], dummy_compile1)); if (verbose) { println(msgs); } @@ -133,7 +133,7 @@ bool checkOK(str stmts) { } bool checkModuleOK(loc moduleToCheck, PathConfig pathConfig = pathConfigForTesting()) { - errors = getErrorMessages(rascalTModelForLocs([moduleToCheck], rascalCompilerConfig(pathConfig), dummy_compile1)); + errors = getErrorMessages(rascalTModelForLocs([moduleToCheck], rascalCompilerConfig(pathConfig)[infoModuleChecked=true], dummy_compile1)); if(size(errors) == 0) return true; throw abbrev("");