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 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 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 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(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 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(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 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(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 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(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 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(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 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(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 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(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 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(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 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(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 proc) { for(ModuleImport moduleImport : moduleImports) moduleImport.module.findValuesForPrefix(prefix, NamespaceFilters.intersection(filter, moduleImport.filter), proc); } @Override public void findTypesForPrefix(String prefix, NamespaceFilter filter, Consumer consumer) { for(ModuleImport moduleImport : moduleImports) moduleImport.module.findTypesForPrefix(prefix, NamespaceFilters.intersection(filter, moduleImport.filter), consumer); } }