]> gerrit.simantics Code Review - simantics/platform.git/blob - 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
1 package org.simantics.scl.compiler.environment;
2
3 import gnu.trove.procedure.TObjectProcedure;
4
5 import java.io.StringReader;
6 import java.util.ArrayList;
7 import java.util.List;
8 import java.util.function.Consumer;
9
10 import org.simantics.scl.compiler.common.names.Name;
11 import org.simantics.scl.compiler.elaboration.contexts.TypeTranslationContext;
12 import org.simantics.scl.compiler.elaboration.modules.SCLValue;
13 import org.simantics.scl.compiler.elaboration.modules.TypeAlias;
14 import org.simantics.scl.compiler.elaboration.modules.TypeClass;
15 import org.simantics.scl.compiler.elaboration.modules.TypeConstructor;
16 import org.simantics.scl.compiler.elaboration.relations.SCLEntityType;
17 import org.simantics.scl.compiler.elaboration.relations.SCLRelation;
18 import org.simantics.scl.compiler.elaboration.rules.MappingRelation;
19 import org.simantics.scl.compiler.elaboration.rules.TransformationRule;
20 import org.simantics.scl.compiler.environment.filter.AcceptAllNamespaceFilter;
21 import org.simantics.scl.compiler.errors.ErrorLog;
22 import org.simantics.scl.compiler.internal.codegen.effects.EffectConstructor;
23 import org.simantics.scl.compiler.internal.parsing.exceptions.SCLSyntaxErrorException;
24 import org.simantics.scl.compiler.internal.parsing.parser.SCLParserImpl;
25 import org.simantics.scl.compiler.internal.parsing.types.TypeAst;
26 import org.simantics.scl.compiler.top.SCLExpressionCompilationException;
27 import org.simantics.scl.compiler.types.TCon;
28 import org.simantics.scl.compiler.types.Type;
29
30 public class Environments {
31     /**
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.
38      */
39     public static SCLValue getValue(Environment environment, String localName) throws AmbiguousNameException {
40         return getEnvironmentEntry(environment, localName, getValue);
41     }
42     
43     /**
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.
50      */
51     public static SCLRelation getRelation(Environment environment, String localName) throws AmbiguousNameException {
52         return getEnvironmentEntry(environment, localName, getRelation);
53     }
54     
55     public static MappingRelation getMappingRelation(Environment environment, String localName) throws AmbiguousNameException {
56         return getEnvironmentEntry(environment, localName, getMappingRelation);
57     }
58     
59     public static TransformationRule getRule(Environment environment, String localName) throws AmbiguousNameException {
60         return getEnvironmentEntry(environment, localName, getRule);
61     }
62     
63     /**
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.
70      */
71     public static SCLEntityType getEntityType(Environment environment, String localName) throws AmbiguousNameException {
72         return getEnvironmentEntry(environment, localName, getEntityType);
73     }
74     
75     /**
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.
82      */
83     public static TypeConstructor getTypeConstructor(Environment environment, String localName) throws AmbiguousNameException {
84         return getEnvironmentEntry(environment, localName, getTypeConstructor);
85     }
86     
87     /**
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.
94      */
95     public static EffectConstructor getEffectConstructor(Environment environment, String localName) throws AmbiguousNameException {
96         return getEnvironmentEntry(environment, localName, getEffectConstructor);
97     }
98     
99     /**
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.
106      */
107     public static TypeClass getTypeClass(Environment environment, String localName) throws AmbiguousNameException {
108         return getEnvironmentEntry(environment, localName, getTypeClass);
109     }
110     
111     /**
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.
118      */
119     public static TypeAlias getTypeAlias(Environment environment, String localName) throws AmbiguousNameException {
120         return getEnvironmentEntry(environment, localName, getTypeAlias);
121     }
122
123     /**
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.
130      */
131     public static Name getValueName(Environment environment, String localName) throws AmbiguousNameException {
132         SCLValue value = getValue(environment, localName);
133         if(value == null)
134             return null;
135         else
136             return value.getName();
137     }
138     
139     /**
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.
146      */
147     public static TCon getTypeConstructorName(Environment environment, String localName) throws AmbiguousNameException {
148         TypeConstructor typeConstructor = getTypeConstructor(environment, localName);
149         if(typeConstructor == null)
150             return null;
151         else
152             return typeConstructor.name;
153     }
154     
155     /**
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.
162      */
163     public static TCon getEffectConstructorName(Environment environment, String localName) throws AmbiguousNameException {
164         EffectConstructor effectConstructor = getEffectConstructor(environment, localName);
165         if(effectConstructor == null)
166             return null;
167         else
168             return effectConstructor.name;
169     }
170     
171     /**
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.
178      */
179     public static TCon getTypeClassName(Environment environment, String localName) throws AmbiguousNameException {
180         TypeClass typeClass = getTypeClass(environment, localName);
181         if(typeClass == null)
182             return null;
183         else
184             return typeClass.name;
185     }
186     
187     /**
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
193      */
194     public static Type getType(Environment environment, String typeText) throws SCLExpressionCompilationException {
195         SCLParserImpl parser = new SCLParserImpl(new StringReader(typeText));
196         ErrorLog errorLog = new ErrorLog();
197         try {
198             TypeAst typeAst = (TypeAst)parser.parseType();
199             TypeTranslationContext context = new TypeTranslationContext(errorLog, environment);
200             Type type = context.toType(typeAst);
201             if(errorLog.isEmpty())
202                 return type;
203         } catch(SCLSyntaxErrorException e) {
204             errorLog.log(e.location, e.getMessage());
205         } catch(Exception e) {
206             errorLog.log(e);
207         }
208         throw new SCLExpressionCompilationException(errorLog.getErrors());
209     }
210
211     /**
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
217      */
218     public static void findValuesForPrefix(Environment environment,
219             String prefix, TObjectProcedure<SCLValue> proc) {
220         findValuesForPrefix(environment.getLocalNamespace(), prefix, proc);
221     }
222     
223     public static List<SCLValue> findValuesForPrefix(Environment environment,
224             String prefix) {
225         final ArrayList<SCLValue> result = new ArrayList<SCLValue>();
226         findValuesForPrefix(environment, prefix,
227                 new TObjectProcedure<SCLValue>() {
228                     @Override
229                     public boolean execute(SCLValue value) {
230                         result.add(value);
231                         return true;
232                     }
233                 });
234         return result;
235     }
236     
237     /**
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
243      */
244     public static void findValuesForPrefix(Namespace namespace,
245             String prefix, TObjectProcedure<SCLValue> proc) {
246         int p = prefix.indexOf('.');
247         if(p > 0) {
248             Namespace childNamespace = namespace.getNamespace(prefix.substring(0, p));
249             if(childNamespace != null)
250                 findValuesForPrefix(childNamespace, prefix.substring(p+1), proc);
251         }
252         else
253             namespace.findValuesForPrefix(prefix, AcceptAllNamespaceFilter.INSTANCE, proc);
254     }
255     
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>() {
259
260             @Override
261             public void accept(TCon tcon) {
262                 results.add(tcon);
263             }
264         });
265         return results;
266     }
267     
268     /**
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
274      */
275     public static void findTypesForPrefix(Namespace namespace, String prefix, Consumer<TCon> consumer) {
276         int p = prefix.indexOf('.');
277         if(p > 0) {
278             Namespace childNamespace = namespace.getNamespace(prefix.substring(0, p));
279             if(childNamespace != null)
280                 findTypesForPrefix(childNamespace, prefix.substring(p+1), consumer);
281         }
282         else
283             namespace.findTypesForPrefix(prefix, AcceptAllNamespaceFilter.INSTANCE, consumer);
284     }
285     
286     /* Accessor objects for retrieving values from a namespace. */
287     
288     private static interface NamespaceValueAccessor<T> {
289         public T get(Namespace ns, String name) throws AmbiguousNameException;
290     }
291     
292     private static final NamespaceValueAccessor<SCLValue> getValue = new NamespaceValueAccessor<SCLValue>() {
293                 @Override
294                 public SCLValue get(Namespace ns, String name) throws AmbiguousNameException {
295                         return ns.getValue(name);
296                 }               
297         };
298     
299     private static final NamespaceValueAccessor<SCLRelation> getRelation = new NamespaceValueAccessor<SCLRelation>() {
300                 @Override
301                 public SCLRelation get(Namespace ns, String name) throws AmbiguousNameException {
302                         return ns.getRelation(name);
303                 }               
304         };
305     
306         private static final NamespaceValueAccessor<MappingRelation> getMappingRelation = new NamespaceValueAccessor<MappingRelation>() {
307         @Override
308         public MappingRelation get(Namespace ns, String name) throws AmbiguousNameException {
309             return ns.getMappingRelation(name);
310         }
311     };
312     
313     private static final NamespaceValueAccessor<TransformationRule> getRule = new NamespaceValueAccessor<TransformationRule>() {
314         @Override
315         public TransformationRule get(Namespace ns, String name) throws AmbiguousNameException {
316             return ns.getRule(name);
317         }
318     };
319     
320     private static final NamespaceValueAccessor<SCLEntityType> getEntityType = new NamespaceValueAccessor<SCLEntityType>() {
321                 @Override
322                 public SCLEntityType get(Namespace ns, String name) throws AmbiguousNameException {
323                         return ns.getEntityType(name);
324                 }               
325         };
326     
327     private static final NamespaceValueAccessor<TypeConstructor> getTypeConstructor = new NamespaceValueAccessor<TypeConstructor>() {
328                 @Override
329                 public TypeConstructor get(Namespace ns, String name) throws AmbiguousNameException {
330                         return ns.getTypeConstructor(name);
331                 }               
332         };
333     
334     private static final NamespaceValueAccessor<EffectConstructor> getEffectConstructor = new NamespaceValueAccessor<EffectConstructor>() {
335                 @Override
336                 public EffectConstructor get(Namespace ns, String name) throws AmbiguousNameException {
337                         return ns.getEffectConstructor(name);
338                 }               
339         };
340     
341     private static final NamespaceValueAccessor<TypeClass> getTypeClass = new NamespaceValueAccessor<TypeClass>() {
342                 @Override
343                 public TypeClass get(Namespace ns, String name) throws AmbiguousNameException {
344                         return ns.getTypeClass(name);
345                 }               
346         };
347     
348     private static final NamespaceValueAccessor<TypeAlias> getTypeAlias = new NamespaceValueAccessor<TypeAlias>() {
349                 @Override
350                 public TypeAlias get(Namespace ns, String name) throws AmbiguousNameException {
351                         return ns.getTypeAlias(name);
352                 }               
353         };
354     
355         private static <T> T getEnvironmentEntry(Environment environment, String localName, NamespaceValueAccessor<T> accessor) throws AmbiguousNameException {
356         Namespace namespace = environment.getLocalNamespace();
357         int curPos = 0;
358         while(true) {
359             int pos = localName.indexOf('.', curPos);
360             if(pos < 0)
361                 return accessor.get(namespace, localName.substring(curPos));
362             namespace = namespace.getNamespace(localName.substring(curPos, pos));
363             if(namespace == null)
364                 return null;
365             curPos = pos + 1;
366         }
367     }
368 }