Skip to content

Commit

Permalink
Robustness improvements
Browse files Browse the repository at this point in the history
- Incoming PathConfig is validated
- More potentially exception triggering code is now inside a try catch
- Simplification/improvement of several signatures
  • Loading branch information
PaulKlint committed Mar 9, 2024
1 parent 104fe83 commit 99553dd
Show file tree
Hide file tree
Showing 10 changed files with 140 additions and 120 deletions.
2 changes: 1 addition & 1 deletion .classpath
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/test-classes" path="target/generated-test-resources">
<attributes>
<attribute name="test" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
<attribute name="optional" value="true"/>
</attributes>
</classpathentry>
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@
<dependency>
<groupId>org.rascalmpl</groupId>
<artifactId>rascal</artifactId>
<version>0.34.0</version>
<version>0.36.0-RC1</version>
</dependency>
</dependencies>
</project>
134 changes: 94 additions & 40 deletions src/org/rascalmpl/core/library/lang/rascalcore/check/Checker.rsc
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,12 @@ extend lang::rascalcore::check::RascalConfig;

import IO;
import List;
import Map;
import Message;
import Node;
import Relation;
import Set;
import String;

import util::Benchmark;
import util::Reflective;
import util::FileSystem;
import util::Monitor;
Expand Down Expand Up @@ -89,7 +87,7 @@ void rascalPreCollectInitialization(map[str, Tree] namedTrees, Collector c){
// }
//}

// ---- Various check functions ---------------------------------------------
// ---- Various PathConfigs ---------------------------------------------

private int npc = 0;
@synopsis{PathConfig for testing generated modules in |memory://test-modules/| in memory file system.}
Expand All @@ -98,17 +96,19 @@ private int npc = 0;
* generates bin files in the in-memory file system
* depends only on the pre-compiled standard library from the rascal project
}
public PathConfig getDefaultPathConfig() {
public PathConfig getDefaultTestingPathConfig() {
npc += 1;
snpc = "<npc>";
return pathConfig(
srcs = [|memory://test-modules/|],
bin = |memory://test-modules/rascal-core-tests-bin-<snpc>|,
libs = [|lib://rascal/|]
srcs = [ |memory:///test-modules/| ],
bin = |memory:///test-modules/rascal-core-tests-bin-<snpc>|,
generatedSources = |memory:///test-modules/generated-test-sources-<snpc>|,
resources = |memory:///test-modules/generated-test-resources-<snpc>|,
libs = [ |std:///| ]
);
}

@synopsis{for type-checking test modules in the rascal-core project; such as lang::rascalcore::check::Test1}
@synopsis{PathConfig for type-checking test modules in the rascal-core project; such as lang::rascalcore::check::Test1}
@description{
* sources have to be in `|project://rascal-core/src/org/rascalmpl/core/library|`
* binaries will be stored the target folder of the rascal-core project
Expand Down Expand Up @@ -137,14 +137,53 @@ public PathConfig getRascalProjectPathConfig() {
snpc = "<npc>";
return pathConfig(
srcs = [|project://rascal/src/org/rascalmpl/library|],
bin = |memory://test-modules/rascal-lib-bin-<snpc>|,
bin = |memory:///test-modules/rascal-lib-bin-<snpc>|,
libs = []
);
}

CompilerConfig getRascalCompilerConfig()
= cconfig();

list[Message] validatePathConfigForCompiler(PathConfig pcfg, loc mloc){
msgs = [];

if(isEmpty(pcfg.srcs)) msgs += error("PathConfig: `srcs` is empty", mloc);
for(src <- pcfg.srcs){
if(!exists(src)) msgs += error("PathConfig `srcs`: <src> does not exist", src);
}
for(lb <- pcfg.libs){
if(!exists(lb)) msgs += error("PathConfig `libs`: <lb> does not exist", lb);
}

if(!exists(pcfg.bin)) {
try {
mkDirectory(pcfg.resources);
} catch _: {
msgs += error("PathConfig `bin`: <pcfg.bin> does not exist", pcfg.bin);
}
}

if(!exists(pcfg.resources)) {
try {
mkDirectory(pcfg.resources);
} catch _: {
msgs += error("PathConfig `resources`: <pcfg.resources> does not exist", pcfg.resources);
}
}

if(!exists(pcfg.generatedSources))
try {
mkDirectory(pcfg.generatedSources);
} catch _: {
msgs += error("PathConfig `generatedSources`: <pcfg.generatedSources> does not exist", pcfg.generatedSources);
}

return msgs;
}

// ---- Various check functions ---------------------------------------------

// rascalTModelForLocs is the basic work horse

ModuleStatus rascalTModelForLocs(
Expand All @@ -153,14 +192,29 @@ ModuleStatus rascalTModelForLocs(
CompilerConfig compilerConfig,
list[Message](str qualifiedModuleName, lang::rascal::\syntax::Rascal::Module M, ModuleStatus ms, CompilerConfig compilerConfig) codgen
){
bool forceCompilationTopModule = false; /***** for convenience, set to true during development of type checker *****/

pcfg = config.typepalPathConfig;
if(compilerConfig.verbose) iprintln(pcfg);

bool forceCompilationTopModule = false; /***** for convenience, set to true during development of type checker *****/

msgs = validatePathConfigForCompiler(pcfg, mlocs[0]);
if(!isEmpty(msgs)){
throw msgs;
}

ModuleStatus ms = newModuleStatus(pcfg);
topModuleNames = { getModuleName(mloc, pcfg) | mloc <- mlocs };

topModuleNames = {};

for(mloc <- mlocs){
//try {
m = getModuleName(mloc, pcfg);
topModuleNames += {m};
//} catch str e: {
// ms.messages += [ error("Cannot get module name for <mloc>, reason: <e>", mloc) ];
// return ms;
//}
}

try {
ms = getImportAndExtendGraph(topModuleNames, pcfg);

Expand All @@ -179,7 +233,7 @@ ModuleStatus rascalTModelForLocs(

if(isEmpty(sorted)){
ordered = toList(topModuleNames);
for(topModuleName <- topModuleNames){
for(str topModuleName <- topModuleNames){
module2component[topModuleName] = {topModuleName};
}
} else {
Expand Down Expand Up @@ -211,7 +265,7 @@ ModuleStatus rascalTModelForLocs(
}
}
if(!all(m <- component, tpl_uptodate() in ms.status[m] || checked() in ms.status[m])){
<tm, ms> = rascalTModelComponent(component, ms, config=config);
<tm, ms> = rascalTModelComponent(component, ms, config);
moduleScopes += getModuleScopes(tm);
map[str,TModel] tmodels_for_component = ();
map[str,set[str]] m_imports = ();
Expand Down Expand Up @@ -252,6 +306,8 @@ ModuleStatus rascalTModelForLocs(
}
}
tm.messages += msgs;
} else {
tm.messages += error("Cannot get parse tree for module `<m>`", ms.moduleLocs[m]);
}
}
if(ms.messages[m]?){
Expand All @@ -276,6 +332,8 @@ ModuleStatus rascalTModelForLocs(
msgs = codgen(m, pt, ms, compilerConfig);
ms.messages[m] = msgs;
ms.status[m] += {code_generated()};
} else {
ms.messages[m] += error("Cannot get parse tree for module `<m>`", ms.moduleLocs[m]);
}
}
ms = doSaveModule(component, m_imports, m_extends, ms, moduleScopes, compilerConfig);
Expand Down Expand Up @@ -326,23 +384,20 @@ tuple[set[str], ModuleStatus] loadImportsAndExtends(str moduleName, ModuleStatus
return <added, ms>;
}

tuple[TModel, ModuleStatus] rascalTModelComponent(set[str] moduleNames, ModuleStatus ms,
TypePalConfig config=rascalTypePalConfig(ms.pathConfig), bool inline=false){
tuple[TModel, ModuleStatus] rascalTModelComponent(set[str] moduleNames, ModuleStatus ms, TypePalConfig config){

pcfg = ms.pathConfig;
modelName = intercalate(" + ", toList(moduleNames));
map[str, Module] namedTrees = ();
for(nm <- moduleNames){
//if(checked() notin ms.status[nm]){
<success, pt, ms> = getModuleParseTree(nm, ms);
if(success){
namedTrees[nm] = pt;
}
//} else {
// println("*** rascalTModelComponent: <moduleNames>: reusing <nm>");
//}
<success, pt, ms> = getModuleParseTree(nm, ms);
if(success){
namedTrees[nm] = pt;
} else {
ms.messages[nm] += error("Cannot get parse tree for module `<nm>`", ms.moduleLocs[nm]);
}
}

jobStart("RascalCompiler");
jobStep("RascalCompiler", "Type checking <modelName>"); // TODO: monitor
if(config.verbose) println("Type checking <modelName>");

Expand Down Expand Up @@ -378,20 +433,19 @@ ModuleStatus rascalTModelForNames(list[str] moduleNames,
list[Message] (str qualifiedModuleName, lang::rascal::\syntax::Rascal::Module M, ModuleStatus ms, CompilerConfig compilerConfig) codgen){



//try {
pcfg = config.typepalPathConfig;
mlocs = [ getModuleLocation(moduleName, pcfg) | moduleName <- moduleNames ];
return rascalTModelForLocs(mlocs, config, compilerConfig, codgen);
//} catch value e: {
// mloc = |unknown:///|(0,0,<0,0>,<0,0>);
// ms = newModuleStatus();
// for( moduleName <- moduleNames){
// ms.messages[moduleName] = [ error("<e>", mloc) ];
// }
// return ms;
// //return <(moduleName : tmodel()[messages = [ error("<e>", mloc) ]] | moduleName <- moduleNames), (), ()>;
//}
pcfg = config.typepalPathConfig;
mlocs = [];
for(moduleName <- moduleNames){
try {
mlocs += [ getModuleLocation(moduleName, pcfg) ];
} catch value e: {
mloc = |unknown:///|(0,0,<0,0>,<0,0>);
ms = newModuleStatus(pcfg);
ms.messages[moduleName] = [ error("<e>", mloc) ];
return ms;
}
}
return rascalTModelForLocs(mlocs, config, compilerConfig, codgen);
}

// ---- checker functions for IDE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,25 @@ start syntax Modules
// ---- Testing ---------------------------------------------------------------

TModel rascalTModelForTestModules(Tree pt, bool debug=false){
ms = getInlineImportAndExtendGraph(pt, getDefaultPathConfig());
TypePalConfig config=rascalTypePalConfig(getDefaultPathConfig());
if(debug){
ms = getInlineImportAndExtendGraph(pt, getDefaultTestingPathConfig());
TypePalConfig config=rascalTypePalConfig(getDefaultTestingPathConfig());
if(debug){
config = config[logImports = true];
}
}
if(start[Modules] mds := pt){
return rascalTModelComponent( (unescape("<md.header.name>") : md | md <- mds.top.modules ), ms, config=config, inline=true)[1];
return rascalTModelComponent( {unescape("<md.header.name>") | md <- mds.top.modules }, ms, config)[1];
} else if(Modules mds := pt){
return rascalTModelComponent( (unescape("<md.header.name>") : md | md <- mds.modules ), ms, config=config, inline=true)[1];
return rascalTModelComponent( {unescape("<md.header.name>") | md <- mds.modules }, ms, config)[1];
} else
throw "Cannot handle Modules";
}

void testModules(str names...) {
if(isEmpty(names)) names = allTests;
runTests([|project://rascal-core/src/org/rascalmpl/core/library/lang/rascalcore/check/tests/<name>.ttl| | str name <- names], #Modules, rascalTModelForTestModules, verbose=false);
runTests([|project://rascal-core/src/org/rascalmpl/core/library/lang/rascalcore/check/tests-ttl/<name>.ttl| | str name <- names], #Modules, rascalTModelForTestModules, verbose=false);
}

list[str] allTests = ["adt", "adtparam", "alias", "assignment", "datadecl", "exp", "fields", "fundecl",
"imports", "operators", "pat", "scope", "splicepats", "stats"/*,"syntax1", "syntax2", "syntax3"*/];
"imports", "operators", "pat", "scope", "splicepats", "stats"/*,"syntax1", "syntax2", "syntax3"*/];

value main() = testModules();
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,8 @@ import util::Reflective;

void collect(Module current: (Module) `<Header header> <Body body>`, Collector c){

//current = current.top;
mloc = getLoc(current);
mname = prettyPrintName(header.name);
//println("Type checking module <mname>");
checkModuleName(getLoc(current), header.name, c);

tagsMap = getTags(header.tags);
Expand Down Expand Up @@ -68,8 +67,8 @@ void checkModuleName(loc mloc, QualifiedName qualifiedModuleName, Collector c){
if(mloc.scheme != mloc1.scheme || mloc.authority != mloc1.authority || mloc.path != mloc1.path){
c.report(error(qualifiedModuleName, "Module name %v is incompatible with its file location", mname));
}
} catch _: {
c.report(error(qualifiedModuleName, "Module name %v is not consistent with its file location", mname));
} catch str e: {
c.report(error(qualifiedModuleName, e));
}
} else if(isEmpty(pcfgVal)){
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,8 @@ ModuleStatus getImportAndExtendGraph(str qualifiedModuleName, ModuleStatus ms){
ms.strPaths += {<qualifiedModuleName, kind, imp>};
ms = getImportAndExtendGraph(imp, ms);
}
} else {
ms.messages[qualifiedModuleName] += error("Cannot get parse tree for module `<qualifiedModuleName>`", ms.moduleLocs[qualifiedModuleName]);
}

return ms;
Expand Down Expand Up @@ -462,7 +464,6 @@ ModuleStatus doSaveModule(set[str] component, map[str,set[str]] m_imports, map[s
filteredModuleScopes = {getModuleScope(m, moduleScopes, pcfg) | str m <- (qualifiedModuleName + imports), checked() in ms.status[m]} + extendedModuleScopes;

TModel m1 = tmodel();

m1.modelName = qualifiedModuleName;
m1.moduleLocs = (qualifiedModuleName : mscope);

Expand Down Expand Up @@ -561,13 +562,13 @@ ModuleStatus doSaveModule(set[str] component, map[str,set[str]] m_imports, map[s
writeBinaryValueFile(tplLoc, m1);
if(compilerConfig.logWrittenFiles) println("Written: <tplLoc>");
} catch value e: {
throw "Corrupt TPL file <tplLoc> because of <e>";
throw "Cannot write TPL file <tplLoc>, reason: <e>";
}

ms.tmodels[qualifiedModuleName] = m1;

} catch value e: {
ms.tmodels[qualifiedModuleName] = tmodel(modelName=qualifiedModuleName, messages=tm.messages + [error("Could not save .tpl file for `<qualifiedModuleName>`: <e>", |unknown:///|(0,0,<0,0>,<0,0>))]);
ms.tmodels[qualifiedModuleName] = tmodel(modelName=qualifiedModuleName, messages=tm.messages + [error("Could not save .tpl file for `<qualifiedModuleName>`, reason: <e>", |unknown:///|(0,0,<0,0>,<0,0>))]);
return ms;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ void rascalPostSolver(map[str,Tree] namedTrees, Solver s){
}
}

loc rascalCreateLogicalLoc(Define def, str _modelName, PathConfig pcfg){
loc rascalCreateLogicalLoc(Define def, str modelName, PathConfig pcfg){
if(def.idRole in keepInTModelRoles){
moduleName = getModuleName(def.defined, pcfg);
moduleNameSlashed = replaceAll(moduleName, "::", "/");
Expand Down
Loading

0 comments on commit 99553dd

Please sign in to comment.