From 2aa1a6f2ed9e0bcd34fb7a220359a277783e6022 Mon Sep 17 00:00:00 2001 From: Sung-Shik Jongmans Date: Fri, 29 May 2026 11:05:02 +0200 Subject: [PATCH 01/12] Remove trailing whitespace from example program in the `modfun` tests to make it grammatical --- src/examples/modfun/A.mfun | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/examples/modfun/A.mfun b/src/examples/modfun/A.mfun index 144382a..6085491 100644 --- a/src/examples/modfun/A.mfun +++ b/src/examples/modfun/A.mfun @@ -2,4 +2,4 @@ module A { import B; def a : int -> int = fun i : int { 5 + i }; def a : int -> int = fun i : int { 6 + i }; -} +} \ No newline at end of file From 1bae24307745974f640de9a034c58a5804a2f3cc Mon Sep 17 00:00:00 2001 From: Sung-Shik Jongmans Date: Fri, 29 May 2026 12:45:08 +0200 Subject: [PATCH 02/12] Update `checkAllTypesAvailable` to assert the overall validity (instead of only type availability) of all `Define` values in a TModel --- .../typepal/ConfigurableScopeGraph.rsc | 2 ++ src/analysis/typepal/Solver.rsc | 18 ++++++++++++------ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/analysis/typepal/ConfigurableScopeGraph.rsc b/src/analysis/typepal/ConfigurableScopeGraph.rsc index 5e61dc8..8e15b63 100644 --- a/src/analysis/typepal/ConfigurableScopeGraph.rsc +++ b/src/analysis/typepal/ConfigurableScopeGraph.rsc @@ -108,6 +108,8 @@ data TypePalConfig( ); data TypePalConfig( + bool assertValidDefines = true, + bool verbose = false, PathConfig typepalPathConfig = pathConfig(), diff --git a/src/analysis/typepal/Solver.rsc b/src/analysis/typepal/Solver.rsc index dd5a46b..2e4d60f 100644 --- a/src/analysis/typepal/Solver.rsc +++ b/src/analysis/typepal/Solver.rsc @@ -32,11 +32,17 @@ import Type; import analysis::typepal::StringSimilarity; import util::IDEServices; -void checkAllTypesAvailable(TModel tm){ - for(tup: <- tm.defines){ - if(!(defInfo has atype)){ - throw "checkTypesAvailable: , "; - } +void assertValidDefines(TModel tm){ + if (!tm.config.assertValidDefines) return; + for(d <- tm.defines){ + + assert isContainedIn(d.defined, d.scope) || "global-scope" == d.scope.scheme : + "Expected: For each `d` in `tm.defines`, `d.defined` is contained in `d.scope`. " + + "Actual: For `` in TModel ``, `` (`d.defined`) isn\'t contained in `` (`d.scope`)."; + + assert d.defInfo has atype : + "Expected: For each `d` in `tm.defines`, field `d.defInfo` has field `atype`. " + + "Actual: For `` in TModel ``, `` (`d.defInfo`) doesn\'t have that field."; } } @@ -1765,7 +1771,7 @@ Solver newSolver(map[str,Tree] namedTrees, TModel tm){ messages = visit(messages) { case loc l => solver_toPhysicalLoc(l) }; tm.messages = sortMostPrecise(toList(toSet(messages))); - checkAllTypesAvailable(tm); + assertValidDefines(tm); return tm; } From d3a5189c40ef67da173ddfdc85aef8ba913566ce Mon Sep 17 00:00:00 2001 From: Sung-Shik Jongmans Date: Fri, 29 May 2026 15:40:52 +0200 Subject: [PATCH 03/12] Add function to assert the validity of all pairs in the `useDef` relation of a TModel --- .../typepal/ConfigurableScopeGraph.rsc | 1 + src/analysis/typepal/Solver.rsc | 44 +++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/src/analysis/typepal/ConfigurableScopeGraph.rsc b/src/analysis/typepal/ConfigurableScopeGraph.rsc index 8e15b63..26b4fb0 100644 --- a/src/analysis/typepal/ConfigurableScopeGraph.rsc +++ b/src/analysis/typepal/ConfigurableScopeGraph.rsc @@ -109,6 +109,7 @@ data TypePalConfig( data TypePalConfig( bool assertValidDefines = true, + bool assertValidUseDef = false, bool verbose = false, diff --git a/src/analysis/typepal/Solver.rsc b/src/analysis/typepal/Solver.rsc index 2e4d60f..c3de447 100644 --- a/src/analysis/typepal/Solver.rsc +++ b/src/analysis/typepal/Solver.rsc @@ -46,6 +46,49 @@ void assertValidDefines(TModel tm){ } } +void assertValidUseDef(TModel tm, Solver solver) { + if (!tm.config.assertValidUseDef) return; + scopeGraph = newScopeGraph(tm, tm.config); + scopeGraph.setSolver(solver); + + useLocs = sort([u.occ | u <- tm.uses], isLexicallyLess); + defLocs = sort([d.defined | d <- tm.defines], isLexicallyLess); + for (pair: <- tm.useDef) { + + assert useLoc in useLocs : + "Expected: For each `\` in `tm.useDef`, a corresponding `Use` exists in `tm.uses` for `useLoc`. " + + "Actual: For `` in TModel ``, a corresponding `Use` value doesn\'t exist for `` (`useLoc`), but it does for ``."; + + assert defLoc in defLocs : + "Expected: For each `\` in `tm.useDef`, a corresponding `Define` exists in `tm.defines` for `defLoc`. " + + "Actual: For `` in TModel ``, a corresponding `Define` value doesn\'t exist for `` (`defLoc`), but it does for ``."; + + usesAtUseLoc = [u | u <- tm.uses, useLoc == u.occ]; + defsAtDefLoc = [d | d <- tm.defines, defLoc == d.defined]; + reachable = (u: scopeGraph.lookup(u) | u <- usesAtUseLoc); + if (u <- usesAtUseLoc, d <- defsAtDefLoc, d.defined in reachable[u]) { + + assert u.id == d.id : + "Expected: For each pair in `tm.useDef`, the corresponding `Use` `u` and `Define` `d` have equal `id` fields. " + + "Actual: For `` in TModel ``, `` (`u.id`) isn\'t equal to `` (`d.id`)."; + + assert u.orgId == d.orgId : + "Expected: For each pair in `tm.useDef`, the corresponding `Use` `u` and `Define` `d` have equal `orgId` fields. " + + "Actual: For `` in TModel ``, `` (`u.orgId`) isn\'t equal to `` (`d.orgId`)."; + + assert d.idRole in u.idRoles : + "Expected: For each pair in `tm.useDef`, the corresponding `Use` `u` and `Define` `d` have compatible roles. " + + "Actual: For `` in TModel ``, `` (`u.idRoles`) doesn\'t contain `` (`d.idRole`)."; + + } else { + + assert false : + "Expected: For each `\` in `tm.useDef`, `defLoc` is reachable from `useLoc` in the scope graph. " + + "Actual: For `` in TModel ``, `` (`defLoc`) isn\'t reachable from `` (`useLoc`), but `` are."; + } + } +} + // Implementation of the Solver data type: a collection of call backs Solver newSolver(Tree pt, TModel tm){ @@ -1772,6 +1815,7 @@ Solver newSolver(map[str,Tree] namedTrees, TModel tm){ tm.messages = sortMostPrecise(toList(toSet(messages))); assertValidDefines(tm); + assertValidUseDef(tm, thisSolver); return tm; } From f6b0741d41601dcba12fe33045767216cfc8563c Mon Sep 17 00:00:00 2001 From: Sung-Shik Jongmans Date: Fri, 29 May 2026 15:41:30 +0200 Subject: [PATCH 04/12] Update tests to enable `assertValidUseDef` --- src/analysis/typepal/TestFramework.rsc | 9 +++++++-- src/examples/aliases/Test.rsc | 5 ++++- src/examples/calc/Test.rsc | 2 +- src/examples/dataModel/Test.rsc | 2 +- src/examples/evenOdd/Test.rsc | 2 +- src/examples/fixedMembers/Test.rsc | 2 +- src/examples/fun/Test.rsc | 5 ++++- src/examples/fwjava/Test.rsc | 6 +++++- src/examples/modfun/Test.rsc | 6 +++++- src/examples/pascal/Test.rsc | 4 ++-- src/examples/pico/Test.rsc | 6 ++++-- src/examples/ql/Test.rsc | 9 +++++++-- src/examples/smallOO/Test.rsc | 5 ++++- src/examples/splitstruct/Test.rsc | 2 +- src/examples/staticFields/Test.rsc | 2 +- src/examples/struct/Test.rsc | 2 +- src/examples/structParameters/Test.rsc | 4 +++- src/examples/untypedFun/Test.rsc | 5 ++++- 18 files changed, 56 insertions(+), 22 deletions(-) diff --git a/src/analysis/typepal/TestFramework.rsc b/src/analysis/typepal/TestFramework.rsc index 6494157..6fd700e 100644 --- a/src/analysis/typepal/TestFramework.rsc +++ b/src/analysis/typepal/TestFramework.rsc @@ -100,11 +100,13 @@ bool runTests(list[loc] suites, type[&T<:Tree] begin, TModel(Tree t) getModel, b continue; } ntests += 1; + newTreeSrc = |unknown:///|; try { newTree = visit(parse(begin, "")) { case Tree t => t[src = relocate(t.src, ti.tokens.src)] when t has src }; + newTreeSrc = newTree.src; model = getModel(newTree); list[Message] messages = model.messages; if(verbose) println("runTests: "); @@ -118,7 +120,9 @@ bool runTests(list[loc] suites, type[&T<:Tree] begin, TModel(Tree t) getModel, b failedTests[<"", suite>] = [error("Parse error", relocate(l, ti.tokens.src))]; } catch Ambiguity(loc l, nt, inp): { failedTests[<"", suite>] = [error("Ambiguity ( on ``)", (l.offset?) ? relocate(l, ti.tokens.src) : l)]; - } + } catch AssertionFailed(str s): { + failedTests[<"", suite>] = [error("Assertion failed: ", newTreeSrc)]; + } } testTime += (cpuTime() - startTests); @@ -141,9 +145,10 @@ bool runTests(list[loc] suites, type[&T<:Tree] begin, TModel(Tree t) getModel, b } } } + ok = false; } println("Parse time: msec; Test time: msec"); - return ok; + return ok && isEmpty(failedTests); } lrel[&T<:Tree, set[str]] extractTests(list[loc] suites, type[&T<:Tree] begin) { diff --git a/src/examples/aliases/Test.rsc b/src/examples/aliases/Test.rsc index 4821deb..ce3ab19 100644 --- a/src/examples/aliases/Test.rsc +++ b/src/examples/aliases/Test.rsc @@ -21,7 +21,10 @@ import ParseTree; // ---- Testing --------------------------------------------------------------- TModel aliasesTModelForTree(Tree pt){ - return collectAndSolve(pt, config = aliasesConfig(), modelName = "alias"); + // Enable `assertValidUseDef` only when the program under test **isn't** + // `CircularAlias1` (which is expected to have an invalid `useDef`). + bool assertValidUseDef = md5Hash(pt) != "6e3b63e2945eb4d075ff79f0fd2039eb"; // Hash of program `CircularAlias1` + return collectAndSolve(pt, config = aliasesConfig()[assertValidUseDef = assertValidUseDef], modelName = "alias"); } TModel aliasesTModelFromName(str mname){ diff --git a/src/examples/calc/Test.rsc b/src/examples/calc/Test.rsc index c6c4396..4c7fa94 100644 --- a/src/examples/calc/Test.rsc +++ b/src/examples/calc/Test.rsc @@ -21,7 +21,7 @@ import ParseTree; // In order to parse tests // ---- Testing --------------------------------------------------------------- TModel calcTModelForTree(Tree pt){ - return collectAndSolve(pt, modelName = "calc"); + return collectAndSolve(pt, modelName = "calc", config = tconfig()[assertValidUseDef = true]); } TModel calcTModelFromStr(str text){ diff --git a/src/examples/dataModel/Test.rsc b/src/examples/dataModel/Test.rsc index a002a76..6a08c94 100644 --- a/src/examples/dataModel/Test.rsc +++ b/src/examples/dataModel/Test.rsc @@ -17,7 +17,7 @@ extend examples::dataModel::Checker; extend analysis::typepal::TestFramework; TModel dmTModelForTree(Tree pt){ - return collectAndSolve(pt, config = dmConfig()); + return collectAndSolve(pt, config = dmConfig()[assertValidUseDef = true]); } TModel dmTModelFromName(str mname){ diff --git a/src/examples/evenOdd/Test.rsc b/src/examples/evenOdd/Test.rsc index 9803c30..8e4add5 100644 --- a/src/examples/evenOdd/Test.rsc +++ b/src/examples/evenOdd/Test.rsc @@ -23,7 +23,7 @@ import ParseTree; // In order to parse tests TModel evenOddTModelForTree(Tree pt){ if(pt has top) pt = pt.top; - c = newCollector("even-odd", pt, tconfig()); + c = newCollector("even-odd", pt, tconfig()[assertValidUseDef = true]); collect(pt, c); return newSolver(pt, c.run()).run(); } diff --git a/src/examples/fixedMembers/Test.rsc b/src/examples/fixedMembers/Test.rsc index 6cd8354..8813deb 100644 --- a/src/examples/fixedMembers/Test.rsc +++ b/src/examples/fixedMembers/Test.rsc @@ -22,7 +22,7 @@ import ParseTree; // ---- Testing --------------------------------------------------------------- TModel fixedMembersTModelForTree(Tree pt){ - return collectAndSolve(pt, config = fixedMembersConfig(), modelName="fixed-members"); + return collectAndSolve(pt, config = fixedMembersConfig()[assertValidUseDef = true], modelName = "fixed-members"); } TModel fixedMembersTModelFromName(str mname){ diff --git a/src/examples/fun/Test.rsc b/src/examples/fun/Test.rsc index bb8978a..046717f 100644 --- a/src/examples/fun/Test.rsc +++ b/src/examples/fun/Test.rsc @@ -27,7 +27,7 @@ TModel funTModel(str name){ } TModel funTModelForTree(Tree pt){ - return collectAndSolve(pt, modelName = "fun"); + return collectAndSolve(pt, modelName = "fun", config = tconfig()[assertValidUseDef = true]); } TModel funTModelFromStr(str text){ @@ -43,4 +43,7 @@ list[Message] funCheck(str name) { test bool funTests() = runTests([|project://typepal/src/examples/fun/tests.ttl|], #Fun, funTModelForTree, runName="Fun"); +test bool funTModelTestBig() = [] := funTModel("big").messages; +test bool funTModelTestTmp() = [] := funTModel("tmp").messages; + value main() = funTests(); diff --git a/src/examples/fwjava/Test.rsc b/src/examples/fwjava/Test.rsc index 741791e..df82425 100644 --- a/src/examples/fwjava/Test.rsc +++ b/src/examples/fwjava/Test.rsc @@ -23,7 +23,7 @@ import ParseTree; TModel fwjTModelForTree(Tree pt){ if(pt has top) pt = pt.top; - c = newCollector("fwj", pt, fwjConfig()); + c = newCollector("fwj", pt, fwjConfig()[assertValidUseDef = true]); fwjPreCollectInitialization(pt, c); collect(pt, c); return newSolver(pt, c.run()).run(); @@ -41,4 +41,8 @@ test bool fwjTests() { runName = "FwJava"); } +test bool fwjTModelTestCpt() = [] := fwjTModelFromName("cpt", false).messages; +test bool fwjTModelTestPair() = [] := fwjTModelFromName("pair", false).messages; +test bool fwjTModelTestTmp() = [_, _] := fwjTModelFromName("tmp", false).messages; // Two errors expected + value main() = fwjTests(); \ No newline at end of file diff --git a/src/examples/modfun/Test.rsc b/src/examples/modfun/Test.rsc index 3bce6cd..2e8600e 100644 --- a/src/examples/modfun/Test.rsc +++ b/src/examples/modfun/Test.rsc @@ -28,7 +28,7 @@ TModel modfunTModel(str name){ } TModel modfunTModelForTree(Tree pt){ - return collectAndSolve(pt, modelName="modfun"); + return collectAndSolve(pt, modelName="modfun", config=tconfig()[assertValidUseDef=true]); } TModel modfunTModelFromStr(str text){ @@ -47,5 +47,9 @@ test bool modfunTests() modfunTModelForTree, runName = "ModFun"); +test bool modfunTModelTestA() = [_, _, _] := modfunTModel("A").messages; // Three errors expected +test bool modfunTModelTestB() = [_, _] := modfunTModel("B").messages; // Two errors expected +test bool modfunTModelTestTmp() = [] := modfunTModel("tmp").messages; + value main() = modfunTests(); \ No newline at end of file diff --git a/src/examples/pascal/Test.rsc b/src/examples/pascal/Test.rsc index 6828589..332b1c3 100644 --- a/src/examples/pascal/Test.rsc +++ b/src/examples/pascal/Test.rsc @@ -26,7 +26,7 @@ import util::Reflective; TModel pascalTModelForTree(Tree pt, str programName, PathConfig _, bool _){ if(pt has top) pt = pt.top; - c = newCollector(programName, pt, pascalConfig()); + c = newCollector(programName, pt, pascalConfig()[assertValidUseDef = true]); pascalPreCollectInitialization(pt, c); collect(pt, c); return newSolver(pt, c.run()).run(); @@ -35,7 +35,7 @@ TModel pascalTModelForTree(Tree pt, str programName, PathConfig _, bool _){ TModel pascalTModelForTree(Tree pt, bool _){ if(pt has top) pt = pt.top; - c = newCollector("pascal", pt, pascalConfig()); + c = newCollector("pascal", pt, pascalConfig()[assertValidUseDef = true]); pascalPreCollectInitialization(pt, c); collect(pt, c); return newSolver(pt, c.run()).run(); diff --git a/src/examples/pico/Test.rsc b/src/examples/pico/Test.rsc index 06cf78e..0acc2f0 100644 --- a/src/examples/pico/Test.rsc +++ b/src/examples/pico/Test.rsc @@ -22,11 +22,11 @@ import ParseTree; TModel picoTModelFromName(str name) { Tree pt = parse(#start[Program], |project://typepal/src/examples/pico/.pico|); - return collectAndSolve(pt, modelName="pico"); + return collectAndSolve(pt, modelName="pico", config=tconfig()[assertValidUseDef=true]); } TModel picoTModelForTree(Tree pt) { - return collectAndSolve(pt, modelName="pico"); + return collectAndSolve(pt, modelName="pico", config=tconfig()[assertValidUseDef=true]); } test bool picoTests() { @@ -36,5 +36,7 @@ test bool picoTests() { runName = "Pico"); } +test bool picoTModelTestFac() = [] := picoTModelFromName("fac").messages; + value main() = picoTests(); \ No newline at end of file diff --git a/src/examples/ql/Test.rsc b/src/examples/ql/Test.rsc index 9a290f1..ee6452b 100644 --- a/src/examples/ql/Test.rsc +++ b/src/examples/ql/Test.rsc @@ -22,11 +22,11 @@ import ParseTree; TModel qlTModelForName(str name) { Tree pt = parse(#start[Form], |project://typepal/src/examples/ql/examples/.ql|); - return collectAndSolve(pt, modelName = "ql"); + return collectAndSolve(pt, modelName = "ql", config = tconfig()[assertValidUseDef = true]); } TModel qlTModelForTree(Tree pt) { - return collectAndSolve(pt, modelName = "ql"); + return collectAndSolve(pt, modelName = "ql", config = tconfig()[assertValidUseDef = true]); } test bool qlTests() { @@ -35,5 +35,10 @@ test bool qlTests() { runName = "QL"); } +test bool qlTModelTestAddition() = [] := qlTModelForName("addition").messages; +test bool qlTModelTestAvg() = [] := qlTModelForName("avg").messages; +test bool qlTModelTestTax() = [] := qlTModelForName("tax").messages; +test bool qlTModelTestTax2() = [] := qlTModelForName("tax2").messages; + value main() = qlTests(); \ No newline at end of file diff --git a/src/examples/smallOO/Test.rsc b/src/examples/smallOO/Test.rsc index 1259298..8ed1f7b 100644 --- a/src/examples/smallOO/Test.rsc +++ b/src/examples/smallOO/Test.rsc @@ -21,7 +21,7 @@ import ParseTree; // ---- Testing --------------------------------------------------------------- TModel smallOOTModelForTree(Tree pt){ - return collectAndSolve(pt, config=smallConfig(), modelName="smalloo"); + return collectAndSolve(pt, config=smallConfig()[assertValidUseDef=true], modelName="smalloo"); } TModel smallOOTModelFromName(str mname){ @@ -40,5 +40,8 @@ test bool smallOOTests() { runName = "SmallOO"); } +test bool smallOOTModelTestM1() = [_] := smallOOTModelFromName("M1").messages; // One error expected +test bool smallOOTModelTestM2() = [] := smallOOTModelFromName("M2").messages; + value main() = smallOOTests(); \ No newline at end of file diff --git a/src/examples/splitstruct/Test.rsc b/src/examples/splitstruct/Test.rsc index dc47fea..afa181e 100644 --- a/src/examples/splitstruct/Test.rsc +++ b/src/examples/splitstruct/Test.rsc @@ -22,7 +22,7 @@ import ParseTree; // ---- Testing --------------------------------------------------------------- TModel splitstructTModelForTree(Tree pt){ - return collectAndSolve(pt, config = splitstructConfig(), modelName="splitstruct"); + return collectAndSolve(pt, config = splitstructConfig()[assertValidUseDef = true], modelName = "splitstruct"); } TModel splitstructTModelFromName(str mname){ diff --git a/src/examples/staticFields/Test.rsc b/src/examples/staticFields/Test.rsc index 0ec96de..c9593f0 100644 --- a/src/examples/staticFields/Test.rsc +++ b/src/examples/staticFields/Test.rsc @@ -22,7 +22,7 @@ import ParseTree; // ---- Testing --------------------------------------------------------------- TModel staticFieldsTModelForTree(Tree pt){ - return collectAndSolve(pt, config=staticFieldsConfig(), modelName="staticfields"); + return collectAndSolve(pt, config=staticFieldsConfig()[assertValidUseDef=true], modelName="staticfields"); } TModel staticFieldsTModelFromName(str mname){ diff --git a/src/examples/struct/Test.rsc b/src/examples/struct/Test.rsc index f7be680..291407c 100644 --- a/src/examples/struct/Test.rsc +++ b/src/examples/struct/Test.rsc @@ -22,7 +22,7 @@ import ParseTree; // ---- Testing --------------------------------------------------------------- TModel structTModelForTree(Tree pt){ - return collectAndSolve(pt, config = structConfig(), modelName="struct"); + return collectAndSolve(pt, config = structConfig()[assertValidUseDef = true], modelName = "struct"); } TModel structTModelFromName(str mname){ diff --git a/src/examples/structParameters/Test.rsc b/src/examples/structParameters/Test.rsc index 1b9a4fc..7eb2416 100644 --- a/src/examples/structParameters/Test.rsc +++ b/src/examples/structParameters/Test.rsc @@ -22,7 +22,7 @@ import ParseTree; // ---- Testing --------------------------------------------------------------- TModel structParametersTModelForTree(Tree pt){ - return collectAndSolve(pt, config = structParametersConfig(), modelName="struct-parameters"); + return collectAndSolve(pt, config = structParametersConfig()[assertValidUseDef = true], modelName = "struct-parameters"); } TModel structParametersTModelFromName(str mname){ @@ -37,5 +37,7 @@ test bool structParametersTests() { runName = "StructParameters"); } +test bool structParametersTModelTestTmp() = [] := structParametersTModelFromName("Tmp").messages; + value main() = structParametersTests(); \ No newline at end of file diff --git a/src/examples/untypedFun/Test.rsc b/src/examples/untypedFun/Test.rsc index b93524a..796a550 100644 --- a/src/examples/untypedFun/Test.rsc +++ b/src/examples/untypedFun/Test.rsc @@ -26,9 +26,12 @@ list[Message] untypedFunCheck(str name){ } TModel untypedFunTModelForTree(Tree pt) - = collectAndSolve(pt, modelName="ufun"); + = collectAndSolve(pt, modelName="ufun", config=tconfig()[assertValidUseDef=true]); test bool untypedFunTests() = runTests([|project://typepal/src/examples/untypedFun/tests.ttl|], #Expression, untypedFunTModelForTree, runName="UntypedFun"); +test bool untypedFunTModelTestBig() = [] := untypedFunTModelForTree(sample("big")).messages; +test bool untypedFunTModelTestTmp() = [_] := untypedFunTModelForTree(sample("tmp")).messages; // One error expected + value main() = untypedFunTests(); From 5d280ff907d15a377c07826efa9c2e8874ebe7f2 Mon Sep 17 00:00:00 2001 From: Sung-Shik Jongmans Date: Fri, 29 May 2026 15:42:00 +0200 Subject: [PATCH 05/12] Fix issue that uses resolved by the solver (instead of by the collector) weren't included in `tm.uses` yet --- src/analysis/typepal/Solver.rsc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/analysis/typepal/Solver.rsc b/src/analysis/typepal/Solver.rsc index c3de447..e7d108d 100644 --- a/src/analysis/typepal/Solver.rsc +++ b/src/analysis/typepal/Solver.rsc @@ -1784,6 +1784,9 @@ Solver newSolver(map[str,Tree] namedTrees, TModel tm){ //println("definedBy;"); iprintln(definedBy); tm.useDef = { *{ | loc d <- definedBy[u]} | loc u <- definedBy }; + // Update `uses` with all uses resolved by the solver + tm.uses = [*({*tm.uses} + {*def2uses[d] | d <- def2uses})]; + ldefines = for(tup: <- tm.defines){ if(defInfo has tree){ l = getLogicalLoc(defInfo.tree); From c179aa4c9bd58c3f5ce75bdb9f1a30c352f3faad Mon Sep 17 00:00:00 2001 From: Sung-Shik Jongmans Date: Fri, 29 May 2026 15:52:57 +0200 Subject: [PATCH 06/12] Remove redundant assignment --- src/analysis/typepal/TestFramework.rsc | 1 - 1 file changed, 1 deletion(-) diff --git a/src/analysis/typepal/TestFramework.rsc b/src/analysis/typepal/TestFramework.rsc index 6fd700e..c4ce452 100644 --- a/src/analysis/typepal/TestFramework.rsc +++ b/src/analysis/typepal/TestFramework.rsc @@ -145,7 +145,6 @@ bool runTests(list[loc] suites, type[&T<:Tree] begin, TModel(Tree t) getModel, b } } } - ok = false; } println("Parse time: msec; Test time: msec"); return ok && isEmpty(failedTests); From 71279ae10410b721abc0a51dad539d03dda57849 Mon Sep 17 00:00:00 2001 From: Sung-Shik Jongmans Date: Mon, 1 Jun 2026 09:19:47 +0200 Subject: [PATCH 07/12] Add `name` argument to `getModel` function argument of `runTests` (to be able to change the config of the collector/solver depending on the particular example, if needed) --- src/analysis/typepal/TestFramework.rsc | 4 ++-- src/examples/aliases/Test.rsc | 2 +- src/examples/calc/Test.rsc | 2 +- src/examples/evenOdd/Test.rsc | 2 +- src/examples/fixedMembers/Test.rsc | 2 +- src/examples/fun/Test.rsc | 5 ++++- src/examples/fwjava/Test.rsc | 2 +- src/examples/modfun/Test.rsc | 2 +- src/examples/modules/Checker.rsc | 2 +- src/examples/pascal/Test.rsc | 2 +- src/examples/pico/Test.rsc | 2 +- src/examples/ql/Test.rsc | 2 +- src/examples/smallOO/Test.rsc | 2 +- src/examples/splitstruct/Test.rsc | 2 +- src/examples/staticFields/Test.rsc | 2 +- src/examples/struct/Test.rsc | 2 +- src/examples/structParameters/Test.rsc | 2 +- src/examples/untypedFun/Test.rsc | 5 ++++- 18 files changed, 25 insertions(+), 19 deletions(-) diff --git a/src/analysis/typepal/TestFramework.rsc b/src/analysis/typepal/TestFramework.rsc index c4ce452..dba9447 100644 --- a/src/analysis/typepal/TestFramework.rsc +++ b/src/analysis/typepal/TestFramework.rsc @@ -73,7 +73,7 @@ bool matches(str subject, str pat){ str spinChar(int n) = n < 0 ? "|" : (0: "|", 1: "/", 2: "-", 3: "\\")[n%4]; -bool runTests(list[loc] suites, type[&T<:Tree] begin, TModel(Tree t) getModel, bool verbose = false, set[str] runOnly = {}, str runName = ""){ +bool runTests(list[loc] suites, type[&T<:Tree] begin, TModel(Tree t, str name) getModel, bool verbose = false, set[str] runOnly = {}, str runName = ""){ TTL ttlProgram = [TTL] ""; map[tuple[str, loc], list[Message]]failedTests = (); @@ -107,7 +107,7 @@ bool runTests(list[loc] suites, type[&T<:Tree] begin, TModel(Tree t) getModel, b when t has src }; newTreeSrc = newTree.src; - model = getModel(newTree); + model = getModel(newTree, ""); list[Message] messages = model.messages; if(verbose) println("runTests: "); expected = ti.expect is none ? {} : {deescape(""[1..-1]) | TTL_String s <- ti.expect.messages}; diff --git a/src/examples/aliases/Test.rsc b/src/examples/aliases/Test.rsc index ce3ab19..6aebe7e 100644 --- a/src/examples/aliases/Test.rsc +++ b/src/examples/aliases/Test.rsc @@ -35,7 +35,7 @@ TModel aliasesTModelFromName(str mname){ test bool aliasesTests() { return runTests([|project://typepal/src/examples/aliases/aliases.ttl|], #start[Program], - TModel (Tree t) { return aliasesTModelForTree(t); }, + TModel (Tree t, str _name) { return aliasesTModelForTree(t); }, runName = "Aliases"); } diff --git a/src/examples/calc/Test.rsc b/src/examples/calc/Test.rsc index 4c7fa94..98aef4b 100644 --- a/src/examples/calc/Test.rsc +++ b/src/examples/calc/Test.rsc @@ -32,7 +32,7 @@ TModel calcTModelFromStr(str text){ test bool calcTests() { return runTests([|project://typepal/src/examples/calc/tests.ttl|], #Calc, - calcTModelForTree, + TModel (Tree t, str _name) { return calcTModelForTree(t); }, runName="Calc"); } diff --git a/src/examples/evenOdd/Test.rsc b/src/examples/evenOdd/Test.rsc index 8e4add5..50b77f0 100644 --- a/src/examples/evenOdd/Test.rsc +++ b/src/examples/evenOdd/Test.rsc @@ -36,7 +36,7 @@ TModel evenOddTModelFromStr(str text){ test bool evenOddTests() { return runTests([|project://typepal/src/examples/evenOdd/tests.ttl|], #EvenOdd, - evenOddTModelForTree, + TModel (Tree t, str _name) { return evenOddTModelForTree(t); }, runName="EvenOdd"); } diff --git a/src/examples/fixedMembers/Test.rsc b/src/examples/fixedMembers/Test.rsc index 8813deb..a15c9ed 100644 --- a/src/examples/fixedMembers/Test.rsc +++ b/src/examples/fixedMembers/Test.rsc @@ -33,7 +33,7 @@ TModel fixedMembersTModelFromName(str mname){ test bool fixedMembersTests() { return runTests([|project://typepal/src/examples/fixedMembers/fixedMembers.ttl|], #start[Program], - TModel (Tree t) { return fixedMembersTModelForTree(t); }, + TModel (Tree t, str _name) { return fixedMembersTModelForTree(t); }, runName = "fixedMembers"); } diff --git a/src/examples/fun/Test.rsc b/src/examples/fun/Test.rsc index 046717f..74b94a1 100644 --- a/src/examples/fun/Test.rsc +++ b/src/examples/fun/Test.rsc @@ -41,7 +41,10 @@ list[Message] funCheck(str name) { } test bool funTests() - = runTests([|project://typepal/src/examples/fun/tests.ttl|], #Fun, funTModelForTree, runName="Fun"); + = runTests([|project://typepal/src/examples/fun/tests.ttl|], + #Fun, + TModel (Tree t, str _name) { return funTModelForTree(t); }, + runName="Fun"); test bool funTModelTestBig() = [] := funTModel("big").messages; test bool funTModelTestTmp() = [] := funTModel("tmp").messages; diff --git a/src/examples/fwjava/Test.rsc b/src/examples/fwjava/Test.rsc index df82425..a8fdfcd 100644 --- a/src/examples/fwjava/Test.rsc +++ b/src/examples/fwjava/Test.rsc @@ -37,7 +37,7 @@ TModel fwjTModelFromName(str mname, bool _){ test bool fwjTests() { return runTests([|project://typepal/src/examples/fwjava/tests.ttl|], #start[FWJProgram], - TModel (Tree t) { return fwjTModelForTree(t); }, + TModel (Tree t, str _name) { return fwjTModelForTree(t); }, runName = "FwJava"); } diff --git a/src/examples/modfun/Test.rsc b/src/examples/modfun/Test.rsc index 2e8600e..253c006 100644 --- a/src/examples/modfun/Test.rsc +++ b/src/examples/modfun/Test.rsc @@ -44,7 +44,7 @@ list[Message] modfunCheck(str name) { test bool modfunTests() = runTests([|project://typepal/src/examples/modfun/tests.ttl|], #ModFun, - modfunTModelForTree, + TModel (Tree t, str _name) { return modfunTModelForTree(t); }, runName = "ModFun"); test bool modfunTModelTestA() = [_, _, _] := modfunTModel("A").messages; // Three errors expected diff --git a/src/examples/modules/Checker.rsc b/src/examples/modules/Checker.rsc index 400d7bc..689fc01 100644 --- a/src/examples/modules/Checker.rsc +++ b/src/examples/modules/Checker.rsc @@ -147,7 +147,7 @@ list[Message] runModules(str name, bool debug = false) { } bool testModules(int n, bool debug = false, set[str] runOnly = {}) { - return runTests([|project://modules-core/src/lang/modules/modules<"">.ttl|], #start[Program], TModel (Tree t) { + return runTests([|project://modules-core/src/lang/modules/modules<"">.ttl|], #start[Program], TModel (Tree t, str _name) { return modulesTModelFromTree(t); }, runOnly = runOnly); } diff --git a/src/examples/pascal/Test.rsc b/src/examples/pascal/Test.rsc index 332b1c3..9cf87d8 100644 --- a/src/examples/pascal/Test.rsc +++ b/src/examples/pascal/Test.rsc @@ -57,7 +57,7 @@ test bool pascalTests() { //return true; bool ok = runTests([|project://typepal/src/examples/pascal/expression-tests.ttl|, |project://typepal/src/examples/pascal/statement-tests.ttl| - ], #start[Program], TModel (Tree t) { return pascalTModelForTree(t, false); }, + ], #start[Program], TModel (Tree t, str _name) { return pascalTModelForTree(t, false); }, runName = "Pascal"); println("Executing Pascal examples\r"); int n = 0; diff --git a/src/examples/pico/Test.rsc b/src/examples/pico/Test.rsc index 0acc2f0..9a43171 100644 --- a/src/examples/pico/Test.rsc +++ b/src/examples/pico/Test.rsc @@ -32,7 +32,7 @@ TModel picoTModelForTree(Tree pt) { test bool picoTests() { return runTests([|project://typepal/src/examples/pico/tests.ttl|], #start[Program], - TModel (Tree t) { return picoTModelForTree(t); }, + TModel (Tree t, str _name) { return picoTModelForTree(t); }, runName = "Pico"); } diff --git a/src/examples/ql/Test.rsc b/src/examples/ql/Test.rsc index ee6452b..30bb8a5 100644 --- a/src/examples/ql/Test.rsc +++ b/src/examples/ql/Test.rsc @@ -31,7 +31,7 @@ TModel qlTModelForTree(Tree pt) { test bool qlTests() { return runTests([|project://typepal/src/examples/ql/tests.ttl|], #start[Form], - TModel (Tree t) { return qlTModelForTree(t); }, + TModel (Tree t, str _name) { return qlTModelForTree(t); }, runName = "QL"); } diff --git a/src/examples/smallOO/Test.rsc b/src/examples/smallOO/Test.rsc index 8ed1f7b..044f754 100644 --- a/src/examples/smallOO/Test.rsc +++ b/src/examples/smallOO/Test.rsc @@ -36,7 +36,7 @@ list[Message] checkSmallOO(str mname) { test bool smallOOTests() { return runTests([|project://typepal/src/examples/smallOO/tests.ttl|], #start[Module], - TModel (Tree t) { return smallOOTModelForTree(t); }, + TModel (Tree t, str _name) { return smallOOTModelForTree(t); }, runName = "SmallOO"); } diff --git a/src/examples/splitstruct/Test.rsc b/src/examples/splitstruct/Test.rsc index afa181e..ed0315d 100644 --- a/src/examples/splitstruct/Test.rsc +++ b/src/examples/splitstruct/Test.rsc @@ -33,7 +33,7 @@ TModel splitstructTModelFromName(str mname){ test bool splitstructTests() { return runTests([|project://typepal/src/examples/splitstruct/tests.ttl|], #start[Program], - TModel (Tree t) { return splitstructTModelForTree(t); }, + TModel (Tree t, str _name) { return splitstructTModelForTree(t); }, runName = "SplitStruct"); } diff --git a/src/examples/staticFields/Test.rsc b/src/examples/staticFields/Test.rsc index c9593f0..1d83be1 100644 --- a/src/examples/staticFields/Test.rsc +++ b/src/examples/staticFields/Test.rsc @@ -33,7 +33,7 @@ TModel staticFieldsTModelFromName(str mname){ test bool staticFieldsTests() { return runTests([|project://typepal/src/examples/staticFields/tests.ttl|], #start[Program], - TModel (Tree t) { return staticFieldsTModelForTree(t); }, + TModel (Tree t, str _name) { return staticFieldsTModelForTree(t); }, runName = "StaticFields"); } diff --git a/src/examples/struct/Test.rsc b/src/examples/struct/Test.rsc index 291407c..badd742 100644 --- a/src/examples/struct/Test.rsc +++ b/src/examples/struct/Test.rsc @@ -33,7 +33,7 @@ TModel structTModelFromName(str mname){ test bool structTests() { return runTests([|project://typepal/src/examples/struct/tests.ttl|], #start[Program], - TModel (Tree t) { return structTModelForTree(t); }, + TModel (Tree t, str _name) { return structTModelForTree(t); }, runName = "Struct"); } diff --git a/src/examples/structParameters/Test.rsc b/src/examples/structParameters/Test.rsc index 7eb2416..74290ec 100644 --- a/src/examples/structParameters/Test.rsc +++ b/src/examples/structParameters/Test.rsc @@ -33,7 +33,7 @@ TModel structParametersTModelFromName(str mname){ test bool structParametersTests() { return runTests([|project://typepal/src/examples/structParameters/tests.ttl|], #start[Program], - TModel (Tree t) { return structParametersTModelForTree(t); }, + TModel (Tree t, str _name) { return structParametersTModelForTree(t); }, runName = "StructParameters"); } diff --git a/src/examples/untypedFun/Test.rsc b/src/examples/untypedFun/Test.rsc index 796a550..f642bad 100644 --- a/src/examples/untypedFun/Test.rsc +++ b/src/examples/untypedFun/Test.rsc @@ -29,7 +29,10 @@ TModel untypedFunTModelForTree(Tree pt) = collectAndSolve(pt, modelName="ufun", config=tconfig()[assertValidUseDef=true]); test bool untypedFunTests() - = runTests([|project://typepal/src/examples/untypedFun/tests.ttl|], #Expression, untypedFunTModelForTree, runName="UntypedFun"); + = runTests([|project://typepal/src/examples/untypedFun/tests.ttl|], + #Expression, + TModel (Tree t, str _name) { return untypedFunTModelForTree(t); }, + runName="UntypedFun"); test bool untypedFunTModelTestBig() = [] := untypedFunTModelForTree(sample("big")).messages; test bool untypedFunTModelTestTmp() = [_] := untypedFunTModelForTree(sample("tmp")).messages; // One error expected From 92f66f3d04de44fca68867800d4ddf345fbe623c Mon Sep 17 00:00:00 2001 From: Sung-Shik Jongmans Date: Mon, 1 Jun 2026 09:24:04 +0200 Subject: [PATCH 08/12] Update `aliasesTests` to disable use-def validation for example `CircularAlias1` --- src/examples/aliases/Test.rsc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/examples/aliases/Test.rsc b/src/examples/aliases/Test.rsc index 6aebe7e..bf2515f 100644 --- a/src/examples/aliases/Test.rsc +++ b/src/examples/aliases/Test.rsc @@ -20,10 +20,7 @@ import ParseTree; // ---- Testing --------------------------------------------------------------- -TModel aliasesTModelForTree(Tree pt){ - // Enable `assertValidUseDef` only when the program under test **isn't** - // `CircularAlias1` (which is expected to have an invalid `useDef`). - bool assertValidUseDef = md5Hash(pt) != "6e3b63e2945eb4d075ff79f0fd2039eb"; // Hash of program `CircularAlias1` +TModel aliasesTModelForTree(Tree pt, bool assertValidUseDef = true){ return collectAndSolve(pt, config = aliasesConfig()[assertValidUseDef = assertValidUseDef], modelName = "alias"); } @@ -35,7 +32,10 @@ TModel aliasesTModelFromName(str mname){ test bool aliasesTests() { return runTests([|project://typepal/src/examples/aliases/aliases.ttl|], #start[Program], - TModel (Tree t, str _name) { return aliasesTModelForTree(t); }, + // Enable `assertValidUseDef` only when the program under + // test **isn't** `CircularAlias1` (which is expected to + // have an invalid `useDef`). + TModel (Tree t, str name) { return aliasesTModelForTree(t, assertValidUseDef = name != "CircularAlias1"); }, runName = "Aliases"); } From cc276036a76b035ae4ce5b0a95dabe415135e8ed Mon Sep 17 00:00:00 2001 From: Sung-Shik Jongmans Date: Mon, 1 Jun 2026 09:27:33 +0200 Subject: [PATCH 09/12] Fix whitespace --- src/examples/fun/Test.rsc | 2 +- src/examples/modfun/Test.rsc | 6 +++--- src/examples/untypedFun/Test.rsc | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/examples/fun/Test.rsc b/src/examples/fun/Test.rsc index 74b94a1..aaa406b 100644 --- a/src/examples/fun/Test.rsc +++ b/src/examples/fun/Test.rsc @@ -41,7 +41,7 @@ list[Message] funCheck(str name) { } test bool funTests() - = runTests([|project://typepal/src/examples/fun/tests.ttl|], + = runTests([|project://typepal/src/examples/fun/tests.ttl|], #Fun, TModel (Tree t, str _name) { return funTModelForTree(t); }, runName="Fun"); diff --git a/src/examples/modfun/Test.rsc b/src/examples/modfun/Test.rsc index 253c006..9297dd6 100644 --- a/src/examples/modfun/Test.rsc +++ b/src/examples/modfun/Test.rsc @@ -43,9 +43,9 @@ list[Message] modfunCheck(str name) { test bool modfunTests() = runTests([|project://typepal/src/examples/modfun/tests.ttl|], - #ModFun, - TModel (Tree t, str _name) { return modfunTModelForTree(t); }, - runName = "ModFun"); + #ModFun, + TModel (Tree t, str _name) { return modfunTModelForTree(t); }, + runName = "ModFun"); test bool modfunTModelTestA() = [_, _, _] := modfunTModel("A").messages; // Three errors expected test bool modfunTModelTestB() = [_, _] := modfunTModel("B").messages; // Two errors expected diff --git a/src/examples/untypedFun/Test.rsc b/src/examples/untypedFun/Test.rsc index f642bad..6d9d757 100644 --- a/src/examples/untypedFun/Test.rsc +++ b/src/examples/untypedFun/Test.rsc @@ -30,9 +30,9 @@ TModel untypedFunTModelForTree(Tree pt) test bool untypedFunTests() = runTests([|project://typepal/src/examples/untypedFun/tests.ttl|], - #Expression, - TModel (Tree t, str _name) { return untypedFunTModelForTree(t); }, - runName="UntypedFun"); + #Expression, + TModel (Tree t, str _name) { return untypedFunTModelForTree(t); }, + runName="UntypedFun"); test bool untypedFunTModelTestBig() = [] := untypedFunTModelForTree(sample("big")).messages; test bool untypedFunTModelTestTmp() = [_] := untypedFunTModelForTree(sample("tmp")).messages; // One error expected From 7d3bb85e86233a6e4a7dc3474144336706581940 Mon Sep 17 00:00:00 2001 From: Sung-Shik Jongmans Date: Mon, 1 Jun 2026 10:13:11 +0200 Subject: [PATCH 10/12] Fix issue that location containment in validity checks should be physical instead of logical --- src/analysis/typepal/Solver.rsc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/analysis/typepal/Solver.rsc b/src/analysis/typepal/Solver.rsc index e7d108d..f78a705 100644 --- a/src/analysis/typepal/Solver.rsc +++ b/src/analysis/typepal/Solver.rsc @@ -36,7 +36,7 @@ void assertValidDefines(TModel tm){ if (!tm.config.assertValidDefines) return; for(d <- tm.defines){ - assert isContainedIn(d.defined, d.scope) || "global-scope" == d.scope.scheme : + assert isContainedIn(d.defined, d.scope, tm.logical2physical) || "global-scope" == d.scope.scheme : "Expected: For each `d` in `tm.defines`, `d.defined` is contained in `d.scope`. " + "Actual: For `` in TModel ``, `` (`d.defined`) isn\'t contained in `` (`d.scope`)."; From 839dccc4c17e81d6d98b10fbeefb1b148dbecc85 Mon Sep 17 00:00:00 2001 From: Sung-Shik Jongmans Date: Mon, 1 Jun 2026 11:44:20 +0200 Subject: [PATCH 11/12] Update default of `assertValidDefines` to `false` --- src/analysis/typepal/ConfigurableScopeGraph.rsc | 2 +- src/examples/aliases/Test.rsc | 2 +- src/examples/calc/Test.rsc | 2 +- src/examples/dataModel/Test.rsc | 2 +- src/examples/evenOdd/Test.rsc | 2 +- src/examples/fixedMembers/Test.rsc | 2 +- src/examples/fun/Test.rsc | 2 +- src/examples/fwjava/Test.rsc | 8 +++++++- src/examples/modfun/Test.rsc | 2 +- src/examples/pascal/Test.rsc | 4 ++-- src/examples/pico/Test.rsc | 4 ++-- src/examples/ql/Test.rsc | 4 ++-- src/examples/smallOO/Test.rsc | 2 +- src/examples/splitstruct/Test.rsc | 2 +- src/examples/staticFields/Test.rsc | 2 +- src/examples/struct/Test.rsc | 2 +- src/examples/structParameters/Test.rsc | 2 +- src/examples/untypedFun/Test.rsc | 2 +- 18 files changed, 27 insertions(+), 21 deletions(-) diff --git a/src/analysis/typepal/ConfigurableScopeGraph.rsc b/src/analysis/typepal/ConfigurableScopeGraph.rsc index 26b4fb0..d6df65c 100644 --- a/src/analysis/typepal/ConfigurableScopeGraph.rsc +++ b/src/analysis/typepal/ConfigurableScopeGraph.rsc @@ -108,7 +108,7 @@ data TypePalConfig( ); data TypePalConfig( - bool assertValidDefines = true, + bool assertValidDefines = false, bool assertValidUseDef = false, bool verbose = false, diff --git a/src/examples/aliases/Test.rsc b/src/examples/aliases/Test.rsc index bf2515f..b12d2d0 100644 --- a/src/examples/aliases/Test.rsc +++ b/src/examples/aliases/Test.rsc @@ -21,7 +21,7 @@ import ParseTree; // ---- Testing --------------------------------------------------------------- TModel aliasesTModelForTree(Tree pt, bool assertValidUseDef = true){ - return collectAndSolve(pt, config = aliasesConfig()[assertValidUseDef = assertValidUseDef], modelName = "alias"); + return collectAndSolve(pt, config = aliasesConfig()[assertValidDefines = true][assertValidUseDef = assertValidUseDef], modelName = "alias"); } TModel aliasesTModelFromName(str mname){ diff --git a/src/examples/calc/Test.rsc b/src/examples/calc/Test.rsc index 98aef4b..885fe3e 100644 --- a/src/examples/calc/Test.rsc +++ b/src/examples/calc/Test.rsc @@ -21,7 +21,7 @@ import ParseTree; // In order to parse tests // ---- Testing --------------------------------------------------------------- TModel calcTModelForTree(Tree pt){ - return collectAndSolve(pt, modelName = "calc", config = tconfig()[assertValidUseDef = true]); + return collectAndSolve(pt, modelName = "calc", config = tconfig()[assertValidDefines = true][assertValidUseDef = true]); } TModel calcTModelFromStr(str text){ diff --git a/src/examples/dataModel/Test.rsc b/src/examples/dataModel/Test.rsc index 6a08c94..c958bf8 100644 --- a/src/examples/dataModel/Test.rsc +++ b/src/examples/dataModel/Test.rsc @@ -17,7 +17,7 @@ extend examples::dataModel::Checker; extend analysis::typepal::TestFramework; TModel dmTModelForTree(Tree pt){ - return collectAndSolve(pt, config = dmConfig()[assertValidUseDef = true]); + return collectAndSolve(pt, config = dmConfig()[assertValidDefines = true][assertValidUseDef = true]); } TModel dmTModelFromName(str mname){ diff --git a/src/examples/evenOdd/Test.rsc b/src/examples/evenOdd/Test.rsc index 50b77f0..db460ab 100644 --- a/src/examples/evenOdd/Test.rsc +++ b/src/examples/evenOdd/Test.rsc @@ -23,7 +23,7 @@ import ParseTree; // In order to parse tests TModel evenOddTModelForTree(Tree pt){ if(pt has top) pt = pt.top; - c = newCollector("even-odd", pt, tconfig()[assertValidUseDef = true]); + c = newCollector("even-odd", pt, tconfig()[assertValidDefines = true][assertValidUseDef = true]); collect(pt, c); return newSolver(pt, c.run()).run(); } diff --git a/src/examples/fixedMembers/Test.rsc b/src/examples/fixedMembers/Test.rsc index a15c9ed..fd5fe48 100644 --- a/src/examples/fixedMembers/Test.rsc +++ b/src/examples/fixedMembers/Test.rsc @@ -22,7 +22,7 @@ import ParseTree; // ---- Testing --------------------------------------------------------------- TModel fixedMembersTModelForTree(Tree pt){ - return collectAndSolve(pt, config = fixedMembersConfig()[assertValidUseDef = true], modelName = "fixed-members"); + return collectAndSolve(pt, config = fixedMembersConfig()[assertValidDefines = true][assertValidUseDef = true], modelName = "fixed-members"); } TModel fixedMembersTModelFromName(str mname){ diff --git a/src/examples/fun/Test.rsc b/src/examples/fun/Test.rsc index aaa406b..5241e4a 100644 --- a/src/examples/fun/Test.rsc +++ b/src/examples/fun/Test.rsc @@ -27,7 +27,7 @@ TModel funTModel(str name){ } TModel funTModelForTree(Tree pt){ - return collectAndSolve(pt, modelName = "fun", config = tconfig()[assertValidUseDef = true]); + return collectAndSolve(pt, modelName = "fun", config = tconfig()[assertValidDefines = true][assertValidUseDef = true]); } TModel funTModelFromStr(str text){ diff --git a/src/examples/fwjava/Test.rsc b/src/examples/fwjava/Test.rsc index a8fdfcd..e62bfe4 100644 --- a/src/examples/fwjava/Test.rsc +++ b/src/examples/fwjava/Test.rsc @@ -23,7 +23,7 @@ import ParseTree; TModel fwjTModelForTree(Tree pt){ if(pt has top) pt = pt.top; - c = newCollector("fwj", pt, fwjConfig()[assertValidUseDef = true]); + c = newCollector("fwj", pt, fwjConfig()[assertValidDefines = true][assertValidUseDef = true]); fwjPreCollectInitialization(pt, c); collect(pt, c); return newSolver(pt, c.run()).run(); @@ -45,4 +45,10 @@ test bool fwjTModelTestCpt() = [] := fwjTModelFromName("cpt", false).messages; test bool fwjTModelTestPair() = [] := fwjTModelFromName("pair", false).messages; test bool fwjTModelTestTmp() = [_, _] := fwjTModelFromName("tmp", false).messages; // Two errors expected +test bool fwjUseDefTestCpt() { + tm = fwjTModelFromName("cpt", false); + iprintln(tm.useDef); + return true; +} + value main() = fwjTests(); \ No newline at end of file diff --git a/src/examples/modfun/Test.rsc b/src/examples/modfun/Test.rsc index 9297dd6..591fe5e 100644 --- a/src/examples/modfun/Test.rsc +++ b/src/examples/modfun/Test.rsc @@ -28,7 +28,7 @@ TModel modfunTModel(str name){ } TModel modfunTModelForTree(Tree pt){ - return collectAndSolve(pt, modelName="modfun", config=tconfig()[assertValidUseDef=true]); + return collectAndSolve(pt, modelName="modfun", config=tconfig()[assertValidDefines=true][assertValidUseDef=true]); } TModel modfunTModelFromStr(str text){ diff --git a/src/examples/pascal/Test.rsc b/src/examples/pascal/Test.rsc index 9cf87d8..ec3f113 100644 --- a/src/examples/pascal/Test.rsc +++ b/src/examples/pascal/Test.rsc @@ -26,7 +26,7 @@ import util::Reflective; TModel pascalTModelForTree(Tree pt, str programName, PathConfig _, bool _){ if(pt has top) pt = pt.top; - c = newCollector(programName, pt, pascalConfig()[assertValidUseDef = true]); + c = newCollector(programName, pt, pascalConfig()[assertValidDefines = true][assertValidUseDef = true]); pascalPreCollectInitialization(pt, c); collect(pt, c); return newSolver(pt, c.run()).run(); @@ -35,7 +35,7 @@ TModel pascalTModelForTree(Tree pt, str programName, PathConfig _, bool _){ TModel pascalTModelForTree(Tree pt, bool _){ if(pt has top) pt = pt.top; - c = newCollector("pascal", pt, pascalConfig()[assertValidUseDef = true]); + c = newCollector("pascal", pt, pascalConfig()[assertValidDefines = true][assertValidUseDef = true]); pascalPreCollectInitialization(pt, c); collect(pt, c); return newSolver(pt, c.run()).run(); diff --git a/src/examples/pico/Test.rsc b/src/examples/pico/Test.rsc index 9a43171..d31cea2 100644 --- a/src/examples/pico/Test.rsc +++ b/src/examples/pico/Test.rsc @@ -22,11 +22,11 @@ import ParseTree; TModel picoTModelFromName(str name) { Tree pt = parse(#start[Program], |project://typepal/src/examples/pico/.pico|); - return collectAndSolve(pt, modelName="pico", config=tconfig()[assertValidUseDef=true]); + return collectAndSolve(pt, modelName="pico", config=tconfig()[assertValidDefines=true][assertValidUseDef=true]); } TModel picoTModelForTree(Tree pt) { - return collectAndSolve(pt, modelName="pico", config=tconfig()[assertValidUseDef=true]); + return collectAndSolve(pt, modelName="pico", config=tconfig()[assertValidDefines=true][assertValidUseDef=true]); } test bool picoTests() { diff --git a/src/examples/ql/Test.rsc b/src/examples/ql/Test.rsc index 30bb8a5..4bb9401 100644 --- a/src/examples/ql/Test.rsc +++ b/src/examples/ql/Test.rsc @@ -22,11 +22,11 @@ import ParseTree; TModel qlTModelForName(str name) { Tree pt = parse(#start[Form], |project://typepal/src/examples/ql/examples/.ql|); - return collectAndSolve(pt, modelName = "ql", config = tconfig()[assertValidUseDef = true]); + return collectAndSolve(pt, modelName = "ql", config = tconfig()[assertValidDefines = true][assertValidUseDef = true]); } TModel qlTModelForTree(Tree pt) { - return collectAndSolve(pt, modelName = "ql", config = tconfig()[assertValidUseDef = true]); + return collectAndSolve(pt, modelName = "ql", config = tconfig()[assertValidDefines = true][assertValidUseDef = true]); } test bool qlTests() { diff --git a/src/examples/smallOO/Test.rsc b/src/examples/smallOO/Test.rsc index 044f754..7c0d3c9 100644 --- a/src/examples/smallOO/Test.rsc +++ b/src/examples/smallOO/Test.rsc @@ -21,7 +21,7 @@ import ParseTree; // ---- Testing --------------------------------------------------------------- TModel smallOOTModelForTree(Tree pt){ - return collectAndSolve(pt, config=smallConfig()[assertValidUseDef=true], modelName="smalloo"); + return collectAndSolve(pt, config=smallConfig()[assertValidDefines=true][assertValidUseDef=true], modelName="smalloo"); } TModel smallOOTModelFromName(str mname){ diff --git a/src/examples/splitstruct/Test.rsc b/src/examples/splitstruct/Test.rsc index ed0315d..11fa56d 100644 --- a/src/examples/splitstruct/Test.rsc +++ b/src/examples/splitstruct/Test.rsc @@ -22,7 +22,7 @@ import ParseTree; // ---- Testing --------------------------------------------------------------- TModel splitstructTModelForTree(Tree pt){ - return collectAndSolve(pt, config = splitstructConfig()[assertValidUseDef = true], modelName = "splitstruct"); + return collectAndSolve(pt, config = splitstructConfig()[assertValidDefines = true][assertValidUseDef = true], modelName = "splitstruct"); } TModel splitstructTModelFromName(str mname){ diff --git a/src/examples/staticFields/Test.rsc b/src/examples/staticFields/Test.rsc index 1d83be1..39fbde5 100644 --- a/src/examples/staticFields/Test.rsc +++ b/src/examples/staticFields/Test.rsc @@ -22,7 +22,7 @@ import ParseTree; // ---- Testing --------------------------------------------------------------- TModel staticFieldsTModelForTree(Tree pt){ - return collectAndSolve(pt, config=staticFieldsConfig()[assertValidUseDef=true], modelName="staticfields"); + return collectAndSolve(pt, config=staticFieldsConfig()[assertValidDefines=true][assertValidUseDef=true], modelName="staticfields"); } TModel staticFieldsTModelFromName(str mname){ diff --git a/src/examples/struct/Test.rsc b/src/examples/struct/Test.rsc index badd742..3bf42eb 100644 --- a/src/examples/struct/Test.rsc +++ b/src/examples/struct/Test.rsc @@ -22,7 +22,7 @@ import ParseTree; // ---- Testing --------------------------------------------------------------- TModel structTModelForTree(Tree pt){ - return collectAndSolve(pt, config = structConfig()[assertValidUseDef = true], modelName = "struct"); + return collectAndSolve(pt, config = structConfig()[assertValidDefines = true][assertValidUseDef = true], modelName = "struct"); } TModel structTModelFromName(str mname){ diff --git a/src/examples/structParameters/Test.rsc b/src/examples/structParameters/Test.rsc index 74290ec..4777cfa 100644 --- a/src/examples/structParameters/Test.rsc +++ b/src/examples/structParameters/Test.rsc @@ -22,7 +22,7 @@ import ParseTree; // ---- Testing --------------------------------------------------------------- TModel structParametersTModelForTree(Tree pt){ - return collectAndSolve(pt, config = structParametersConfig()[assertValidUseDef = true], modelName = "struct-parameters"); + return collectAndSolve(pt, config = structParametersConfig()[assertValidDefines = true][assertValidUseDef = true], modelName = "struct-parameters"); } TModel structParametersTModelFromName(str mname){ diff --git a/src/examples/untypedFun/Test.rsc b/src/examples/untypedFun/Test.rsc index 6d9d757..020a028 100644 --- a/src/examples/untypedFun/Test.rsc +++ b/src/examples/untypedFun/Test.rsc @@ -26,7 +26,7 @@ list[Message] untypedFunCheck(str name){ } TModel untypedFunTModelForTree(Tree pt) - = collectAndSolve(pt, modelName="ufun", config=tconfig()[assertValidUseDef=true]); + = collectAndSolve(pt, modelName="ufun", config=tconfig()[assertValidDefines=true][assertValidUseDef=true]); test bool untypedFunTests() = runTests([|project://typepal/src/examples/untypedFun/tests.ttl|], From 92744aa9fc9d3da6e04b84b1e5c1f17f544647d9 Mon Sep 17 00:00:00 2001 From: Sung-Shik Jongmans Date: Mon, 1 Jun 2026 16:45:36 +0200 Subject: [PATCH 12/12] Revert removal of `checkAllTypesAvailable`, as it happens to be part of Typepal's public API (and at least one consumer in the integration test exists) --- src/analysis/typepal/Solver.rsc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/analysis/typepal/Solver.rsc b/src/analysis/typepal/Solver.rsc index f78a705..8a4abab 100644 --- a/src/analysis/typepal/Solver.rsc +++ b/src/analysis/typepal/Solver.rsc @@ -32,6 +32,14 @@ import Type; import analysis::typepal::StringSimilarity; import util::IDEServices; +void checkAllTypesAvailable(TModel tm){ + for(tup: <- tm.defines){ + if(!(defInfo has atype)){ + throw "checkTypesAvailable: , "; + } + } +} + void assertValidDefines(TModel tm){ if (!tm.config.assertValidDefines) return; for(d <- tm.defines){