--- /dev/null
+package org.simantics.scl.compiler.environment;
+
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.procedure.TObjectProcedure;
+
+import java.util.ArrayList;
+import java.util.function.Consumer;
+
+import org.simantics.scl.compiler.elaboration.modules.SCLValue;
+import org.simantics.scl.compiler.elaboration.modules.TypeAlias;
+import org.simantics.scl.compiler.elaboration.modules.TypeClass;
+import org.simantics.scl.compiler.elaboration.modules.TypeConstructor;
+import org.simantics.scl.compiler.elaboration.relations.SCLEntityType;
+import org.simantics.scl.compiler.elaboration.relations.SCLRelation;
+import org.simantics.scl.compiler.elaboration.rules.MappingRelation;
+import org.simantics.scl.compiler.elaboration.rules.TransformationRule;
+import org.simantics.scl.compiler.environment.filter.NamespaceFilter;
+import org.simantics.scl.compiler.environment.filter.NamespaceFilters;
+import org.simantics.scl.compiler.internal.codegen.effects.EffectConstructor;
+import org.simantics.scl.compiler.module.Module;
+import org.simantics.scl.compiler.types.TCon;
+
+public class NamespaceImpl implements Namespace {
+
+ private final THashMap<String, Namespace> namespaceMap;
+ private final ModuleImport[] moduleImports;
+
+ public static class ModuleImport {
+ public final Module module;
+ public NamespaceFilter filter;
+
+ public ModuleImport(Module module, NamespaceFilter filter) {
+ this.module = module;
+ this.filter = filter;
+ }
+ }
+
+ public NamespaceImpl(THashMap<String, Namespace> namespaceMap,
+ ModuleImport[] moduleImports) {
+ this.namespaceMap = namespaceMap;
+ this.moduleImports = moduleImports;
+ }
+
+ @Override
+ public Namespace getNamespace(String name) {
+ return namespaceMap.get(name);
+ }
+
+ @Override
+ public SCLValue getValue(String name) throws AmbiguousNameException {
+ SCLValue result = null, temp;
+ Module resultModule = null;
+ ArrayList<String> conflictingModules = null;
+ for(ModuleImport moduleImport : moduleImports) {
+ Module module = moduleImport.module;
+ temp = module.getValue(name);
+ if(temp != null
+ && !temp.isPrivate()
+ && moduleImport.filter.isValueIncluded(name)) {
+ if(result != null) {
+ if(conflictingModules == null) {
+ conflictingModules = new ArrayList<String>(2);
+ conflictingModules.add(resultModule.getName());
+ }
+ conflictingModules.add(module.getName());
+ }
+ else {
+ result = temp;
+ resultModule = module;
+ }
+ }
+ }
+ if(conflictingModules != null)
+ throw new AmbiguousNameException(conflictingModules, name);
+ return result;
+ }
+
+ @Override
+ public SCLRelation getRelation(String name) throws AmbiguousNameException {
+ SCLRelation result = null, temp;
+ Module resultModule = null;
+ ArrayList<String> conflictingModules = null;
+ for(ModuleImport moduleImport : moduleImports) {
+ Module module = moduleImport.module;
+ temp = module.getRelation(name);
+ if(temp != null) {
+ if(result != null) {
+ if(conflictingModules == null) {
+ conflictingModules = new ArrayList<String>(2);
+ conflictingModules.add(resultModule.getName());
+ }
+ conflictingModules.add(module.getName());
+ }
+ else {
+ result = temp;
+ resultModule = module;
+ }
+ }
+ }
+ if(conflictingModules != null)
+ throw new AmbiguousNameException(conflictingModules, name);
+ return result;
+ }
+
+ @Override
+ public SCLEntityType getEntityType(String name)
+ throws AmbiguousNameException {
+ SCLEntityType result = null, temp;
+ Module resultModule = null;
+ ArrayList<String> conflictingModules = null;
+ for(ModuleImport moduleImport : moduleImports) {
+ Module module = moduleImport.module;
+ temp = module.getEntityType(name);
+ if(temp != null) {
+ if(result != null) {
+ if(conflictingModules == null) {
+ conflictingModules = new ArrayList<String>(2);
+ conflictingModules.add(resultModule.getName());
+ }
+ conflictingModules.add(module.getName());
+ }
+ else {
+ result = temp;
+ resultModule = module;
+ }
+ }
+ }
+ if(conflictingModules != null)
+ throw new AmbiguousNameException(conflictingModules, name);
+ return result;
+ }
+
+ @Override
+ public TypeConstructor getTypeConstructor(String name)
+ throws AmbiguousNameException {
+ TypeConstructor result = null, temp;
+ Module resultModule = null;
+ ArrayList<String> conflictingModules = null;
+ for(ModuleImport moduleImport : moduleImports) {
+ Module module = moduleImport.module;
+ temp = module.getTypeConstructor(name);
+ if(temp != null) {
+ if(result != null) {
+ if(conflictingModules == null) {
+ conflictingModules = new ArrayList<String>(2);
+ conflictingModules.add(resultModule.getName());
+ }
+ conflictingModules.add(module.getName());
+ }
+ else {
+ result = temp;
+ resultModule = module;
+ }
+ }
+ }
+ if(conflictingModules != null)
+ throw new AmbiguousNameException(conflictingModules, name);
+ return result;
+ }
+
+ @Override
+ public EffectConstructor getEffectConstructor(String name)
+ throws AmbiguousNameException {
+ EffectConstructor result = null, temp;
+ Module resultModule = null;
+ ArrayList<String> conflictingModules = null;
+ for(ModuleImport moduleImport : moduleImports) {
+ Module module = moduleImport.module;
+ temp = module.getEffectConstructor(name);
+ if(temp != null) {
+ if(result != null) {
+ if(conflictingModules == null) {
+ conflictingModules = new ArrayList<String>(2);
+ conflictingModules.add(resultModule.getName());
+ }
+ conflictingModules.add(module.getName());
+ }
+ else {
+ result = temp;
+ resultModule = module;
+ }
+ }
+ }
+ if(conflictingModules != null)
+ throw new AmbiguousNameException(conflictingModules, name);
+ return result;
+ }
+
+ @Override
+ public TypeClass getTypeClass(String name) throws AmbiguousNameException {
+ TypeClass result = null, temp;
+ Module resultModule = null;
+ ArrayList<String> conflictingModules = null;
+ for(ModuleImport moduleImport : moduleImports) {
+ Module module = moduleImport.module;
+ temp = module.getTypeClass(name);
+ if(temp != null) {
+ if(result != null) {
+ if(conflictingModules == null) {
+ conflictingModules = new ArrayList<String>(2);
+ conflictingModules.add(resultModule.getName());
+ }
+ conflictingModules.add(module.getName());
+ }
+ else {
+ result = temp;
+ resultModule = module;
+ }
+ }
+ }
+ if(conflictingModules != null)
+ throw new AmbiguousNameException(conflictingModules, name);
+ return result;
+ }
+
+ @Override
+ public TypeAlias getTypeAlias(String name) throws AmbiguousNameException {
+ TypeAlias result = null, temp;
+ Module resultModule = null;
+ ArrayList<String> conflictingModules = null;
+ for(ModuleImport moduleImport : moduleImports) {
+ Module module = moduleImport.module;
+ temp = module.getTypeAlias(name);
+ if(temp != null) {
+ if(result != null) {
+ if(conflictingModules == null) {
+ conflictingModules = new ArrayList<String>(2);
+ conflictingModules.add(resultModule.getName());
+ }
+ conflictingModules.add(module.getName());
+ }
+ else {
+ result = temp;
+ resultModule = module;
+ }
+ }
+ }
+ if(conflictingModules != null)
+ throw new AmbiguousNameException(conflictingModules, name);
+ return result;
+ }
+
+ @Override
+ public MappingRelation getMappingRelation(String name) throws AmbiguousNameException {
+ MappingRelation result = null, temp;
+ Module resultModule = null;
+ ArrayList<String> conflictingModules = null;
+ for(ModuleImport moduleImport : moduleImports) {
+ Module module = moduleImport.module;
+ temp = module.getMappingRelation(name);
+ if(temp != null) {
+ if(result != null) {
+ if(conflictingModules == null) {
+ conflictingModules = new ArrayList<String>(2);
+ conflictingModules.add(resultModule.getName());
+ }
+ conflictingModules.add(module.getName());
+ }
+ else {
+ result = temp;
+ resultModule = module;
+ }
+ }
+ }
+ if(conflictingModules != null)
+ throw new AmbiguousNameException(conflictingModules, name);
+ return result;
+ }
+
+ @Override
+ public TransformationRule getRule(String name) throws AmbiguousNameException {
+ TransformationRule result = null, temp;
+ Module resultModule = null;
+ ArrayList<String> conflictingModules = null;
+ for(ModuleImport moduleImport : moduleImports) {
+ Module module = moduleImport.module;
+ temp = module.getRule(name);
+ if(temp != null) {
+ if(result != null) {
+ if(conflictingModules == null) {
+ conflictingModules = new ArrayList<String>(2);
+ conflictingModules.add(resultModule.getName());
+ }
+ conflictingModules.add(module.getName());
+ }
+ else {
+ result = temp;
+ resultModule = module;
+ }
+ }
+ }
+ if(conflictingModules != null)
+ throw new AmbiguousNameException(conflictingModules, name);
+ return result;
+ }
+
+ @Override
+ public void findValuesForPrefix(String prefix, NamespaceFilter filter, TObjectProcedure<SCLValue> proc) {
+ for(ModuleImport moduleImport : moduleImports)
+ moduleImport.module.findValuesForPrefix(prefix,
+ NamespaceFilters.intersection(filter, moduleImport.filter),
+ proc);
+ }
+
+ @Override
+ public void findTypesForPrefix(String prefix, NamespaceFilter filter, Consumer<TCon> consumer) {
+ for(ModuleImport moduleImport : moduleImports)
+ moduleImport.module.findTypesForPrefix(prefix,
+ NamespaceFilters.intersection(filter, moduleImport.filter),
+ consumer);
+ }
+
+}