From e17766e79cb06990e9958b2f302b08c99d272f2e Mon Sep 17 00:00:00 2001 From: Sung-Shik Jongmans Date: Wed, 24 Jun 2026 09:17:07 +0200 Subject: [PATCH 1/7] Add scratch file --- src/org/rascalmpl/compiler/Scratch.rsc | 137 +++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 src/org/rascalmpl/compiler/Scratch.rsc diff --git a/src/org/rascalmpl/compiler/Scratch.rsc b/src/org/rascalmpl/compiler/Scratch.rsc new file mode 100644 index 00000000000..5fe293fd548 --- /dev/null +++ b/src/org/rascalmpl/compiler/Scratch.rsc @@ -0,0 +1,137 @@ +module Scratch + +import Prelude; +import lang::rascalcore::check::Checker; +import lang::rascalcore::check::ModuleLocations; +import util::FileSystem; +import util::SystemAPI; +import util::Benchmark; + +import analysis::typepal::Solver; + +loc rascalLib() { + loc rascalLib = resolveLocation(|std:///|); + if (/org.rascalmpl.library.?$/ := rascalLib.path) { + rascalLib = rascalLib.parent.parent.parent; + } + return rascalLib; +} + +loc typepalLib() { + return |mvn://org.rascalmpl--typepal--0.17.0-RC4-SNAPSHOT/|; +} + +int typecheckBirdCore(bool force = false) = realTimeOf(void() { typecheck(|home:///Desktop/bird/bird-core|, ["src/main/rascal"], force = force); }); + +int typecheckRascalLibraryAnalysis(bool force = false) = realTimeOf(void() { typecheck(|home:///Desktop/usethesource2/rascal|, ["src/org/rascalmpl/library"], dir = "analysis", force = force); }); + +int typecheckTypepal(bool force = false) = realTimeOf(void() { typecheck(|home:///Desktop/usethesource2/typepal|, ["src"], force = force); }); +// 1454032 +// 1207079 - remove check in Result constructor -- UNSOUND +// 1149042 - add cache for getSimpleVariable + +bool typecheck(loc project, list[str] srcs, str dir = "", bool force = false) { + + // Create path config + + println(); + println("## Create path config"); + println(); + + PathConfig pcfg = pathConfig( + srcs = [project + src | str src <- srcs], + bin = project + "target/classes", + libs = [rascalLib()] + ); + + iprintln(pcfg); + println(); + + // Delete `bin` + + if (force) { + println("## Delete `bin`"); + println(); + + remove(pcfg.bin); + + iprintln(sort([*find(pcfg.bin, "tpl")])); + println(); + } + + // Typecheck `srcs` + + println("## Typecheck `srcs`"); + println(); + + list[str] moduleNames = [getRascalModuleName(l, pcfg) | loc src <- pcfg.srcs, loc l <- find(src + dir, "rsc")]; + + iprintln(sort(moduleNames)); + println(); + + calculatorFailureCount = 0; + calculatorFailureNanoTime = 0; + requirementFailureCount = 0; + requirementFailureNanoTime = 0; + ModuleStatus ms = rascalTModelForNames(moduleNames, rascalCompilerConfig(pcfg)[enableErrorFixes = false], dummy_compile1); + + iprintln(sort([*find(pcfg.bin, "tpl")])); + println(); + + return (true | it && found | str moduleName <- moduleNames, := getTModelForModule(moduleName, ms)); +} + +void z1(int n = 10) { + set[loc] locs = {}; + for (int i <- [0..n]) { + locs += |unknown:///| + ""; + // if (i % 1000 == 0) { + // println(i); + // } + } +} + +void z2(int n = 10) { + list[int] elems = []; + for (int i <- [0..n]) { + elems += i; + if (i % (10*1000) == 0) { + println(i); + } + } +} + +void z3(int n = 10) { + set[value] elems = {}; + for (int i <- [0..n]) { + elems += ""; + } +} + +/* + +6-tuples zijn duur, projectie is mogelijk goedkoper + + - overloaded type zijn triples (bijv. alleen 3e element gebruikt) + - over het algemeen kort, sommige 100 overloads + - defines zijn 6-tuples + + +Misschien vergelijkbaar met lange ADT constructors + + +komen zowel in Rascal typechecker als in typepal voor + + + + +binaire relaties geoptimaliseerd in Vallang. n-ary relaties niet zo erg. +6-tuple vervangen door 6 binary relaties???? + + + +Aanpak: + + - hoog niveau gaan meten welke delen van de checker de meeste tijd kosten + +*/ \ No newline at end of file From 27c103392229c6bd9a6abd511eecaa296659009b Mon Sep 17 00:00:00 2001 From: Sung-Shik Jongmans Date: Wed, 24 Jun 2026 09:18:27 +0200 Subject: [PATCH 2/7] Disable assertions for RascalShell launch target --- .vscode/launch.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index fa9529bef36..fa0c556435d 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -37,7 +37,7 @@ "request": "launch", "mainClass": "org.rascalmpl.shell.RascalShell", "projectName": "rascal", - "vmArgs": "-Xss80m -Xmx2g -ea", + "vmArgs": "-Xss80m -Xmx2g", "console": "integratedTerminal" }, { From 98eaa5f22979c66480c874a471d3e6ff78aa0a3b Mon Sep 17 00:00:00 2001 From: Sung-Shik Jongmans Date: Wed, 24 Jun 2026 15:50:18 +0200 Subject: [PATCH 3/7] Add flamegraph generator --- .vscode/launch.json | 2 +- .../rascalmpl/interpreter/utils/Profiler.java | 71 ++++++++++++++++++- 2 files changed, 71 insertions(+), 2 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index fa0c556435d..d6d60dc0909 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -37,7 +37,7 @@ "request": "launch", "mainClass": "org.rascalmpl.shell.RascalShell", "projectName": "rascal", - "vmArgs": "-Xss80m -Xmx2g", + "vmArgs": "-Xss80m -Xmx2g -Dorg.rascalmpl.profiling.flameGraph.script=C:/Users/sung-/Desktop/FlameGraph-1.0/flamegraph.pl", "console": "integratedTerminal" }, { diff --git a/src/org/rascalmpl/interpreter/utils/Profiler.java b/src/org/rascalmpl/interpreter/utils/Profiler.java index f7671310dfe..15badd74cf7 100644 --- a/src/org/rascalmpl/interpreter/utils/Profiler.java +++ b/src/org/rascalmpl/interpreter/utils/Profiler.java @@ -13,22 +13,29 @@ *******************************************************************************/ package org.rascalmpl.interpreter.utils; +import java.io.IOException; import java.io.PrintWriter; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Vector; +import java.util.stream.Collectors; import org.rascalmpl.ast.AbstractAST; +import org.rascalmpl.debug.IRascalFrame; import org.rascalmpl.interpreter.Evaluator; import org.rascalmpl.interpreter.env.Environment; +import org.rascalmpl.values.ValueFactoryFactory; + import io.usethesource.vallang.IList; import io.usethesource.vallang.IListWriter; import io.usethesource.vallang.ISourceLocation; import io.usethesource.vallang.IValueFactory; -import org.rascalmpl.values.ValueFactoryFactory; class Count { int ticks; @@ -72,6 +79,64 @@ public boolean equals(Object obj) { } } +class FlameGraph { + private final Map counts = new HashMap<>(); + + void sample(Evaluator eval) { + var frames = eval.getCallStack().stream(); + var folded = frames.map(FlameGraph::getFrameTitle).collect(Collectors.joining(";")); + var count = counts.computeIfAbsent(folded, k -> new Count()); + count.increment(); + } + + private static String getFrameTitle(IRascalFrame frame) { + var title = frame.getName(); + var callerLocation = frame.getCallerLocation(); + if (callerLocation != null) { + title += " at " + callerLocation; + } + return title; + } + + void write() { + var name = "flameGraph"; + var out = Path.of(name + ".out"); + var err = Path.of(name + ".err"); + var svg = Path.of(name + ".svg"); + + try { + Files.writeString(out, ""); + for (var e : counts.entrySet()) { + // Newlines must be `\n` for `flamegraph.pl` to work + var csq = String.format("%s %d\n", e.getKey(), e.getValue().getTicks()); + Files.writeString(out, csq, StandardOpenOption.APPEND); + } + + var scriptKey = "org.rascalmpl.profiling.flameGraph.script"; + var scriptValue = System.getProperty(scriptKey); + if (scriptValue != null) { + var script = Path.of(scriptValue); + if (Files.exists(script)) { + + ProcessBuilder processBuilder = new ProcessBuilder("perl", script.toString(), out.toString()); + processBuilder.redirectOutput(svg.toFile()); + processBuilder.redirectError(err.toFile()); + + Process process = processBuilder.start(); + try { + process.waitFor(); + } catch (InterruptedException e) { + // Ignore; doesn't matter + } + } + } + + } catch (IOException e) { + e.printStackTrace(); + } + } +} + public class Profiler extends Thread { private Evaluator eval; private volatile boolean running; @@ -79,6 +144,7 @@ public class Profiler extends Thread { private final Map ast; private final Map frame; private final Map names; + private final FlameGraph flameGraph = new FlameGraph(); public Profiler(Evaluator ev){ super("Rascal-Sampling-Profiler"); @@ -95,6 +161,8 @@ public void run(){ AbstractAST current = eval.getCurrentAST(); Environment env = eval.getCurrentEnvt(); String name = env.getName(); + + flameGraph.sample(eval); if (current != null) { ISourceLocation stat = current.getLocation(); @@ -162,6 +230,7 @@ public void report() { report("FRAMES", frame); eval.getOutPrinter().println(); report("ASTS", ast); + flameGraph.write(); } private void report(String title, Map data) { From f24c6defc0e37215213fa3df788ca9f7b8f07632 Mon Sep 17 00:00:00 2001 From: Sung-Shik Jongmans Date: Wed, 24 Jun 2026 15:52:30 +0200 Subject: [PATCH 4/7] Add `importedModulesResolved` cache --- .../interpreter/env/ModuleEnvironment.java | 47 ++++++++++++++----- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/src/org/rascalmpl/interpreter/env/ModuleEnvironment.java b/src/org/rascalmpl/interpreter/env/ModuleEnvironment.java index 1cbca8745ae..3c61a028175 100644 --- a/src/org/rascalmpl/interpreter/env/ModuleEnvironment.java +++ b/src/org/rascalmpl/interpreter/env/ModuleEnvironment.java @@ -133,6 +133,7 @@ public void clearLookupCaches() { importedModules.replaceAll((k, v) -> Optional.empty()); cachedGeneralKeywordParameters = null; cachedPublicFunctions = null; + cachedImportedModulesResolved = null; } /** @@ -382,12 +383,14 @@ public void addImport(String name, ModuleEnvironment env) { typeStore.importStore(env.typeStore); this.cachedGeneralKeywordParameters = null; this.cachedPublicFunctions = null; + this.cachedImportedModulesResolved = null; } void removeModule(String name) { importedModules.computeIfPresent(name, (k, v) -> Optional.empty()); this.cachedGeneralKeywordParameters = null; this.cachedPublicFunctions = null; + this.cachedImportedModulesResolved = null; } public void addExtend(String name) { @@ -397,6 +400,7 @@ public void addExtend(String name) { extended.add(name); this.cachedGeneralKeywordParameters = null; this.cachedPublicFunctions = null; + this.cachedImportedModulesResolved = null; } public List getTests() { @@ -453,6 +457,7 @@ public void unImport(String moduleName) { } cachedGeneralKeywordParameters = null; cachedPublicFunctions = null; + cachedImportedModulesResolved = null; } public void unExtend(String moduleName) { @@ -884,24 +889,44 @@ public ModuleEnvironment getImport(String moduleName) { return result.get(); } + private List cachedImportedModulesResolved = null; + private Iterable importedModulesResolved = - () -> new Iterator() { - Iterator>> iterator = importedModules.entrySet().iterator(); - @Override - public boolean hasNext() { - return iterator.hasNext(); - } - @Override - public ModuleEnvironment next() { - var entry = iterator.next(); + () -> getCachedImportedModulesResolved().iterator(); + // () -> new Iterator() { + // Iterator>> iterator = importedModules.entrySet().iterator(); + // @Override + // public boolean hasNext() { + // return iterator.hasNext(); + // } + // @Override + // public ModuleEnvironment next() { + // var entry = iterator.next(); + // var result = entry.getValue(); + // if (result.isEmpty()) { + // result = Optional.ofNullable(heap.getModule(entry.getKey())); + // entry.setValue(result); + // } + // return result.orElse(null); + // } + // }; + + private List getCachedImportedModulesResolved() { + if (cachedImportedModulesResolved == null) { + cachedImportedModulesResolved = new ArrayList<>(); + for (Entry> entry : importedModules.entrySet()) { var result = entry.getValue(); if (result.isEmpty()) { result = Optional.ofNullable(heap.getModule(entry.getKey())); entry.setValue(result); } - return result.orElse(null); + if (result.isPresent()) { + cachedImportedModulesResolved.add(result.get()); + } } - }; + } + return cachedImportedModulesResolved; + } @Override public void storeVariable(QualifiedName name, Result result) { From 264c063d9ed3bf13144e4dbc532b09e5e803b99f Mon Sep 17 00:00:00 2001 From: Sung-Shik Jongmans Date: Fri, 3 Jul 2026 13:56:55 +0200 Subject: [PATCH 5/7] Add preliminary unsafe mode --- src/org/rascalmpl/interpreter/IEvaluator.java | 1 + src/org/rascalmpl/interpreter/result/Result.java | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/org/rascalmpl/interpreter/IEvaluator.java b/src/org/rascalmpl/interpreter/IEvaluator.java index 529ff5b66ef..20219c6fdba 100644 --- a/src/org/rascalmpl/interpreter/IEvaluator.java +++ b/src/org/rascalmpl/interpreter/IEvaluator.java @@ -53,6 +53,7 @@ * Interface needs to be properly split up in different compoments. */ public interface IEvaluator extends IEvaluatorContext { + public static final boolean UNSAFE_MODE = true; public static final String LOADING_JOB_CONSTANT = "loading modules"; /** diff --git a/src/org/rascalmpl/interpreter/result/Result.java b/src/org/rascalmpl/interpreter/result/Result.java index a6847f9ecb8..b8c15d30f60 100644 --- a/src/org/rascalmpl/interpreter/result/Result.java +++ b/src/org/rascalmpl/interpreter/result/Result.java @@ -27,6 +27,7 @@ import org.rascalmpl.ast.Field; import org.rascalmpl.ast.Name; import org.rascalmpl.exceptions.ImplementationError; +import org.rascalmpl.interpreter.IEvaluator; import org.rascalmpl.interpreter.IEvaluatorContext; import org.rascalmpl.interpreter.control_exceptions.MatchFailed; import org.rascalmpl.interpreter.env.Environment; @@ -86,7 +87,7 @@ public abstract class Result implements Iterator> iter, IEvaluatorContext ctx) { // Check for null in case of void result or uninit. - if (value != null && !value.getType().isSubtypeOf(type)) { + if (!IEvaluator.UNSAFE_MODE && value != null && !value.getType().isSubtypeOf(type)) { throw new UnexpectedType(type, value.getType(), ctx.getCurrentAST()); } From cfc9c9c1b2fb6d36d0ea2d3514c2a6019af10aff Mon Sep 17 00:00:00 2001 From: Sung-Shik Jongmans Date: Fri, 3 Jul 2026 14:54:48 +0200 Subject: [PATCH 6/7] Replace linear searches for component scopes and filtered module scopes with log search --- .../compiler/lang/rascalcore/check/Import.rsc | 38 ++++++++++++------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/src/org/rascalmpl/compiler/lang/rascalcore/check/Import.rsc b/src/org/rascalmpl/compiler/lang/rascalcore/check/Import.rsc index 6b39268e7ef..145762e8c5f 100644 --- a/src/org/rascalmpl/compiler/lang/rascalcore/check/Import.rsc +++ b/src/org/rascalmpl/compiler/lang/rascalcore/check/Import.rsc @@ -425,14 +425,6 @@ ModuleStatus doSaveModule(set[MODID] component, map[MODID,set[MODID]] m_imports, set[MODID] filteredModuleScopes = {}; loc2moduleName = invertUnique(ms.moduleLocs); - bool isContainedInComponentScopes(loc inner, map[loc,loc] m){ - return any(cs <- component_scopes, isContainedIn(inner, cs, m)); - }; - - bool isContainedInFilteredModuleScopes(loc inner, map[loc,loc] m){ - return any(cs <- filteredModuleScopes, isContainedIn(inner, cs, m)); - }; - for(currentModule <- component){ start_save = cpuTime(); tm = transient_tms[currentModule]; @@ -453,9 +445,28 @@ ModuleStatus doSaveModule(set[MODID] component, map[MODID,set[MODID]] m_imports, m1.modelName = moduleId2moduleName(currentModule); m1.moduleLocs = (m1.modelName : currentModule); - m1.facts = (key : tm.facts[key] | key <- tm.facts, isContainedInFilteredModuleScopes(key, tm.logical2physical)); + list[loc] sortedComponentScopes = sort([tm.logical2physical[s] ? s | s <- component_scopes]); + list[loc] sortedFilteredModuleScopes = sort([tm.logical2physical[s] ? s | s <- filteredModuleScopes]); + + int sortedIndexOf(list[&T] sortedList, &T elem) { + int lo = 0; + int hi = size(sortedList) - 1; + while (lo <= hi) { + int middle = lo + floor((hi - lo) / 2); + if (sortedList[middle] < elem) { + lo = middle + 1; + } else if (sortedList[middle] > elem) { + hi = middle - 1; + } else { + return middle; + } + } + return -1; + } + + m1.facts = (key : tm.facts[key] | key <- tm.facts, sortedIndexOf(sortedFilteredModuleScopes, tm.logical2physical[key] ? key) != -1); - m1.specializedFacts = (key : tm.specializedFacts[key] | key <- tm.specializedFacts, isContainedInComponentScopes(key, tm.logical2physical), any(fms <- filteredModuleScopes, isContainedIn(key, fms))); + m1.specializedFacts = (key : tm.specializedFacts[key] | key <- tm.specializedFacts, sortedIndexOf(sortedComponentScopes, tm.logical2physical[key] ? key) != -1, sortedIndexOf(sortedFilteredModuleScopes, tm.logical2physical[key] ? key) != -1); m1.facts += m1.specializedFacts; m1.messages = [msg | msg <- tm.messages, isContainedIn(msg.at, currentModule, tm.logical2physical)]; @@ -492,11 +503,12 @@ ModuleStatus doSaveModule(set[MODID] component, map[MODID,set[MODID]] m_imports, // Filter model for current module and replace functions in defType by their defined type defs = for(tup: <- tm.defines){ - if( ( idRole in variableRoles ? ( isContainedInComponentScopes(defined, tm.logical2physical) + defined = tm.logical2physical[defined] ? defined; + if( ( idRole in variableRoles ? ( sortedIndexOf(sortedComponentScopes, defined) != -1 ) : ( idRole in keepInTModelRoles - && ( isContainedInComponentScopes(defined, tm.logical2physical) - || isContainedInFilteredModuleScopes(defined, tm.logical2physical) + && ( sortedIndexOf(sortedComponentScopes, defined) != -1 + || sortedIndexOf(sortedFilteredModuleScopes, defined) != -1 ) ) ) From a66cb86f7e071709eadc1540401494fb7120c867 Mon Sep 17 00:00:00 2001 From: Sung-Shik Jongmans Date: Fri, 31 Jul 2026 15:16:35 +0200 Subject: [PATCH 7/7] Replace log searches with map lookups --- pom.xml | 3 +- .../compiler/lang/rascalcore/check/Import.rsc | 42 ++++++++----------- 2 files changed, 19 insertions(+), 26 deletions(-) diff --git a/pom.xml b/pom.xml index af4336d8e52..7db059969d2 100644 --- a/pom.xml +++ b/pom.xml @@ -455,7 +455,8 @@ org.rascalmpl typepal - 0.17.0-RC3 + + 0.17.0-RC4-SNAPSHOT compile diff --git a/src/org/rascalmpl/compiler/lang/rascalcore/check/Import.rsc b/src/org/rascalmpl/compiler/lang/rascalcore/check/Import.rsc index 145762e8c5f..6ac0523ccc7 100644 --- a/src/org/rascalmpl/compiler/lang/rascalcore/check/Import.rsc +++ b/src/org/rascalmpl/compiler/lang/rascalcore/check/Import.rsc @@ -439,34 +439,27 @@ ModuleStatus doSaveModule(set[MODID] component, map[MODID,set[MODID]] m_imports, extendedModuleScopes += {*tm.paths[ems,importPath()] | MODID ems <- extendedModuleScopes}; // add imports of extended modules filteredModuleScopes = {m | MODID m <- (currentModule + imports), hasProperty(m, ms, checked())} + extendedModuleScopes; + map[str,loc] componentScopesByUri = (s.uri: s | loc s <- component_scopes, loc s := tm.logical2physical[s] ? s); + map[str,loc] filteredModuleScopesByUri = (s.uri: s | loc s <- filteredModuleScopes, loc s := tm.logical2physical[s] ? s); + + bool isContainedInComponentScopes(loc key) { + key = tm.logical2physical[key] ? key; + return key.uri in componentScopesByUri ? isContainedIn(key, componentScopesByUri[key.uri]) : false; + } + bool isContainedInFilteredModuleScopes(loc key) { + key = tm.logical2physical[key] ? key; + return key.uri in filteredModuleScopesByUri ? isContainedIn(key, filteredModuleScopesByUri[key.uri]) : false; + } + TModel m1 = tmodel(); m1.version = getCurrentTplVersion(); m1.rascalTplVersion = compilerConfig.rascalTplVersion; m1.modelName = moduleId2moduleName(currentModule); m1.moduleLocs = (m1.modelName : currentModule); - list[loc] sortedComponentScopes = sort([tm.logical2physical[s] ? s | s <- component_scopes]); - list[loc] sortedFilteredModuleScopes = sort([tm.logical2physical[s] ? s | s <- filteredModuleScopes]); - - int sortedIndexOf(list[&T] sortedList, &T elem) { - int lo = 0; - int hi = size(sortedList) - 1; - while (lo <= hi) { - int middle = lo + floor((hi - lo) / 2); - if (sortedList[middle] < elem) { - lo = middle + 1; - } else if (sortedList[middle] > elem) { - hi = middle - 1; - } else { - return middle; - } - } - return -1; - } - - m1.facts = (key : tm.facts[key] | key <- tm.facts, sortedIndexOf(sortedFilteredModuleScopes, tm.logical2physical[key] ? key) != -1); + m1.facts = (key : tm.facts[key] | key <- tm.facts, isContainedInFilteredModuleScopes(key)); - m1.specializedFacts = (key : tm.specializedFacts[key] | key <- tm.specializedFacts, sortedIndexOf(sortedComponentScopes, tm.logical2physical[key] ? key) != -1, sortedIndexOf(sortedFilteredModuleScopes, tm.logical2physical[key] ? key) != -1); + m1.specializedFacts = (key : tm.specializedFacts[key] | key <- tm.specializedFacts, isContainedInComponentScopes(key), isContainedInFilteredModuleScopes(key)); m1.facts += m1.specializedFacts; m1.messages = [msg | msg <- tm.messages, isContainedIn(msg.at, currentModule, tm.logical2physical)]; @@ -503,12 +496,11 @@ ModuleStatus doSaveModule(set[MODID] component, map[MODID,set[MODID]] m_imports, // Filter model for current module and replace functions in defType by their defined type defs = for(tup: <- tm.defines){ - defined = tm.logical2physical[defined] ? defined; - if( ( idRole in variableRoles ? ( sortedIndexOf(sortedComponentScopes, defined) != -1 + if( ( idRole in variableRoles ? ( isContainedInComponentScopes(defined) ) : ( idRole in keepInTModelRoles - && ( sortedIndexOf(sortedComponentScopes, defined) != -1 - || sortedIndexOf(sortedFilteredModuleScopes, defined) != -1 + && ( isContainedInComponentScopes(defined) + || isContainedInFilteredModuleScopes(defined) ) ) )