X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.scl.compiler%2Fsrc%2Forg%2Fsimantics%2Fscl%2Fcompiler%2Fenvironment%2FEnvironments.java;fp=bundles%2Forg.simantics.scl.compiler%2Fsrc%2Forg%2Fsimantics%2Fscl%2Fcompiler%2Fenvironment%2FEnvironments.java;h=11bc2577dfcaf41d92186bcbfa584387f440d16a;hb=969bd23cab98a79ca9101af33334000879fb60c5;hp=0000000000000000000000000000000000000000;hpb=866dba5cd5a3929bbeae85991796acb212338a08;p=simantics%2Fplatform.git 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 index 000000000..11bc2577d --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/Environments.java @@ -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 proc) { + findValuesForPrefix(environment.getLocalNamespace(), prefix, proc); + } + + public static List findValuesForPrefix(Environment environment, + String prefix) { + final ArrayList result = new ArrayList(); + findValuesForPrefix(environment, prefix, + new TObjectProcedure() { + @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 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 findTypesForPrefix(Environment environment, String prefix) { + final List results = new ArrayList<>(); + findTypesForPrefix(environment.getLocalNamespace(), prefix, new Consumer() { + + @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 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 { + public T get(Namespace ns, String name) throws AmbiguousNameException; + } + + private static final NamespaceValueAccessor getValue = new NamespaceValueAccessor() { + @Override + public SCLValue get(Namespace ns, String name) throws AmbiguousNameException { + return ns.getValue(name); + } + }; + + private static final NamespaceValueAccessor getRelation = new NamespaceValueAccessor() { + @Override + public SCLRelation get(Namespace ns, String name) throws AmbiguousNameException { + return ns.getRelation(name); + } + }; + + private static final NamespaceValueAccessor getMappingRelation = new NamespaceValueAccessor() { + @Override + public MappingRelation get(Namespace ns, String name) throws AmbiguousNameException { + return ns.getMappingRelation(name); + } + }; + + private static final NamespaceValueAccessor getRule = new NamespaceValueAccessor() { + @Override + public TransformationRule get(Namespace ns, String name) throws AmbiguousNameException { + return ns.getRule(name); + } + }; + + private static final NamespaceValueAccessor getEntityType = new NamespaceValueAccessor() { + @Override + public SCLEntityType get(Namespace ns, String name) throws AmbiguousNameException { + return ns.getEntityType(name); + } + }; + + private static final NamespaceValueAccessor getTypeConstructor = new NamespaceValueAccessor() { + @Override + public TypeConstructor get(Namespace ns, String name) throws AmbiguousNameException { + return ns.getTypeConstructor(name); + } + }; + + private static final NamespaceValueAccessor getEffectConstructor = new NamespaceValueAccessor() { + @Override + public EffectConstructor get(Namespace ns, String name) throws AmbiguousNameException { + return ns.getEffectConstructor(name); + } + }; + + private static final NamespaceValueAccessor getTypeClass = new NamespaceValueAccessor() { + @Override + public TypeClass get(Namespace ns, String name) throws AmbiguousNameException { + return ns.getTypeClass(name); + } + }; + + private static final NamespaceValueAccessor getTypeAlias = new NamespaceValueAccessor() { + @Override + public TypeAlias get(Namespace ns, String name) throws AmbiguousNameException { + return ns.getTypeAlias(name); + } + }; + + private static T getEnvironmentEntry(Environment environment, String localName, NamespaceValueAccessor 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; + } + } +}