Skip to content
This repository was archived by the owner on Mar 5, 2025. It is now read-only.

Commit 2a0b66d

Browse files
committed
Moved getModuleName and friends from util::Reflective to CheckerCommon
1 parent d97dbbc commit 2a0b66d

File tree

1 file changed

+244
-0
lines changed

1 file changed

+244
-0
lines changed

src/org/rascalmpl/core/library/lang/rascalcore/check/CheckerCommon.rsc

Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,250 @@ import util::Reflective;
3131
import lang::rascalcore::compile::util::Names; // TODO: refactor, this is an undesired dependency on compile
3232
import lang::rascalcore::compile::CompileTimeError;
3333

34+
35+
str makeFileName(str qualifiedModuleName, str extension = "rsc") {
36+
str qnameSlashes = replaceAll(qualifiedModuleName, "::", "/");
37+
int n = findLast(qnameSlashes, "/");
38+
str prefix = extension == "rsc" ? "" : "$";
39+
str package = extension == "rsc" ? "" : "rascal/";
40+
qnameSlashes = n < 0 ? "<prefix>" + qnameSlashes : qnameSlashes[0..n] + "/<prefix>" + qnameSlashes[n+1..];
41+
return "<package><qnameSlashes><isEmpty(extension) ? "" : ".<extension>">";
42+
}
43+
44+
loc getSearchPathLoc(str filePath, PathConfig pcfg){
45+
for(loc dir <- pcfg.srcs + pcfg.libs){
46+
fileLoc = dir + filePath;
47+
if(exists(fileLoc)){
48+
//println("getModuleLocation <qualifiedModuleName> =\> <fileLoc>");
49+
return fileLoc;
50+
}
51+
}
52+
throw "Module with path <filePath> not found";
53+
}
54+
55+
@synopsis{Get the location of a named module, search for `src` in srcs and `tpl` in libs}
56+
loc getModuleLocation(str qualifiedModuleName, PathConfig pcfg){
57+
fileName = makeFileName(qualifiedModuleName, extension="rsc");
58+
for(loc dir <- pcfg.srcs){
59+
fileLoc = dir + fileName;
60+
if(exists(fileLoc)){
61+
return fileLoc;
62+
}
63+
}
64+
fileName = makeFileName(qualifiedModuleName, extension="tpl");
65+
for(loc dir <- pcfg.libs){
66+
fileLoc = dir + fileName;
67+
68+
if(exists(fileLoc)){
69+
return fileLoc;
70+
}
71+
}
72+
throw "Module `<qualifiedModuleName>` not found;\n<pcfg>";
73+
}
74+
75+
tuple[str,str] splitFileExtension(str path){
76+
int n = findLast(path, ".");
77+
if(n < 0) return <path, "">;
78+
return <path[0 .. n], path[n+1 .. ]>;
79+
}
80+
81+
@synopsis{Determine length of common suffix of list of strings}
82+
int commonSuffix(list[str] dir, list[str] m)
83+
= commonPrefix(reverse(dir), reverse(m));
84+
85+
@synopsis{Determine length of common prefix of list of strings}
86+
int commonPrefix(list[str] rdir, list[str] rm){
87+
for(int i <- index(rm)){
88+
if(i >= size(rdir)){
89+
return i;
90+
} else if(rdir[i] != rm[i]){
91+
return i;
92+
} else {
93+
continue;
94+
}
95+
}
96+
return size(rm);
97+
}
98+
99+
@synopsis{Find the module name corresponding to a given module location via its (src or tpl) location}
100+
str getModuleName(loc moduleLoc, PathConfig pcfg){
101+
modulePath = moduleLoc.path;
102+
103+
rscFile = endsWith(modulePath, "rsc");
104+
tplFile = endsWith(modulePath, "tpl");
105+
106+
if(!( rscFile || tplFile )){
107+
throw "Not a Rascal .src or .tpl file: <moduleLoc>";
108+
}
109+
110+
if(contains(modulePath, "Content")){
111+
println("Content");
112+
}
113+
114+
// Find matching .rsc file in source directories
115+
if(rscFile){
116+
for(loc dir <- pcfg.srcs){
117+
if(moduleLoc.authority == dir.authority && startsWith(modulePath, dir.path)) {
118+
moduleName = replaceFirst(modulePath, dir.path, "");
119+
<moduleName, ext> = splitFileExtension(moduleName);
120+
if(moduleName[0] == "/"){
121+
moduleName = moduleName[1..];
122+
}
123+
moduleName = replaceAll(moduleName, "/", "::");
124+
return moduleName;
125+
}
126+
}
127+
}
128+
129+
// Find longest matching .tpl file in library directories
130+
131+
<modulePathNoExt, ext> = splitFileExtension(modulePath);
132+
while(modulePathNoExt[0] == "/"){
133+
modulePathNoExt = modulePathNoExt[1..];
134+
}
135+
136+
modulePathAsList = split("/", modulePathNoExt);
137+
if(tplFile){
138+
lastName = modulePathAsList[-1];
139+
if(lastName[0] == "$"){
140+
modulePathAsList = [*modulePathAsList[..-1],lastName[1..]];
141+
}
142+
}
143+
if(modulePathAsList[0] == "rascal"){
144+
modulePathAsList = modulePathAsList[1..];
145+
}
146+
modulePathReversed = reverse(modulePathAsList);
147+
148+
int longestSuffix = 0;
149+
for(loc dir <- pcfg.libs){
150+
dir = dir + "rascal";
151+
dpath = dir.path;
152+
153+
while(dpath[0] == "/"){
154+
dpath = dpath[1..];
155+
}
156+
157+
for(loc file <- find(dir, "tpl")){
158+
candidate = replaceFirst(file.path, dpath, "");
159+
<candidate, ext> = splitFileExtension(candidate);
160+
161+
if(contains(candidate, "Content")){
162+
println("Content");
163+
}
164+
while(candidate[0] == "/"){
165+
candidate = candidate[1..];
166+
}
167+
168+
candidateAsList = split("/", candidate);
169+
lastName = candidateAsList[-1];
170+
if(lastName[0] == "$"){
171+
candidateAsList = [*candidateAsList[..-1],lastName[1..]];
172+
}
173+
// println("cand: <candidateAsList>, modpath: <modulePathAsList>");
174+
n = commonPrefix(reverse(candidateAsList), modulePathReversed);
175+
176+
if(n > longestSuffix){
177+
longestSuffix = n;
178+
}
179+
}
180+
}
181+
182+
if(longestSuffix > 0){
183+
lastName = modulePathAsList[-1];
184+
if(lastName[0] == "$"){
185+
modulePathAsList = [*modulePathAsList[..-1],lastName[1..]];
186+
}
187+
return intercalate("::", modulePathAsList[size(modulePathAsList) - longestSuffix .. ]);
188+
}
189+
throw "No module name found for <moduleLoc>;\nsrcs=<pcfg.srcs>;\nlibs=<pcfg.libs>";
190+
}
191+
192+
@synopsis{Derive a location from a given module name for reading}
193+
@description{
194+
Given a module name, a file name extension, and a PathConfig,
195+
a path name is constructed from the module name + extension.
196+
197+
If a file F with this path exists in one of the directories in the PathConfig,
198+
then the pair <true, F> is returned. Otherwise <false, some error location> is returned.
199+
200+
For a source extension (typically "rsc" or "mu" but this can be configured) srcs is searched, otherwise binPath + libs.
201+
}
202+
@examples{
203+
```rascal-shell
204+
import util::Reflective;
205+
getDerivedReadLoc("List", "rsc", pathConfig());
206+
getDerivedReadLoc("experiments::Compiler::Compile", "rvm", pathConfig());
207+
getDerivedReadLoc("experiments::Compiler::muRascal2RVM::Library", "mu", pathConfig());
208+
```
209+
}
210+
@benefits{
211+
This function is useful for type checking and compilation tasks, when derived information related to source modules has to be read
212+
from locations in different, configurable, directories.
213+
}
214+
215+
tuple[bool, loc] getDerivedReadLoc(str qualifiedModuleName, str extension, PathConfig pcfg, set[str] srcExtensions = {"rsc", "mu"}, str rootDir = ""){
216+
fileName = makeFileName(qualifiedModuleName, extension=extension);
217+
//println("getDerivedReadLoc: <fileName>");
218+
219+
if(extension in srcExtensions){
220+
for(loc dir <- pcfg.srcs){ // In a source directory?
221+
fileLoc = dir + rootDir + fileName;
222+
if(exists(fileLoc)){
223+
//println("getDerivedReadLoc: <qualifiedModuleName>, <extension> =\> <fileLoc");
224+
return <true, fileLoc>;
225+
}
226+
}
227+
} else {
228+
for(loc dir <- pcfg.bin + pcfg.libs){ // In a bin or lib directory?
229+
230+
fileLoc = dir + rootDir + fileName;
231+
if(exists(fileLoc)){
232+
//println("getDerivedReadLoc: <qualifiedModuleName>, <extension> =\> <fileLoc>");
233+
return <true, fileLoc>;
234+
}
235+
}
236+
}
237+
//println("getDerivedReadLoc: <qualifiedModuleName>, <extension> =\> |error:///|");
238+
return <false, |error:///|>;
239+
}
240+
241+
242+
@synopsis{Derive a location from a given module name for writing}
243+
@description{
244+
Given a module name, a file name extension, and a PathConfig,
245+
a path name is constructed from the module name + extension.
246+
247+
For source modules, a writable location cannot be derived.
248+
For other modules, a location for this path in bin will be returned.
249+
}
250+
@examples{
251+
```rascal-shell
252+
import util::Reflective;
253+
getDerivedWriteLoc("List", "rvm", pathConfig());
254+
getDerivedWriteLoc("experiments::Compiler::Compile", "rvm", pathConfig());
255+
```
256+
257+
```rascal-shell,error
258+
getDerivedWriteLoc("experiments::Compiler::muRascal2RVM::Library", "rsc", pathConfig());
259+
```
260+
}
261+
@benefits{
262+
This function is useful for type checking and compilation tasks, when derived information related to source modules has to be written
263+
to locations in separate, configurable, directories.
264+
}
265+
loc getDerivedWriteLoc(str qualifiedModuleName, str extension, PathConfig pcfg, set[str] srcExtensions = {"rsc", "mu"}, str rootDir = ""){
266+
if(extension in srcExtensions){
267+
throw "Cannot derive writable location for module <qualifiedModuleName> with extension <extension>";
268+
}
269+
fileNameSrc = makeFileName(qualifiedModuleName);
270+
fileNameBin = makeFileName(qualifiedModuleName, extension=extension);
271+
272+
bin = pcfg.bin;
273+
fileLocBin = bin + rootDir + fileNameBin;
274+
//println("getDerivedWriteLoc: <qualifiedModuleName>, <extension> =\> <fileLocBin>");
275+
return fileLocBin;
276+
}
277+
34278
void checkSupportedByParserGenerator(Tree t, Collector c){
35279
c.require("implemented by parsergenerator", t, [t], void(Solver s){
36280
tp = s.getType(t);

0 commit comments

Comments
 (0)