1 package org.simantics.scl.compiler.environment;
3 import java.io.StringReader;
4 import java.util.ArrayList;
6 import java.util.function.Consumer;
8 import org.simantics.scl.compiler.common.names.Name;
9 import org.simantics.scl.compiler.elaboration.contexts.TypeTranslationContext;
10 import org.simantics.scl.compiler.elaboration.modules.SCLValue;
11 import org.simantics.scl.compiler.elaboration.modules.TypeAlias;
12 import org.simantics.scl.compiler.elaboration.modules.TypeClass;
13 import org.simantics.scl.compiler.elaboration.modules.TypeConstructor;
14 import org.simantics.scl.compiler.elaboration.relations.SCLEntityType;
15 import org.simantics.scl.compiler.elaboration.relations.SCLRelation;
16 import org.simantics.scl.compiler.elaboration.rules.MappingRelation;
17 import org.simantics.scl.compiler.elaboration.rules.TransformationRule;
18 import org.simantics.scl.compiler.environment.filter.AcceptAllNamespaceFilter;
19 import org.simantics.scl.compiler.errors.ErrorLog;
20 import org.simantics.scl.compiler.internal.codegen.effects.EffectConstructor;
21 import org.simantics.scl.compiler.internal.parsing.exceptions.SCLSyntaxErrorException;
22 import org.simantics.scl.compiler.internal.parsing.parser.SCLParserImpl;
23 import org.simantics.scl.compiler.internal.parsing.types.TypeAst;
24 import org.simantics.scl.compiler.top.SCLExpressionCompilationException;
25 import org.simantics.scl.compiler.types.TCon;
26 import org.simantics.scl.compiler.types.Type;
28 import gnu.trove.procedure.TObjectProcedure;
30 public class Environments {
32 * Get the SCLValue object representing an SCL value defined in a given environment.
33 * The name can be a local name or a fully scoped name with modules separated by periods.
34 * @param environment the environment
35 * @param localName the name to be searched for
36 * @return An SCLValue instance, or null if not found.
37 * @throws AmbiguousNameException if the same name is found in multiple imported modules.
39 public static SCLValue getValue(Environment environment, String localName) throws AmbiguousNameException {
40 return getEnvironmentEntry(environment, localName, getValue);
44 * Get the SCLRelation object representing an SCL relation defined in a given environment.
45 * The name can be a local name or a fully scoped name with modules separated by periods.
46 * @param environment the environment
47 * @param localName the name to be searched for
48 * @return An SCLRelation instance, or null if not found.
49 * @throws AmbiguousNameException if the same name is found in multiple imported modules.
51 public static SCLRelation getRelation(Environment environment, String localName) throws AmbiguousNameException {
52 return getEnvironmentEntry(environment, localName, getRelation);
55 public static MappingRelation getMappingRelation(Environment environment, String localName) throws AmbiguousNameException {
56 return getEnvironmentEntry(environment, localName, getMappingRelation);
59 public static TransformationRule getRule(Environment environment, String localName) throws AmbiguousNameException {
60 return getEnvironmentEntry(environment, localName, getRule);
64 * Get the SCLEntityType object representing an entity type defined in a given environment.
65 * The name can be a local name or a fully scoped name with modules separated by periods.
66 * @param environment the environment
67 * @param localName the name to be searched for
68 * @return An SCLEntityType instance, or null if not found.
69 * @throws AmbiguousNameException if the same name is found in multiple imported modules.
71 public static SCLEntityType getEntityType(Environment environment, String localName) throws AmbiguousNameException {
72 return getEnvironmentEntry(environment, localName, getEntityType);
76 * Get the TypeConstructor object representing an type defined in a given environment.
77 * The name can be a local name or a fully scoped name with modules separated by periods.
78 * @param environment the environment
79 * @param localName the name to be searched for
80 * @return A TypeConstructor instance, or null if not found.
81 * @throws AmbiguousNameException if the same name is found in multiple imported modules.
83 public static TypeConstructor getTypeConstructor(Environment environment, String localName) throws AmbiguousNameException {
84 return getEnvironmentEntry(environment, localName, getTypeConstructor);
88 * Get the EffectConstructor object representing an effect defined in a given environment.
89 * The name can be a local name or a fully scoped name with modules separated by periods.
90 * @param environment the environment
91 * @param localName the name to be searched for
92 * @return An EffectConstructor instance, or null if not found.
93 * @throws AmbiguousNameException if the same name is found in multiple imported modules.
95 public static EffectConstructor getEffectConstructor(Environment environment, String localName) throws AmbiguousNameException {
96 return getEnvironmentEntry(environment, localName, getEffectConstructor);
100 * Get the TypeClass object representing a type class defined in a given environment.
101 * The name can be a local name or a fully scoped name with modules separated by periods.
102 * @param environment the environment
103 * @param localName the name to be searched for
104 * @return A TypeClass instance, or null if not found.
105 * @throws AmbiguousNameException if the same name is found in multiple imported modules.
107 public static TypeClass getTypeClass(Environment environment, String localName) throws AmbiguousNameException {
108 return getEnvironmentEntry(environment, localName, getTypeClass);
112 * Get the TypeAlias object representing a type alias defined in a given environment.
113 * The name can be a local name or a fully scoped name with modules separated by periods.
114 * @param environment the environment
115 * @param localName the name to be searched for
116 * @return A TypeAlias instance, or null if not found.
117 * @throws AmbiguousNameException if the same name is found in multiple imported modules.
119 public static TypeAlias getTypeAlias(Environment environment, String localName) throws AmbiguousNameException {
120 return getEnvironmentEntry(environment, localName, getTypeAlias);
124 * Get the Name object representing an SCL value defined in a given environment.
125 * The name can be a local name or a fully scoped name with modules separated by periods.
126 * @param environment the environment
127 * @param localName the name to be searched for
128 * @return A Name instance, or null if not found.
129 * @throws AmbiguousNameException if the same name is used in multiple imported modules.
131 public static Name getValueName(Environment environment, String localName) throws AmbiguousNameException {
132 SCLValue value = getValue(environment, localName);
136 return value.getName();
140 * Get the TCon object representing a type declared in a given environment.
141 * The name can be a local name or a fully scoped name with modules separated by periods.
142 * @param environment the environment
143 * @param localName the name to be searched for
144 * @return A TCon instance, or null if not found.
145 * @throws AmbiguousNameException if the same name is used in multiple imported modules.
147 public static TCon getTypeConstructorName(Environment environment, String localName) throws AmbiguousNameException {
148 TypeConstructor typeConstructor = getTypeConstructor(environment, localName);
149 if(typeConstructor == null)
152 return typeConstructor.name;
156 * Get the TCon object representing an effect declared in a given environment.
157 * The name can be a local name or a fully scoped name with modules separated by periods.
158 * @param environment the environment
159 * @param localName the name to be searched for
160 * @return A TCon instance, or null if not found.
161 * @throws AmbiguousNameException if the same name is used in multiple imported modules.
163 public static TCon getEffectConstructorName(Environment environment, String localName) throws AmbiguousNameException {
164 EffectConstructor effectConstructor = getEffectConstructor(environment, localName);
165 if(effectConstructor == null)
168 return effectConstructor.name;
172 * Get the TCon object representing a type class declared in a given environment.
173 * The name can be a local name or a fully scoped name with modules separated by periods.
174 * @param environment the environment
175 * @param localName the name to be searched for
176 * @return A TCon instance, or null if not found.
177 * @throws AmbiguousNameException if the same name is used in multiple imported modules.
179 public static TCon getTypeClassName(Environment environment, String localName) throws AmbiguousNameException {
180 TypeClass typeClass = getTypeClass(environment, localName);
181 if(typeClass == null)
184 return typeClass.name;
188 * Parse a given SCL type expression into a Type defined in a given environment.
189 * @param environment the environment
190 * @param typeText an SCL language type expression
191 * @return A Type instance
192 * @throws SCLExpressionCompilationException if the expression compilation fails
194 public static Type getType(Environment environment, String typeText) throws SCLExpressionCompilationException {
195 SCLParserImpl parser = new SCLParserImpl(new StringReader(typeText));
196 ErrorLog errorLog = new ErrorLog();
198 TypeAst typeAst = (TypeAst)parser.parseType();
199 TypeTranslationContext context = new TypeTranslationContext(errorLog, environment);
200 Type type = context.toType(typeAst);
201 if(errorLog.isEmpty())
203 } catch(SCLSyntaxErrorException e) {
204 errorLog.log(e.location, e.getMessage());
205 } catch(Exception e) {
208 throw new SCLExpressionCompilationException(errorLog.getErrors());
212 * Find a list of values in an environment that share a common prefix.
213 * The name can be a local name or a fully scoped name with modules separated by periods.
214 * @param environment An environment
215 * @param prefix A name prefix
216 * @param values A collection into which the found values are added
218 public static void findValuesForPrefix(Environment environment,
219 String prefix, TObjectProcedure<SCLValue> proc) {
220 findValuesForPrefix(environment.getLocalNamespace(), prefix, proc);
223 public static List<SCLValue> findValuesForPrefix(Environment environment,
225 final ArrayList<SCLValue> result = new ArrayList<SCLValue>();
226 findValuesForPrefix(environment, prefix,
227 new TObjectProcedure<SCLValue>() {
229 public boolean execute(SCLValue value) {
238 * Find a list of values in a namespace that share a common prefix.
239 * The name can be a local name or a fully scoped name with modules separated by periods.
240 * @param namespace An namespace
241 * @param prefix A name prefix
242 * @param values A collection into which the found values are added
244 public static void findValuesForPrefix(Namespace namespace,
245 String prefix, TObjectProcedure<SCLValue> proc) {
246 int p = prefix.indexOf('.');
248 Namespace childNamespace = namespace.getNamespace(prefix.substring(0, p));
249 if(childNamespace != null)
250 findValuesForPrefix(childNamespace, prefix.substring(p+1), proc);
253 namespace.findValuesForPrefix(prefix, AcceptAllNamespaceFilter.INSTANCE, proc);
256 public static List<TCon> findTypesForPrefix(Environment environment, String prefix) {
257 final List<TCon> results = new ArrayList<>();
258 findTypesForPrefix(environment.getLocalNamespace(), prefix, new Consumer<TCon>() {
261 public void accept(TCon tcon) {
269 * Find a list of values in a namespace that share a common prefix.
270 * The name can be a local name or a fully scoped name with modules separated by periods.
271 * @param namespace An namespace
272 * @param prefix A name prefix
273 * @param values A collection into which the found values are added
275 public static void findTypesForPrefix(Namespace namespace, String prefix, Consumer<TCon> consumer) {
276 int p = prefix.indexOf('.');
278 Namespace childNamespace = namespace.getNamespace(prefix.substring(0, p));
279 if(childNamespace != null)
280 findTypesForPrefix(childNamespace, prefix.substring(p+1), consumer);
283 namespace.findTypesForPrefix(prefix, AcceptAllNamespaceFilter.INSTANCE, consumer);
286 /* Accessor objects for retrieving values from a namespace. */
288 private static interface NamespaceValueAccessor<T> {
289 public T get(Namespace ns, String name) throws AmbiguousNameException;
292 private static final NamespaceValueAccessor<SCLValue> getValue = new NamespaceValueAccessor<SCLValue>() {
294 public SCLValue get(Namespace ns, String name) throws AmbiguousNameException {
295 return ns.getValue(name);
299 private static final NamespaceValueAccessor<SCLRelation> getRelation = new NamespaceValueAccessor<SCLRelation>() {
301 public SCLRelation get(Namespace ns, String name) throws AmbiguousNameException {
302 return ns.getRelation(name);
306 private static final NamespaceValueAccessor<MappingRelation> getMappingRelation = new NamespaceValueAccessor<MappingRelation>() {
308 public MappingRelation get(Namespace ns, String name) throws AmbiguousNameException {
309 return ns.getMappingRelation(name);
313 private static final NamespaceValueAccessor<TransformationRule> getRule = new NamespaceValueAccessor<TransformationRule>() {
315 public TransformationRule get(Namespace ns, String name) throws AmbiguousNameException {
316 return ns.getRule(name);
320 private static final NamespaceValueAccessor<SCLEntityType> getEntityType = new NamespaceValueAccessor<SCLEntityType>() {
322 public SCLEntityType get(Namespace ns, String name) throws AmbiguousNameException {
323 return ns.getEntityType(name);
327 private static final NamespaceValueAccessor<TypeConstructor> getTypeConstructor = new NamespaceValueAccessor<TypeConstructor>() {
329 public TypeConstructor get(Namespace ns, String name) throws AmbiguousNameException {
330 return ns.getTypeConstructor(name);
334 private static final NamespaceValueAccessor<EffectConstructor> getEffectConstructor = new NamespaceValueAccessor<EffectConstructor>() {
336 public EffectConstructor get(Namespace ns, String name) throws AmbiguousNameException {
337 return ns.getEffectConstructor(name);
341 private static final NamespaceValueAccessor<TypeClass> getTypeClass = new NamespaceValueAccessor<TypeClass>() {
343 public TypeClass get(Namespace ns, String name) throws AmbiguousNameException {
344 return ns.getTypeClass(name);
348 private static final NamespaceValueAccessor<TypeAlias> getTypeAlias = new NamespaceValueAccessor<TypeAlias>() {
350 public TypeAlias get(Namespace ns, String name) throws AmbiguousNameException {
351 return ns.getTypeAlias(name);
355 private static <T> T getEnvironmentEntry(Environment environment, String localName, NamespaceValueAccessor<T> accessor) throws AmbiguousNameException {
356 Namespace namespace = environment.getLocalNamespace();
359 int pos = localName.indexOf('.', curPos);
361 return accessor.get(namespace, localName.substring(curPos));
362 namespace = namespace.getNamespace(localName.substring(curPos, pos));
363 if(namespace == null)