\t---- \n<}>");
+ // dbgEnter("lookupPathsWide: in scope , role ");;
res = {};
seenParents = {};
solve(res, scope) {
next_path:
- for(loc parent <- ((pathsCache[pathRole] ? {})[scope] - seenParents)){
+ for( <- pathsByPathRole[pathRole] ? {}, parent notin seenParents){
seenParents += parent;
- //if(wdebug) println("\tlookupPathsWide: scope: , trying semantic path to: ");
-
for(loc def <- lookupScopeWide(parent, use)){
switch(isAcceptablePathFun(parent, def, use, pathRole, the_solver)){
case acceptBinding():
@@ -417,22 +441,20 @@ ScopeGraph newScopeGraph(TModel tm, TypePalConfig config){
}
}
}
- //if(wdebug) println("\tlookupPathsWide: in scope , ==\> ");
+ // dbgLeave("lookupPathsWide: in scope , ==\> ");
return res;
}
// Lookup use in given syntactic scope and via all semantic paths
private set[loc] lookupQualWide(loc scope, Use u){
- //if(wdebug) println("\tlookupQualWide: in scope ");
+ // dbgEnter("lookupQualWide: in scope ");
res = lookupScopeWide(scope, u);
- //if(wdebug) println("\tlookupQualWide: in scope , after lookupScopeWide:\n\t--\> <}>");
-
- //if(wdebug) println("\tlookupQualWide: , loop over ");
+
nextPath:
for(PathRole pathRole <- pathRoles){
candidates = lookupPathsWide(scope, u, pathRole);
- //if(wdebug) println("\tlookupQualWide: candidates: ");
+ // dbg("lookupQualWide: candidates: ");
for(loc candidate <- candidates){
switch(isAcceptableSimpleFun(candidate, u, the_solver)){
case acceptBinding():
@@ -444,51 +466,56 @@ ScopeGraph newScopeGraph(TModel tm, TypePalConfig config){
}
}
}
-
+ // dbgLeave("lookupQualWide: in scope =\> ");
return res;
}
// Lookup use in syntactic scope and via all semantic paths,
// recur to syntactic parent until found
private set[loc] lookupNestWide(loc scope, Use u){
- //if(wdebug) println("\tlookupNestWide: in scope ");
+ // dbgEnter("lookupNestWide: in scope ");
res = lookupQualWide(scope, u);
- //if(wdebug) println("\tlookupNestWide: in scope found:\n\t==\> <}>");
- if(!isEmpty(res)) return res; // <<<
- if(tm.scopes[scope] ?){
- if(scope == tm.scopes[scope]) { println("Identical scope in lookupNestWide: "); return res; }
+ if(!isEmpty(res)) {
+ // dbgLeave("lookupNestWide: in scope =\> ");
+ return res; // <<<
+ }
+
+ if(scope in tm.scopes){
+ if(scope == tm.scopes[scope]) {
+ // dbg("Identical scope in lookupNestWide: ");
+ return res;
+ }
parent = tm.scopes[scope];
- //if(wdebug) println("\tlookupNestWide: in scope move up to ");
res += lookupNestWide(parent, u);
}
-
+ // dbgLeave("lookupNestWide: in scope =\> ");
return res;
}
public set[loc] lookupWide(Use u){
// Update current paths and pathRoles
- current_paths = the_solver.getPaths(); //tm.paths;
- if(current_paths != paths){
- paths = current_paths;
- updatePathCache();
- pathRoles = paths.pathRole;
+ current_pathsByPathRole = the_solver.getPathsByPathRole();
+ if(current_pathsByPathRole != pathsByPathRole){
+ pathsByPathRole = current_pathsByPathRole;
+ pathRoles = domain(pathsByPathRole);
}
scope = u.scope;
- //if(wdebug) println("lookupWide: ");
+ // dbg("\nlookupWide: \n");
+ // dbgPaths();
if(!(u has qualifierRoles)){
defs = {def | loc def <- lookupNestWide(scope, u), isAcceptableSimpleFun(def, u, the_solver) == acceptBinding()};
- //if(wdebug) println("lookupWide: returns:\n\t==\> <}>");
+ // dbg("lookupWide: =\> ");
if(isEmpty(defs)) throw NoBinding(); else return defs;
} else {
startScope = scope;
qscopes = {};
for(str id <- u.ids[0..-1]){
- //if(wdebug) println("lookup, search for ");
+ // dbg("lookup, search for ");
qscopes = lookupNestWide(scope, use(id, "", u.occ, scope, u.qualifierRoles));
if(isEmpty(qscopes)) throw NoBinding();
}
@@ -499,32 +526,26 @@ ScopeGraph newScopeGraph(TModel tm, TypePalConfig config){
defs += { def | def <- scopeLookups, isAcceptableQualifiedFun(def, u, the_solver) == acceptBinding()};
}
if(!isEmpty(defs)){
- //if(wdebug) println("lookupWide: returns:\n\t==\> <}>");
+ // dbg("lookupWide: returns:\n\t==\> <}>");
return defs;
}
}
throw NoBinding();
}
- private void updatePathCache() {
- rel[loc, loc] empty_rel = {};
- pathsCache = ();
- for ( <- paths) {
- pathsCache[pr] ? empty_rel += {};
- }
- }
- Paths paths = {};
- map[PathRole, rel[loc,loc]] pathsCache = ();
+ // Paths paths = {};
set[PathRole] pathRoles = {};
+ map[PathRole,rel[loc,loc]] pathsByPathRole = ();
Solver the_solver = dummySolver();
void do_setSolver(Solver s){
the_solver = s;
- paths = the_solver.getPaths();
- updatePathCache();
- pathRoles = paths.pathRole;
+ pathsByPathRole = the_solver.getPathsByPathRole();
+ pathRoles = domain(pathsByPathRole);
+ // paths = the_solver.getPaths();
+ // pathRoles = paths.pathRole;
}
// Initialize the ScopeGraph context
diff --git a/src/analysis/typepal/ISolver.rsc b/src/analysis/typepal/ISolver.rsc
index f3b7aaa0..40992af4 100644
--- a/src/analysis/typepal/ISolver.rsc
+++ b/src/analysis/typepal/ISolver.rsc
@@ -59,10 +59,13 @@ data Solver
/* Global Info */ TypePalConfig () getConfig,
map[loc, AType]() getFacts,
Paths() getPaths,
+ map[PathRole,rel[loc,loc]]() getPathsByPathRole,
set[Define] (str id, loc scope, set[IdRole] idRoles) getDefinitions, // deprecated
set[Define] () getAllDefines,
Define(loc) getDefine,
rel[loc,loc] () getUseDef,
+ bool(loc,loc) isContainedIn,
+ bool(loc,loc) isBefore,
/* Nested Info */ void(str key, value val) push,
value (str key) pop,
diff --git a/src/analysis/typepal/Solver.rsc b/src/analysis/typepal/Solver.rsc
index ea27d5ed..da101e39 100644
--- a/src/analysis/typepal/Solver.rsc
+++ b/src/analysis/typepal/Solver.rsc
@@ -82,6 +82,8 @@ Solver newSolver(map[str,Tree] namedTrees, TModel tm){
map[loc,loc] logical2physical = tm.logical2physical;
+ map[PathRole, rel[loc,loc]] pathsByPathRole = ();
+
void configTypePal(TypePalConfig tc){
normalizeName = tc.normalizeName;
@@ -119,9 +121,17 @@ Solver newSolver(map[str,Tree] namedTrees, TModel tm){
map[loc, AType] solver_getFacts() = facts;
- Paths solver_getPaths() {
- res = tm.paths;
- return res;
+ Paths solver_getPaths() = tm.paths;
+
+ map[PathRole,rel[loc,loc]] solver_getPathsByPathRole() = pathsByPathRole;
+
+ loc getLogicalLoc(Tree t){
+ l = getLoc(t);
+ return l in physical2logical ? physical2logical[l] : l;
+ }
+
+ loc getLogicalLoc(loc l){
+ return l in physical2logical ? physical2logical[l] : l;
}
//value _getStore(str key) = tm.store[key];
@@ -197,9 +207,9 @@ Solver newSolver(map[str,Tree] namedTrees, TModel tm){
list[Message] messages = [];
list[FailMessage] failMessages = [];
- set[ReferPath] referPaths = tm.referPaths;
-
+ map[loc,loc] physical2logical = invertUnique(tm.logical2physical);
+ set[ReferPath] referPaths = tm.referPaths;
// Error reporting
@@ -312,7 +322,7 @@ Solver newSolver(map[str,Tree] namedTrees, TModel tm){
calculators += calcType(defined, atype);
}
} else if(Tree from := tp){
- fromLoc = getLoc(from);
+ fromLoc = getLogicalLoc(from);
if(fromLoc in facts){
facts[defined] = facts[fromLoc];
} else {
@@ -550,11 +560,14 @@ Solver newSolver(map[str,Tree] namedTrees, TModel tm){
AType solver_getType(value v){
try {
switch(v){
- case Tree tree: return instantiate(findType(tree@\loc));
- case tvar(loc l): return facts[l];
+ case Tree tree: return instantiate(findType(getLogicalLoc(tree)));
+ case tvar(loc l): return facts[getLogicalLoc(l)];
case AType atype: return instantiate(atype);
- case loc l: return l in specializedFacts ? specializedFacts[l] : facts[l];
- case defType(value v) : if(AType atype := v) return atype; else if(Tree tree := v) return instantiate(findType(tree@\loc));
+ case loc l: {
+ l = getLogicalLoc(l);
+ return l in specializedFacts ? specializedFacts[l] : facts[l];
+ }
+ case defType(value v) : if(AType atype := v) return atype; else if(Tree tree := v) return instantiate(findType(getLogicalLoc(tree)));
case Define def: return solver_getType(def.defInfo);
case defTypeCall(list[loc] _, AType(Solver s) getAType):
return getAType(thisSolver);
@@ -593,7 +606,7 @@ Solver newSolver(map[str,Tree] namedTrees, TModel tm){
//@memo
AType solver_getTypeInScopeFromName(str name, loc scope, set[IdRole] idRoles){
try {
- return getTypeInScopeFromName0(name, scope, idRoles);
+ return getTypeInScopeFromName0(name, getLogicalLoc(scope), idRoles);
} catch NoSuchKey(value _):
throw TypeUnavailable();
}
@@ -631,7 +644,7 @@ Solver newSolver(map[str,Tree] namedTrees, TModel tm){
//@memo
AType solver_getTypeInScope(Tree occ, loc scope, set[IdRole] idRoles){
try {
- return getTypeInScope0(occ, scope, idRoles);
+ return getTypeInScope0(occ, getLogicalLoc(scope), idRoles);
} catch NoSuchKey(_):
throw TypeUnavailable();
}
@@ -654,7 +667,8 @@ Solver newSolver(map[str,Tree] namedTrees, TModel tm){
}
AType solver_getTypeInType(AType containerType, Tree selector, set[IdRole] idRolesSel, loc scope){
- selectorLoc = getLoc(selector);
+ selectorLoc = getLogicalLoc(getLoc(selector));
+ scope = getLogicalLoc(scope);
selectorOrgName = "";
selectorName = normalizeName(selectorOrgName);
@@ -741,6 +755,7 @@ Solver newSolver(map[str,Tree] namedTrees, TModel tm){
}
rel[str id, AType atype] solver_getAllDefinedInType(AType containerType, loc scope, set[IdRole] idRoles){
+ scope = getLogicalLoc(scope);
= getTypeNamesAndRole(containerType);
if(!isEmpty(containerNames)){
containerName = containerNames[0];
@@ -764,6 +779,7 @@ Solver newSolver(map[str,Tree] namedTrees, TModel tm){
}
set[Define] solver_getDefinitions(str id, loc scope, set[IdRole] idRoles){
+ scope = getLogicalLoc(scope);
try {
foundDefs = scopeGraph.lookup(use(id, id, anonymousOccurrence, scope, idRoles));
if({def} := foundDefs){
@@ -784,11 +800,20 @@ Solver newSolver(map[str,Tree] namedTrees, TModel tm){
set[Define] solver_getAllDefines() = tm.defines;
- Define solver_getDefine(loc l) = definitions[l];
+ Define solver_getDefine(loc l) = definitions[getLogicalLoc(l)];
rel[loc,loc] solver_getUseDef()
= { *{ | loc d <- definedBy[u]} | loc u <- definedBy };
+ bool solver_isContainedIn(loc inner, loc outer)
+ = isContainedIn(inner, outer, logical2physical);
+
+ bool solver_isBefore(loc l, loc r)
+ = isBefore(l, r, logical2physical);
+
+ loc solver_toPhysicalLoc(loc l)
+ = l in logical2physical ? logical2physical[l] : l;
+
// ---- resolvePath -------------------------------------------------------
bool resolvePaths(){
@@ -796,8 +821,7 @@ Solver newSolver(map[str,Tree] namedTrees, TModel tm){
referPaths = tm.referPaths;
for(ReferPath rp <- referPaths){
try {
- if(referToDef(Use _, PathRole _) := rp){
- u = rp.use;
+ if(referToDef(Use u, PathRole _) := rp){
foundDefs = scopeGraph.lookup(u);
if({loc def} := foundDefs){
definedBy[u.occ] = foundDefs;
@@ -838,10 +862,20 @@ Solver newSolver(map[str,Tree] namedTrees, TModel tm){
;/* ignore until end */
}
}
- newPaths = { tup | tup: <- newPaths, u != d };
- tm.paths += newPaths;
+ newPaths = { tup | tup: <- newPaths, u != d };
tm.referPaths = referPaths;
- return !isEmpty(newPaths);
+ newPathFound = !isEmpty(newPaths);
+ if( newPathFound // we found new paths
+ || (!isEmpty(tm.paths) && isEmpty(pathsByPathRole)) // pathsByPathRole not yet initialized
+ ){
+ tm.paths += newPaths;
+ pathsByPathRole = ();
+ for( <- tm.paths){
+ pathsByPathRole[r] ? {} += {};
+ }
+ }
+
+ return newPathFound;
}
// ---- "equal" and "requireEqual" ----------------------------------------
@@ -1134,9 +1168,9 @@ Solver newSolver(map[str,Tree] namedTrees, TModel tm){
void fact(value v, AType atype){
if(Tree t := v) {
- addFact(getLoc(t), atype);
+ addFact(getLogicalLoc(t), atype);
} else if(loc l := v){
- addFact(l, atype);
+ addFact(getLogicalLoc(l), atype);
} else {
throw TypePalUsage("First argument of `fact` should be `Tree` or `loc`, found ``");
}
@@ -1144,9 +1178,9 @@ Solver newSolver(map[str,Tree] namedTrees, TModel tm){
void solver_specializedFact(value v, AType atype){
if(Tree t := v) {
- specializedFacts[getLoc(t)] = atype;
+ specializedFacts[getLogicalLoc(t)] = atype;
} else if(loc l := v){
- specializedFacts[l] = atype;
+ specializedFacts[getLogicalLoc(l)] = atype;
} else {
throw TypePalUsage("First argument of `specializedFact` should be `Tree` or `loc`, found ``");
}
@@ -1155,18 +1189,23 @@ Solver newSolver(map[str,Tree] namedTrees, TModel tm){
bool allDependenciesKnown(set[loc] deps, bool eager){
if(isEmpty(deps)) return true;
if(eager) return all(dep <- deps, dep in facts);
- return all(dep <- deps, dep in facts, solver_isFullyInstantiated(facts[dep]));
+ return all(dep <- deps,
+ dep in facts,
+ solver_isFullyInstantiated(facts[dep]));
}
bool allDependenciesKnown(list[loc] deps, bool eager){
if(isEmpty(deps)) return true;
if(eager) return all(dep <- deps, dep in facts);
- return all(dep <- deps, dep in facts, solver_isFullyInstantiated(facts[dep]));
+ return all(dep <- deps,
+ dep in facts,
+ solver_isFullyInstantiated(facts[dep]));
}
bool solver_isFullyInstantiated(AType atype){
visit(atype){
- case tvar(loc tname): { if(tname notin facts) return false;
+ case tvar(loc tname): { tname = getLogicalLoc(tname);
+ if(tname notin facts) return false;
if(tvar(_) := facts[tname]) return false;
}
case lazyLub(list[AType] atypes):
@@ -1279,7 +1318,7 @@ Solver newSolver(map[str,Tree] namedTrees, TModel tm){
orgId = udef.orgId;
idRole = udef.idRole;
defined = udef.defined;
- if(defined in logical2physical) continue;
+ //if(defined in logical2physical) defined = logical2physical[defined];
u = use(id, orgId, defined, scope, {idRole}); // turn each unused definition into a use and check for double declarations;
try {
@@ -1293,7 +1332,7 @@ Solver newSolver(map[str,Tree] namedTrees, TModel tm){
doubleDefs += foundDefs;
messages += [error("Double declaration of ``", d1,
causes=[info("Other declaration of ``", d2) | d2 <- foundDefs, d2 != d1 ])
- | d1 <- foundDefs, isContainedIn(u.scope, definitions[d1].scope)
+ | d1 <- foundDefs, isContainedIn(u.scope, definitions[d1].scope, logical2physical)
];
}
}
@@ -1541,7 +1580,9 @@ Solver newSolver(map[str,Tree] namedTrees, TModel tm){
calcNoLubs = [calc | calc <- calculators, !(calc is calcLub)];
- for(Calculator clc <- sort(calcNoLubs, bool(Calculator a, Calculator b){ return a.src.length < b.src.length; })){
+ for(Calculator clc <- sort(calcNoLubs, bool(Calculator a, Calculator b){
+ return (a.src in logical2physical ? logical2physical[a.src] : a.src).length
+ < (b.src in logical2physical ? logical2physical[b.src] : b.src).length; })){
src = clc.src;
if(src notin facts, !alreadyReported(messages, src)){
set[loc] cdeps = toSet(dependsOn(clc));
@@ -1597,7 +1638,7 @@ Solver newSolver(map[str,Tree] namedTrees, TModel tm){
ldefines = for(tup: <- tm.defines){
if(defInfo has tree){
- l = getLoc(defInfo.tree);
+ l = getLogicalLoc(defInfo.tree);
if(l in tm.facts){
dt = defType(tm.facts[l]);
tup.defInfo = setKeywordParameters(dt, getKeywordParameters(defInfo));
@@ -1617,11 +1658,12 @@ Solver newSolver(map[str,Tree] namedTrees, TModel tm){
tm.defines = toSet(ldefines);
for(Define def <- tm.defines){
- if(def.defined notin def2uses && def.defined notin doubleDefs && reportUnused(def.defined, tm)){
- messages += warning("Unused ``", def.defined);
+ defdefined = solver_toPhysicalLoc(def.defined);
+ if(defdefined notin def2uses && defdefined notin doubleDefs && reportUnused(defdefined, tm)){
+ messages += warning("Unused ``", defdefined);
}
}
-
+ messages = visit(messages) { case loc l => solver_toPhysicalLoc(l) };
tm.messages = sortMostPrecise(toList(toSet(messages)));
checkAllTypesAvailable(tm);
@@ -1665,11 +1707,13 @@ Solver newSolver(map[str,Tree] namedTrees, TModel tm){
/* Global Info */ solver_getConfig,
solver_getFacts,
solver_getPaths,
-
+ solver_getPathsByPathRole,
solver_getDefinitions,
solver_getAllDefines,
solver_getDefine,
solver_getUseDef,
+ solver_isContainedIn,
+ solver_isBefore,
/* Nested Info */ solver_push,
solver_pop,
diff --git a/src/analysis/typepal/StringSimilarity.rsc b/src/analysis/typepal/StringSimilarity.rsc
index 7e3fd9b5..1283a4e2 100644
--- a/src/analysis/typepal/StringSimilarity.rsc
+++ b/src/analysis/typepal/StringSimilarity.rsc
@@ -12,12 +12,10 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
}
module analysis::typepal::StringSimilarity
-import List;
-import IO;
import Location;
import Set;
import String;
-//import analysis::typepal::TModel;
+import analysis::typepal::TModel;
import analysis::typepal::ConfigurableScopeGraph;
@synopsis{Tryadic minimum function on integers}
@@ -69,10 +67,15 @@ list[str] similarWords(str w, set[str] vocabulary, int maxDistance)
= sort({ | str v <- vocabulary, d := lev(w, v), d <= maxDistance },
bool (WordSim x, WordSim y){ return x.sim < y.sim;}).word;
+// TODO: remove this temporary copy of isContainedIn (needed to break deployment cycle)
+// should reside in Location.rsc
+private bool isContainedIn(loc inner, loc outer, map[loc,loc] m)
+ = isContainedIn(inner in m ? m[inner] : inner, outer in m ? m[outer] : outer);
+
@synopsis{Find in TModel tm, names similar to Use u. Max edit distance comes from TypePal Configuration.}
list[str] similarNames(Use u, TModel tm){
w = getOrgId(u);
idRoles = u.idRoles;
- vocabulary = { d.orgId | d <- tm.defines, d.idRole in idRoles, isContainedIn(u.occ, d.scope) };
+ vocabulary = { d.orgId | d <- tm.defines, d.idRole in idRoles, isContainedIn(u.occ, d.scope, tm.logical2physical) };
return similarWords(w, vocabulary, tm.config.cutoffForNameSimilarity);
}
diff --git a/src/analysis/typepal/Version.rsc b/src/analysis/typepal/Version.rsc
index 3b6219b3..dddacb10 100644
--- a/src/analysis/typepal/Version.rsc
+++ b/src/analysis/typepal/Version.rsc
@@ -14,7 +14,7 @@ module analysis::typepal::Version
import util::SemVer;
-private str currentTplVersion = "2.0.0";
+private str currentTplVersion = "1.1.0";
bool isValidTplVersion(str version){
return equalVersion(version, currentTplVersion);
diff --git a/src/examples/dataModel/Checker.rsc b/src/examples/dataModel/Checker.rsc
index 61e142e3..3ec5e55b 100644
--- a/src/examples/dataModel/Checker.rsc
+++ b/src/examples/dataModel/Checker.rsc
@@ -31,8 +31,6 @@ str prettyAType(setType(AType tp)) = "Set\<\>";
str prettyAType(entityType(str name)) = name;
str prettyAType(fieldType(str name)) = name;
-str prettyAType(functionType(AType from, AType to)) = "fun -\> ";
-
data IdRole
= entityId()
| fieldId()