Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
14133c6
New module LogicalLocs
PaulKlint Jan 5, 2026
60df6ca
Changes to support native logical locations
PaulKlint Jan 5, 2026
097d908
Added support for nicely indented debug output. Some optimizations
PaulKlint Jan 5, 2026
0134912
Added isContainedIn and isBefore to ISolver API
PaulKlint Jan 5, 2026
7229977
Deal with logical locations
PaulKlint Jan 5, 2026
22d2910
Adapted the use of isContainedIn
PaulKlint Jan 5, 2026
2cda513
Removed calls to obsolete function
PaulKlint Jan 5, 2026
254e0b1
[maven-release-plugin] prepare release v0.15.6-RC1
PaulKlint Jan 5, 2026
11fd48e
[maven-release-plugin] prepare for next development iteration
PaulKlint Jan 5, 2026
e2f41aa
[maven-release-plugin] prepare release v0.16.0-RC1
PaulKlint Jan 6, 2026
4a6f504
[maven-release-plugin] prepare for next development iteration
PaulKlint Jan 6, 2026
f890d0a
Solved deployment cycle related to (now obsolete) LogicalLocation module
PaulKlint Jan 7, 2026
9f6726f
[maven-release-plugin] prepare release v0.16.0-RC2
PaulKlint Jan 7, 2026
c0f5e27
[maven-release-plugin] prepare for next development iteration
PaulKlint Jan 7, 2026
7bbf8ff
Convert all locs in messages to physical locs
PaulKlint Jan 8, 2026
aa28fa2
Some optimizations
PaulKlint Jan 14, 2026
8429a71
[maven-release-plugin] prepare release v0.16.0-RC3
PaulKlint Jan 14, 2026
c128b62
[maven-release-plugin] prepare for next development iteration
PaulKlint Jan 14, 2026
1fd5170
Removed unused pattern variable
PaulKlint Jan 14, 2026
840bc39
[maven-release-plugin] prepare release v0.16.0-RC4
PaulKlint Jan 14, 2026
925e084
[maven-release-plugin] prepare for next development iteration
PaulKlint Jan 14, 2026
9a9c8e8
Optimization
PaulKlint Jan 16, 2026
58815ea
[maven-release-plugin] prepare release v0.16.0-RC5
PaulKlint Jan 16, 2026
29b39b7
[maven-release-plugin] prepare for next development iteration
PaulKlint Jan 16, 2026
8f4620c
Removed erroneous (and redundant) line
PaulKlint Jan 20, 2026
0b2d5a3
Reduce number of duplicate messages
PaulKlint Jan 20, 2026
2dcd9ad
Set version number back to 1.1.0 since there are no changes in TModel
PaulKlint Jan 20, 2026
ba151bc
[maven-release-plugin] prepare release v0.16.0
PaulKlint Jan 20, 2026
37ff636
[maven-release-plugin] prepare for next development iteration
PaulKlint Jan 20, 2026
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
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

<groupId>org.rascalmpl</groupId>
<artifactId>typepal</artifactId>
<version>0.15.6-SNAPSHOT</version>
<version>0.16.1-SNAPSHOT</version>
<packaging>jar</packaging>

<properties>
Expand Down
254 changes: 94 additions & 160 deletions src/analysis/typepal/Collector.rsc

Large diffs are not rendered by default.

117 changes: 69 additions & 48 deletions src/analysis/typepal/ConfigurableScopeGraph.rsc
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ extend analysis::typepal::ISolver;

import IO;
import Set;
import Relation;
import Map;
import util::PathConfig;
import String;
Expand Down Expand Up @@ -215,10 +216,34 @@ data ScopeGraph
void (Solver s) setSolver
);

bool wdebug = false;


ScopeGraph newScopeGraph(TModel tm, TypePalConfig config){

// Debug support: prints nicely indented traces of calls.
// It is commented out since it is rather expensive for these
// high-frequency functions

// bool wdebug = false;
// str dbg_indent = "";

// void incr(){ dbg_indent += " "; }
// void decr() { dbg_indent = dbg_indent[..-4]; }

// void dbgEnter(str s) { if(wdebug) { incr(); println("<dbg_indent><s>"); } }
// void dbg(str s) { if(wdebug) println("<dbg_indent><s>"); }
// void dbgLeave(str s) { if(wdebug){ println("<dbg_indent><s>"); decr(); } }

// void dbgPaths(){
// incr();
// for(p <- tm.paths){
// dbg("path: <p.from>");
// dbg(" <p.pathRole>");
// dbg(" <p.to>");
// }
// decr();
// }

/*************************************************************************/
/* At the moment we support "classic" scopes from the Kastens & Waite */
/* article and "wide" scopes as used for Rascal. We still have to settle */
Expand Down Expand Up @@ -375,36 +400,35 @@ ScopeGraph newScopeGraph(TModel tm, TypePalConfig config){
/* lookupWide returns all definitions in the current syntactic scope (or its */
/* parents) and definitions that can be reached in a single step via semantic links */
/************************************************************************************/

//@memo
// Retrieve all bindings for use in given syntactic scope
private set[loc] bindWide(loc scope, str id, set[IdRole] idRoles){
preDefs = (tm.definesMap[scope] ? ())[id] ? {};

if(isEmpty(preDefs) || isEmpty(preDefs<0> & idRoles)) return {};
return preDefs<1>;
idsInScope = (scope in tm.definesMap) ? tm.definesMap[scope] : ();
foundDefs = id in idsInScope ? domainR(idsInScope[id], idRoles)<1> : {};
// dbg("bindWide: <scope>, <id> =\> <foundDefs>");
return foundDefs;
}

// Lookup use in the given syntactic scope
private set[loc] lookupScopeWide(loc scope, Use use){
//if(wdebug) println("\tlookupScopeWide: <use.id> in scope <scope>");

return {def | def <- bindWide(scope, use.id, use.idRoles), isAcceptableSimpleFun(def, use, the_solver) == acceptBinding()};
// dbgEnter("lookupScopeWide: <use.id> in scope <scope>");
res = {def | def <- bindWide(scope, use.id, use.idRoles), isAcceptableSimpleFun(def, use, the_solver) == acceptBinding()};
// dbgLeave("lookupScopeWide: <use.id> in scope <scope> =\> <res>");
return res;
}

//@memo
// Find all (semantics induced, one-level) bindings for use in given syntactic scope via PathRole
private set[loc] lookupPathsWide(loc scope, Use use, PathRole pathRole){
//if(wdebug) println("\tlookupPathsWide: <use.id> in scope <scope>, role <pathRole>\n<for(p <- tm.paths){>\t---- <p>\n<}>");
// dbgEnter("lookupPathsWide: <use.id> in scope <scope>, role <pathRole>");;
res = {};

seenParents = {};
solve(res, scope) {
next_path:
for(loc parent <- ((pathsCache[pathRole] ? {})[scope] - seenParents)){
for(<scope, loc parent> <- pathsByPathRole[pathRole] ? {}, parent notin seenParents){
seenParents += parent;
//if(wdebug) println("\tlookupPathsWide: scope: <scope>, trying semantic path to: <parent>");

for(loc def <- lookupScopeWide(parent, use)){
switch(isAcceptablePathFun(parent, def, use, pathRole, the_solver)){
case acceptBinding():
Expand All @@ -417,22 +441,20 @@ ScopeGraph newScopeGraph(TModel tm, TypePalConfig config){
}
}
}
//if(wdebug) println("\tlookupPathsWide: <use.id> in scope <scope>, <pathRole> ==\> <res>");
// dbgLeave("lookupPathsWide: <use.id> in scope <scope>, <pathRole> ==\> <res>");
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: <u.id> in scope <scope>");
// dbgEnter("lookupQualWide: <u.id> in scope <scope>");

res = lookupScopeWide(scope, u);
//if(wdebug) println("\tlookupQualWide: <u.id> in scope <scope>, after lookupScopeWide:\n<for(r <- res){>\t--\> <r><}>");

//if(wdebug) println("\tlookupQualWide: <res>, loop over <pathRoles(tm)>");

nextPath:
for(PathRole pathRole <- pathRoles){
candidates = lookupPathsWide(scope, u, pathRole);
//if(wdebug) println("\tlookupQualWide: candidates: <candidates>");
// dbg("lookupQualWide: candidates: <candidates>");
for(loc candidate <- candidates){
switch(isAcceptableSimpleFun(candidate, u, the_solver)){
case acceptBinding():
Expand All @@ -444,51 +466,56 @@ ScopeGraph newScopeGraph(TModel tm, TypePalConfig config){
}
}
}

// dbgLeave("lookupQualWide: <u.id> in scope <scope> =\> <res>");
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: <u.id> in scope <scope>");
// dbgEnter("lookupNestWide: <u.id> in scope <scope>");

res = lookupQualWide(scope, u);
//if(wdebug) println("\tlookupNestWide: <u.id> in scope <scope> found:\n<for(r <- res){>\t==\> <r><}>");
if(!isEmpty(res)) return res; // <<<

if(tm.scopes[scope] ?){
if(scope == tm.scopes[scope]) { println("Identical scope in lookupNestWide: <scope>"); return res; }
if(!isEmpty(res)) {
// dbgLeave("lookupNestWide: <u.id> in scope <scope> =\> <res>");
return res; // <<<
}

if(scope in tm.scopes){
if(scope == tm.scopes[scope]) {
// dbg("Identical scope in lookupNestWide: <scope>");
return res;
}
parent = tm.scopes[scope];
//if(wdebug) println("\tlookupNestWide: <u.id> in scope <scope> move up to <parent>");
res += lookupNestWide(parent, u);
}

// dbgLeave("lookupNestWide: <u.id> in scope <scope> =\> <res>");
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: <u>");
// dbg("\nlookupWide: <u>\n");
// dbgPaths();
if(!(u has qualifierRoles)){
defs = {def | loc def <- lookupNestWide(scope, u), isAcceptableSimpleFun(def, u, the_solver) == acceptBinding()};
//if(wdebug) println("lookupWide: <u> returns:\n<for(d <- defs){>\t==\> <d><}>");
// dbg("lookupWide: <u> =\> <defs>");
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 <id>");
// dbg("lookup, search for <id>");
qscopes = lookupNestWide(scope, use(id, "<u.occ>", u.occ, scope, u.qualifierRoles));
if(isEmpty(qscopes)) throw NoBinding();
}
Expand All @@ -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: <u> returns:\n<for(d <- defs){>\t==\> <d><}>");
// dbg("lookupWide: <u> returns:\n<for(d <- defs){>\t==\> <d><}>");
return defs;
}
}
throw NoBinding();
}

private void updatePathCache() {
rel[loc, loc] empty_rel = {};
pathsCache = ();
for (<loc from, PathRole pr, loc to> <- paths) {
pathsCache[pr] ? empty_rel += {<from, to>};
}
}

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
Expand Down
3 changes: 3 additions & 0 deletions src/analysis/typepal/ISolver.rsc
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Loading