Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 24 additions & 12 deletions src/analysis/typepal/Collector.rsc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ module analysis::typepal::Collector
Implementation of the ICollector interface; this is the API of TypePal's fact and constraint collector
*/

import DateTime;
import Node;
import Map;
import ParseTree;
Expand Down Expand Up @@ -289,11 +290,14 @@ TModel convertTModel2LogicalLocs(TModel tm, map[str,TModel] tmodels){
return tm;
}

Collector newCollector(str modelName, map[str,Tree] namedTrees, TypePalConfig config){
Collector newCollector(str modelName, map[str,Tree] namedTrees, TypePalConfig config, datetime timestamp = $0000-01-01T00:00:00.000+00:00$){

str normalizeName(str input) {
return config.normalizeName(input);
}
if(!timestamp?){
timestamp = now();
}
loc globalScope = |global-scope:///|;
Defines defines = {};

Expand All @@ -320,7 +324,6 @@ Collector newCollector(str modelName, map[str,Tree] namedTrees, TypePalConfig co
loc currentScope = globalScope;
loc rootScope = globalScope;

for(nm <- namedTrees) scopes[getLoc(namedTrees[nm])] = globalScope;
lrel[loc scope, bool lubScope, map[ScopeRole, value] scopeInfo] scopeStack = [<globalScope, false, (anonymousScope(): false)>];
list[loc] lubScopeStack = [];
loc currentLubScope = globalScope;
Expand All @@ -335,6 +338,7 @@ Collector newCollector(str modelName, map[str,Tree] namedTrees, TypePalConfig co
else if(loc ldef := def) l = ldef;
else throw TypePalUsage("Argument `def` of `define` should be `Tree` or `loc`, found <typeOf(def)>");

info.timestamp = timestamp;
def_tup = <orgId, idRole>;
nname = normalizeName(orgId);

Expand Down Expand Up @@ -414,7 +418,7 @@ Collector newCollector(str modelName, map[str,Tree] namedTrees, TypePalConfig co
if(Tree tdef := def) l = getLoc(tdef);
else if(loc ldef := def) l = ldef;
else throw TypePalUsage("Argument `def` of `defineInScope` should be `Tree` or `loc`, found <typeOf(def)>");

info.timestamp = timestamp;
nname = normalizeName(orgId);
if(info is defTypeLub){
throw TypePalUsage("`defLub` cannot be used in combination with `defineInScope`");
Expand Down Expand Up @@ -1005,10 +1009,10 @@ Collector newCollector(str modelName, map[str,Tree] namedTrees, TypePalConfig co
logical2physical += tm.logical2physical;
messages += tm.messages;

scopes += tm.scopes;
scopes = tm.scopes + scopes;
defines += tm.defines;
facts += tm.facts;
paths += tm.paths;
facts = tm.facts + facts;
paths = tm.paths + paths;
}

map[loc,loc] buildLogical2physical(Defines defines){
Expand All @@ -1018,21 +1022,29 @@ Collector newCollector(str modelName, map[str,Tree] namedTrees, TypePalConfig co
my_physical2logical = invertUnique(logical2physical);
} catch MultipleKey(value key, value _first, value _second):{
where = loc l := key ? l : |unknown:///|;
messages += error("Mapping from physical to logical locations is not unique; remove outdated information and try again", where);
messages += error("Mapping from physical to logical locations is not unique; remove outdated information (e.g. `mvn clean`) and try again", where);
return ();
}
for(Define def <- defines){
logicalLoc = my_physical2logical[def.defined] ? config.createLogicalLoc(def, modelName, config.typepalPathConfig);
if(logicalLoc != def.defined){
if(logicalLoc in my_logical2physical){
if(my_logical2physical[logicalLoc] != def.defined){
if(my_physical2logical[def.defined]?){
// logical loc already created for same physical loc
logicalLoc = my_physical2logical[def.defined];
my_logical2physical[logicalLoc] = def.defined;
} else {
// create a new logical loc, if possible
<found, logicalLoc> = config.createLogicalLoc(def, modelName, config.typepalPathConfig);
if(found){
if(logicalLoc in my_logical2physical, my_logical2physical[logicalLoc] != def.defined, my_logical2physical[logicalLoc].top == def.defined.top){
// report different physical locs in the same file with same logical loc as clone
causes = [ info("Clone of `<def.id>`", my_logical2physical[logicalLoc]),
info("Clone of `<def.id>`", def.defined)
];
messages += error("Remove code clone for <prettyRole(def.idRole)> `<def.id>`", def.defined, causes=causes);
} else {
// add a new logical/physical loc mapping
my_logical2physical[logicalLoc] = def.defined;
}
}
my_logical2physical[logicalLoc] = def.defined;
}
}
return my_logical2physical;
Expand Down
7 changes: 4 additions & 3 deletions src/analysis/typepal/ConfigurableScopeGraph.rsc
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ module analysis::typepal::ConfigurableScopeGraph
*/
extend analysis::typepal::Exception;
extend analysis::typepal::ISolver;
extend analysis::typepal::TModel;

import IO;
import Set;
Expand Down Expand Up @@ -89,8 +90,8 @@ str reduceToURIChars(str s){
return res;
}

loc defaultLogicalLoc(Define def, str _modelName, PathConfig _pcfg){
return def.defined; // return original and don't create logical location
tuple[bool, loc] defaultLogicalLoc(Define def, str _modelName, PathConfig _pcfg){
return <true, def.defined>; // return original and don't create logical location
}

list[str] defaultSimilarNames(Use u, TModel tm) = similarNames(u, tm);
Expand Down Expand Up @@ -153,7 +154,7 @@ data TypePalConfig(

bool(loc def, TModel tm) reportUnused = defaultReportUnused,

loc (Define def, str modelName, PathConfig pcfg) createLogicalLoc = defaultLogicalLoc,
tuple[bool, loc] (Define def, str modelName, PathConfig pcfg) createLogicalLoc = defaultLogicalLoc,

list[str] (Use u, TModel tm) similarNames = defaultSimilarNames,

Expand Down
34 changes: 29 additions & 5 deletions src/analysis/typepal/Solver.rsc
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,6 @@ Solver newSolver(map[str,Tree] namedTrees, TModel tm){

bool(loc def, TModel tm) reportUnused = defaultReportUnused;

map[loc,loc] logical2physical = tm.logical2physical;

void configTypePal(TypePalConfig tc){

normalizeName = tc.normalizeName;
Expand Down Expand Up @@ -803,8 +801,35 @@ Solver newSolver(map[str,Tree] namedTrees, TModel tm){
definedBy[u.occ] = foundDefs;
newPaths += {<u.scope, rp.pathRole, def>};
} else {
causes = [ info("Definition of `<u.id>`", d) | d <- foundDefs ];
messages += error("Name `<u.id>` is ambiguous", u.occ, causes=causes);
set[Define] defs = { definitions[d] | d <- foundDefs };
set[str] md5s = { d.defInfo.md5 | d <- defs };
if(size(md5s) == 1){
latestDef = getOneFrom(defs);
for(Define d <- defs){
if(d.defInfo.timestamp?){
if(latestDef.defInfo.timestamp?){
if(d.defInfo.timestamp == latestDef.defInfo.timestamp){
causes = [ info("Definition of `<u.id>`", fd) | loc fd <- foundDefs ];
messages += error("Name `<u.id>` is ambiguous", u.occ, causes=causes);
} else
if(d.defInfo.timestamp > latestDef.defInfo.timestamp){
latestDef = d;
}
} else {
latestDef = d;
}
}
}
definedBy[u.occ] = {latestDef.defined};
newPaths += {<u.scope, rp.pathRole, latestDef.defined>};
} else {
println("Ambiguous <u.id>"); iprintln(foundDefs);
for(d <- foundDefs){
println("<definitions[d]>, <definitions[d].defInfo.md5>");
}
causes = [ info("Definition of `<u.id>`", d) | d <- foundDefs ];
messages += error("Name `<u.id>` is ambiguous", u.occ, causes=causes);
}
}
referPaths -= {rp};
} else {
Expand Down Expand Up @@ -1279,7 +1304,6 @@ Solver newSolver(map[str,Tree] namedTrees, TModel tm){
orgId = udef.orgId;
idRole = udef.idRole;
defined = udef.defined;
if(defined in logical2physical) continue;

u = use(id, orgId, defined, scope, {idRole}); // turn each unused definition into a use and check for double declarations;
try {
Expand Down
5 changes: 3 additions & 2 deletions src/analysis/typepal/TModel.rsc
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,10 @@ data ReferPath

alias ReferPaths = set[ReferPath];

// Language-specific auxiliary associated with a name definition
// Language-specific auxiliary information associated with a name definition
// Extended in a language-specific module

data DefInfo(str md5 = "");
data DefInfo(datetime timestamp = $0000-01-01T00:00:00.000+00:00$);
data DefInfo
= noDefInfo()
;
Expand Down