]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/Environments.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / environment / Environments.java
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/Environments.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/Environments.java
new file mode 100644 (file)
index 0000000..11bc257
--- /dev/null
@@ -0,0 +1,368 @@
+package org.simantics.scl.compiler.environment;
+
+import gnu.trove.procedure.TObjectProcedure;
+
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Consumer;
+
+import org.simantics.scl.compiler.common.names.Name;
+import org.simantics.scl.compiler.elaboration.contexts.TypeTranslationContext;
+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.AcceptAllNamespaceFilter;
+import org.simantics.scl.compiler.errors.ErrorLog;
+import org.simantics.scl.compiler.internal.codegen.effects.EffectConstructor;
+import org.simantics.scl.compiler.internal.parsing.exceptions.SCLSyntaxErrorException;
+import org.simantics.scl.compiler.internal.parsing.parser.SCLParserImpl;
+import org.simantics.scl.compiler.internal.parsing.types.TypeAst;
+import org.simantics.scl.compiler.top.SCLExpressionCompilationException;
+import org.simantics.scl.compiler.types.TCon;
+import org.simantics.scl.compiler.types.Type;
+
+public class Environments {
+    /**
+     * Get the SCLValue object representing an SCL value defined in a given environment.
+     * The name can be a local name or a fully scoped name with modules separated by periods. 
+     * @param environment  the environment
+     * @param localName  the name to be searched for
+     * @return  An SCLValue instance, or null if not found.
+     * @throws AmbiguousNameException  if the same name is found in multiple imported modules.
+     */
+    public static SCLValue getValue(Environment environment, String localName) throws AmbiguousNameException {
+       return getEnvironmentEntry(environment, localName, getValue);
+    }
+    
+    /**
+     * Get the SCLRelation object representing an SCL relation defined in a given environment.
+     * The name can be a local name or a fully scoped name with modules separated by periods. 
+     * @param environment  the environment
+     * @param localName  the name to be searched for
+     * @return  An SCLRelation instance, or null if not found.
+     * @throws AmbiguousNameException  if the same name is found in multiple imported modules.
+     */
+    public static SCLRelation getRelation(Environment environment, String localName) throws AmbiguousNameException {
+       return getEnvironmentEntry(environment, localName, getRelation);
+    }
+    
+    public static MappingRelation getMappingRelation(Environment environment, String localName) throws AmbiguousNameException {
+        return getEnvironmentEntry(environment, localName, getMappingRelation);
+    }
+    
+    public static TransformationRule getRule(Environment environment, String localName) throws AmbiguousNameException {
+        return getEnvironmentEntry(environment, localName, getRule);
+    }
+    
+    /**
+     * Get the SCLEntityType object representing an entity type defined in a given environment.
+     * The name can be a local name or a fully scoped name with modules separated by periods. 
+     * @param environment  the environment
+     * @param localName  the name to be searched for
+     * @return  An SCLEntityType instance, or null if not found.
+     * @throws AmbiguousNameException  if the same name is found in multiple imported modules.
+     */
+    public static SCLEntityType getEntityType(Environment environment, String localName) throws AmbiguousNameException {
+       return getEnvironmentEntry(environment, localName, getEntityType);
+    }
+    
+    /**
+     * Get the TypeConstructor object representing an type defined in a given environment.
+     * The name can be a local name or a fully scoped name with modules separated by periods. 
+     * @param environment  the environment
+     * @param localName  the name to be searched for
+     * @return  A TypeConstructor instance, or null if not found.
+     * @throws AmbiguousNameException  if the same name is found in multiple imported modules.
+     */
+    public static TypeConstructor getTypeConstructor(Environment environment, String localName) throws AmbiguousNameException {
+       return getEnvironmentEntry(environment, localName, getTypeConstructor);
+    }
+    
+    /**
+     * Get the EffectConstructor object representing an effect defined in a given environment.
+     * The name can be a local name or a fully scoped name with modules separated by periods. 
+     * @param environment  the environment
+     * @param localName  the name to be searched for
+     * @return  An EffectConstructor instance, or null if not found.
+     * @throws AmbiguousNameException  if the same name is found in multiple imported modules.
+     */
+    public static EffectConstructor getEffectConstructor(Environment environment, String localName) throws AmbiguousNameException {
+       return getEnvironmentEntry(environment, localName, getEffectConstructor);
+    }
+    
+    /**
+     * Get the TypeClass object representing a type class defined in a given environment.
+     * The name can be a local name or a fully scoped name with modules separated by periods. 
+     * @param environment  the environment
+     * @param localName  the name to be searched for
+     * @return  A TypeClass instance, or null if not found.
+     * @throws AmbiguousNameException  if the same name is found in multiple imported modules.
+     */
+    public static TypeClass getTypeClass(Environment environment, String localName) throws AmbiguousNameException {
+       return getEnvironmentEntry(environment, localName, getTypeClass);
+    }
+    
+    /**
+     * Get the TypeAlias object representing a type alias defined in a given environment.
+     * The name can be a local name or a fully scoped name with modules separated by periods. 
+     * @param environment  the environment
+     * @param localName  the name to be searched for
+     * @return  A TypeAlias instance, or null if not found.
+     * @throws AmbiguousNameException  if the same name is found in multiple imported modules.
+     */
+    public static TypeAlias getTypeAlias(Environment environment, String localName) throws AmbiguousNameException {
+       return getEnvironmentEntry(environment, localName, getTypeAlias);
+    }
+
+    /**
+     * Get the Name object representing an SCL value defined in a given environment.
+     * The name can be a local name or a fully scoped name with modules separated by periods. 
+     * @param environment  the environment
+     * @param localName  the name to be searched for
+     * @return  A Name instance, or null if not found.
+     * @throws AmbiguousNameException  if the same name is used in multiple imported modules.
+     */
+    public static Name getValueName(Environment environment, String localName) throws AmbiguousNameException {
+        SCLValue value = getValue(environment, localName);
+        if(value == null)
+            return null;
+        else
+            return value.getName();
+    }
+    
+    /**
+     * Get the TCon object representing a type declared in a given environment.
+     * The name can be a local name or a fully scoped name with modules separated by periods. 
+     * @param environment  the environment
+     * @param localName  the name to be searched for
+     * @return  A TCon instance, or null if not found.
+     * @throws AmbiguousNameException  if the same name is used in multiple imported modules.
+     */
+    public static TCon getTypeConstructorName(Environment environment, String localName) throws AmbiguousNameException {
+        TypeConstructor typeConstructor = getTypeConstructor(environment, localName);
+        if(typeConstructor == null)
+            return null;
+        else
+            return typeConstructor.name;
+    }
+    
+    /**
+     * Get the TCon object representing an effect declared in a given environment.
+     * The name can be a local name or a fully scoped name with modules separated by periods. 
+     * @param environment  the environment
+     * @param localName  the name to be searched for
+     * @return  A TCon instance, or null if not found.
+     * @throws AmbiguousNameException  if the same name is used in multiple imported modules.
+     */
+    public static TCon getEffectConstructorName(Environment environment, String localName) throws AmbiguousNameException {
+        EffectConstructor effectConstructor = getEffectConstructor(environment, localName);
+        if(effectConstructor == null)
+            return null;
+        else
+            return effectConstructor.name;
+    }
+    
+    /**
+     * Get the TCon object representing a type class declared in a given environment.
+     * The name can be a local name or a fully scoped name with modules separated by periods. 
+     * @param environment  the environment
+     * @param localName  the name to be searched for
+     * @return  A TCon instance, or null if not found.
+     * @throws AmbiguousNameException  if the same name is used in multiple imported modules.
+     */
+    public static TCon getTypeClassName(Environment environment, String localName) throws AmbiguousNameException {
+        TypeClass typeClass = getTypeClass(environment, localName);
+        if(typeClass == null)
+            return null;
+        else
+            return typeClass.name;
+    }
+    
+    /**
+     * Parse a given SCL type expression into a Type defined in a given environment.
+     * @param environment  the environment
+     * @param typeText  an SCL language type expression
+     * @return  A Type instance
+     * @throws SCLExpressionCompilationException  if the expression compilation fails
+     */
+    public static Type getType(Environment environment, String typeText) throws SCLExpressionCompilationException {
+        SCLParserImpl parser = new SCLParserImpl(new StringReader(typeText));
+        ErrorLog errorLog = new ErrorLog();
+        try {
+            TypeAst typeAst = (TypeAst)parser.parseType();
+            TypeTranslationContext context = new TypeTranslationContext(errorLog, environment);
+            Type type = context.toType(typeAst);
+            if(errorLog.isEmpty())
+                return type;
+        } catch(SCLSyntaxErrorException e) {
+            errorLog.log(e.location, e.getMessage());
+        } catch(Exception e) {
+            errorLog.log(e);
+        }
+        throw new SCLExpressionCompilationException(errorLog.getErrors());
+    }
+
+    /**
+     * Find a list of values in an environment that share a common prefix.
+     * The name can be a local name or a fully scoped name with modules separated by periods. 
+     * @param environment  An environment
+     * @param prefix  A name prefix
+     * @param values  A collection into which the found values are added
+     */
+    public static void findValuesForPrefix(Environment environment,
+            String prefix, TObjectProcedure<SCLValue> proc) {
+        findValuesForPrefix(environment.getLocalNamespace(), prefix, proc);
+    }
+    
+    public static List<SCLValue> findValuesForPrefix(Environment environment,
+            String prefix) {
+        final ArrayList<SCLValue> result = new ArrayList<SCLValue>();
+        findValuesForPrefix(environment, prefix,
+                new TObjectProcedure<SCLValue>() {
+                    @Override
+                    public boolean execute(SCLValue value) {
+                        result.add(value);
+                        return true;
+                    }
+                });
+        return result;
+    }
+    
+    /**
+     * Find a list of values in a namespace that share a common prefix.
+     * The name can be a local name or a fully scoped name with modules separated by periods. 
+     * @param namespace  An namespace
+     * @param prefix  A name prefix
+     * @param values  A collection into which the found values are added
+     */
+    public static void findValuesForPrefix(Namespace namespace,
+            String prefix, TObjectProcedure<SCLValue> proc) {
+        int p = prefix.indexOf('.');
+        if(p > 0) {
+            Namespace childNamespace = namespace.getNamespace(prefix.substring(0, p));
+            if(childNamespace != null)
+                findValuesForPrefix(childNamespace, prefix.substring(p+1), proc);
+        }
+        else
+            namespace.findValuesForPrefix(prefix, AcceptAllNamespaceFilter.INSTANCE, proc);
+    }
+    
+    public static List<TCon> findTypesForPrefix(Environment environment, String prefix) {
+        final List<TCon> results = new ArrayList<>();
+        findTypesForPrefix(environment.getLocalNamespace(), prefix, new Consumer<TCon>() {
+
+            @Override
+            public void accept(TCon tcon) {
+                results.add(tcon);
+            }
+        });
+        return results;
+    }
+    
+    /**
+     * Find a list of values in a namespace that share a common prefix.
+     * The name can be a local name or a fully scoped name with modules separated by periods. 
+     * @param namespace  An namespace
+     * @param prefix  A name prefix
+     * @param values  A collection into which the found values are added
+     */
+    public static void findTypesForPrefix(Namespace namespace, String prefix, Consumer<TCon> consumer) {
+        int p = prefix.indexOf('.');
+        if(p > 0) {
+            Namespace childNamespace = namespace.getNamespace(prefix.substring(0, p));
+            if(childNamespace != null)
+                findTypesForPrefix(childNamespace, prefix.substring(p+1), consumer);
+        }
+        else
+            namespace.findTypesForPrefix(prefix, AcceptAllNamespaceFilter.INSTANCE, consumer);
+    }
+    
+    /* Accessor objects for retrieving values from a namespace. */
+    
+    private static interface NamespaceValueAccessor<T> {
+       public T get(Namespace ns, String name) throws AmbiguousNameException;
+    }
+    
+    private static final NamespaceValueAccessor<SCLValue> getValue = new NamespaceValueAccessor<SCLValue>() {
+               @Override
+               public SCLValue get(Namespace ns, String name) throws AmbiguousNameException {
+                       return ns.getValue(name);
+               }               
+       };
+    
+    private static final NamespaceValueAccessor<SCLRelation> getRelation = new NamespaceValueAccessor<SCLRelation>() {
+               @Override
+               public SCLRelation get(Namespace ns, String name) throws AmbiguousNameException {
+                       return ns.getRelation(name);
+               }               
+       };
+    
+       private static final NamespaceValueAccessor<MappingRelation> getMappingRelation = new NamespaceValueAccessor<MappingRelation>() {
+        @Override
+        public MappingRelation get(Namespace ns, String name) throws AmbiguousNameException {
+            return ns.getMappingRelation(name);
+        }
+    };
+    
+    private static final NamespaceValueAccessor<TransformationRule> getRule = new NamespaceValueAccessor<TransformationRule>() {
+        @Override
+        public TransformationRule get(Namespace ns, String name) throws AmbiguousNameException {
+            return ns.getRule(name);
+        }
+    };
+    
+    private static final NamespaceValueAccessor<SCLEntityType> getEntityType = new NamespaceValueAccessor<SCLEntityType>() {
+               @Override
+               public SCLEntityType get(Namespace ns, String name) throws AmbiguousNameException {
+                       return ns.getEntityType(name);
+               }               
+       };
+    
+    private static final NamespaceValueAccessor<TypeConstructor> getTypeConstructor = new NamespaceValueAccessor<TypeConstructor>() {
+               @Override
+               public TypeConstructor get(Namespace ns, String name) throws AmbiguousNameException {
+                       return ns.getTypeConstructor(name);
+               }               
+       };
+    
+    private static final NamespaceValueAccessor<EffectConstructor> getEffectConstructor = new NamespaceValueAccessor<EffectConstructor>() {
+               @Override
+               public EffectConstructor get(Namespace ns, String name) throws AmbiguousNameException {
+                       return ns.getEffectConstructor(name);
+               }               
+       };
+    
+    private static final NamespaceValueAccessor<TypeClass> getTypeClass = new NamespaceValueAccessor<TypeClass>() {
+               @Override
+               public TypeClass get(Namespace ns, String name) throws AmbiguousNameException {
+                       return ns.getTypeClass(name);
+               }               
+       };
+    
+    private static final NamespaceValueAccessor<TypeAlias> getTypeAlias = new NamespaceValueAccessor<TypeAlias>() {
+               @Override
+               public TypeAlias get(Namespace ns, String name) throws AmbiguousNameException {
+                       return ns.getTypeAlias(name);
+               }               
+       };
+    
+       private static <T> T getEnvironmentEntry(Environment environment, String localName, NamespaceValueAccessor<T> accessor) throws AmbiguousNameException {
+        Namespace namespace = environment.getLocalNamespace();
+        int curPos = 0;
+        while(true) {
+            int pos = localName.indexOf('.', curPos);
+            if(pos < 0)
+                return accessor.get(namespace, localName.substring(curPos));
+            namespace = namespace.getNamespace(localName.substring(curPos, pos));
+            if(namespace == null)
+                return null;
+            curPos = pos + 1;
+        }
+    }
+}