]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/environment/Environments.java
Merge changes Ib86a41bb,I4fed12d3
[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 java.io.StringReader;
4 import java.util.ArrayList;
5 import java.util.List;
6 import java.util.function.Consumer;
7
8 import org.simantics.scl.compiler.common.names.Name;
9 import org.simantics.scl.compiler.compilation.CompilationContext;
10 import org.simantics.scl.compiler.elaboration.contexts.TypeTranslationContext;
11 import org.simantics.scl.compiler.elaboration.modules.SCLValue;
12 import org.simantics.scl.compiler.elaboration.modules.TypeClass;
13 import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor;
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.internal.codegen.effects.EffectConstructor;
20 import org.simantics.scl.compiler.internal.parsing.exceptions.SCLSyntaxErrorException;
21 import org.simantics.scl.compiler.internal.parsing.parser.SCLParserImpl;
22 import org.simantics.scl.compiler.internal.parsing.types.TypeAst;
23 import org.simantics.scl.compiler.top.SCLExpressionCompilationException;
24 import org.simantics.scl.compiler.types.TCon;
25 import org.simantics.scl.compiler.types.Type;
26
27 import gnu.trove.procedure.TObjectProcedure;
28
29 public class Environments {
30     /**
31      * Get the SCLValue object representing an SCL value defined in a given environment.
32      * The name can be a local name or a fully scoped name with modules separated by periods. 
33      * @param environment  the environment
34      * @param localName  the name to be searched for
35      * @return  An SCLValue instance, or null if not found.
36      * @throws AmbiguousNameException  if the same name is found in multiple imported modules.
37      */
38     public static SCLValue getValue(Environment environment, String localName) throws AmbiguousNameException {
39         return getEnvironmentEntry(environment, localName, getValue);
40     }
41     
42     /**
43      * Get the SCLRelation object representing an SCL relation defined in a given environment.
44      * The name can be a local name or a fully scoped name with modules separated by periods. 
45      * @param environment  the environment
46      * @param localName  the name to be searched for
47      * @return  An SCLRelation instance, or null if not found.
48      * @throws AmbiguousNameException  if the same name is found in multiple imported modules.
49      */
50     public static SCLRelation getRelation(Environment environment, String localName) throws AmbiguousNameException {
51         return getEnvironmentEntry(environment, localName, getRelation);
52     }
53     
54     public static MappingRelation getMappingRelation(Environment environment, String localName) throws AmbiguousNameException {
55         return getEnvironmentEntry(environment, localName, getMappingRelation);
56     }
57     
58     public static TransformationRule getRule(Environment environment, String localName) throws AmbiguousNameException {
59         return getEnvironmentEntry(environment, localName, getRule);
60     }
61     
62     /**
63      * Get the SCLEntityType object representing an entity type defined in a given environment.
64      * The name can be a local name or a fully scoped name with modules separated by periods. 
65      * @param environment  the environment
66      * @param localName  the name to be searched for
67      * @return  An SCLEntityType instance, or null if not found.
68      * @throws AmbiguousNameException  if the same name is found in multiple imported modules.
69      */
70     public static SCLEntityType getEntityType(Environment environment, String localName) throws AmbiguousNameException {
71         return getEnvironmentEntry(environment, localName, getEntityType);
72     }
73     
74     /**
75      * Get the TypeConstructor object representing an type defined in a given environment.
76      * The name can be a local name or a fully scoped name with modules separated by periods. 
77      * @param environment  the environment
78      * @param localName  the name to be searched for
79      * @return  A TypeConstructor instance, or null if not found.
80      * @throws AmbiguousNameException  if the same name is found in multiple imported modules.
81      */
82     public static TypeDescriptor getTypeDescriptor(Environment environment, String localName) throws AmbiguousNameException {
83         return getEnvironmentEntry(environment, localName, getTypeDescriptor);
84     }
85     
86     /**
87      * Get the EffectConstructor object representing an effect defined in a given environment.
88      * The name can be a local name or a fully scoped name with modules separated by periods. 
89      * @param environment  the environment
90      * @param localName  the name to be searched for
91      * @return  An EffectConstructor instance, or null if not found.
92      * @throws AmbiguousNameException  if the same name is found in multiple imported modules.
93      */
94     public static EffectConstructor getEffectConstructor(Environment environment, String localName) throws AmbiguousNameException {
95         return getEnvironmentEntry(environment, localName, getEffectConstructor);
96     }
97     
98     /**
99      * Get the TypeClass object representing a type class defined in a given environment.
100      * The name can be a local name or a fully scoped name with modules separated by periods. 
101      * @param environment  the environment
102      * @param localName  the name to be searched for
103      * @return  A TypeClass instance, or null if not found.
104      * @throws AmbiguousNameException  if the same name is found in multiple imported modules.
105      */
106     public static TypeClass getTypeClass(Environment environment, String localName) throws AmbiguousNameException {
107         return getEnvironmentEntry(environment, localName, getTypeClass);
108     }
109
110     /**
111      * Get the Name object representing an SCL value defined in a given environment.
112      * The name can be a local name or a fully scoped name with modules separated by periods. 
113      * @param environment  the environment
114      * @param localName  the name to be searched for
115      * @return  A Name instance, or null if not found.
116      * @throws AmbiguousNameException  if the same name is used in multiple imported modules.
117      */
118     public static Name getValueName(Environment environment, String localName) throws AmbiguousNameException {
119         SCLValue value = getValue(environment, localName);
120         if(value == null)
121             return null;
122         else
123             return value.getName();
124     }
125     
126     /**
127      * Get the TCon object representing a type declared in a given environment.
128      * The name can be a local name or a fully scoped name with modules separated by periods. 
129      * @param environment  the environment
130      * @param localName  the name to be searched for
131      * @return  A TCon instance, or null if not found.
132      * @throws AmbiguousNameException  if the same name is used in multiple imported modules.
133      */
134     public static TCon getTypeDescriptorName(Environment environment, String localName) throws AmbiguousNameException {
135         TypeDescriptor typeDescriptor = getTypeDescriptor(environment, localName);
136         if(typeDescriptor == null)
137             return null;
138         else
139             return typeDescriptor.name;
140     }
141     
142     /**
143      * Get the TCon object representing an effect declared in a given environment.
144      * The name can be a local name or a fully scoped name with modules separated by periods. 
145      * @param environment  the environment
146      * @param localName  the name to be searched for
147      * @return  A TCon instance, or null if not found.
148      * @throws AmbiguousNameException  if the same name is used in multiple imported modules.
149      */
150     public static TCon getEffectConstructorName(Environment environment, String localName) throws AmbiguousNameException {
151         EffectConstructor effectConstructor = getEffectConstructor(environment, localName);
152         if(effectConstructor == null)
153             return null;
154         else
155             return effectConstructor.name;
156     }
157     
158     /**
159      * Get the TCon object representing a type class declared in a given environment.
160      * The name can be a local name or a fully scoped name with modules separated by periods. 
161      * @param environment  the environment
162      * @param localName  the name to be searched for
163      * @return  A TCon instance, or null if not found.
164      * @throws AmbiguousNameException  if the same name is used in multiple imported modules.
165      */
166     public static TCon getTypeClassName(Environment environment, String localName) throws AmbiguousNameException {
167         TypeClass typeClass = getTypeClass(environment, localName);
168         if(typeClass == null)
169             return null;
170         else
171             return typeClass.name;
172     }
173     
174     /**
175      * Parse a given SCL type expression into a Type defined in a given environment.
176      * @param environment  the environment
177      * @param typeText  an SCL language type expression
178      * @return  A Type instance
179      * @throws SCLExpressionCompilationException  if the expression compilation fails
180      */
181     public static Type getType(Environment environment, String typeText) throws SCLExpressionCompilationException {
182         SCLParserImpl parser = new SCLParserImpl(new StringReader(typeText));
183         CompilationContext compilationContext = new CompilationContext();
184         compilationContext.environment = environment;
185         try {
186             TypeAst typeAst = (TypeAst)parser.parseType();
187             TypeTranslationContext context = new TypeTranslationContext(compilationContext);
188             Type type = context.toType(typeAst);
189             if(compilationContext.errorLog.isEmpty())
190                 return type;
191         } catch(SCLSyntaxErrorException e) {
192             compilationContext.errorLog.log(e.location, e.getMessage());
193         } catch(Exception e) {
194             compilationContext.errorLog.log(e);
195         }
196         throw new SCLExpressionCompilationException(compilationContext.errorLog.getErrors());
197     }
198
199     /**
200      * Find a list of values in an environment that share a common prefix.
201      * The name can be a local name or a fully scoped name with modules separated by periods. 
202      * @param environment  An environment
203      * @param prefix  A name prefix
204      * @param values  A collection into which the found values are added
205      */
206     public static void findValuesForPrefix(Environment environment,
207             String prefix, TObjectProcedure<SCLValue> proc) {
208         findValuesForPrefix(environment.getLocalNamespace(), prefix, proc);
209     }
210     
211     public static List<SCLValue> findValuesForPrefix(Environment environment,
212             String prefix) {
213         final ArrayList<SCLValue> result = new ArrayList<SCLValue>();
214         findValuesForPrefix(environment, prefix,
215                 new TObjectProcedure<SCLValue>() {
216                     @Override
217                     public boolean execute(SCLValue value) {
218                         result.add(value);
219                         return true;
220                     }
221                 });
222         return result;
223     }
224     
225     /**
226      * Find a list of values in a namespace that share a common prefix.
227      * The name can be a local name or a fully scoped name with modules separated by periods. 
228      * @param namespace  An namespace
229      * @param prefix  A name prefix
230      * @param values  A collection into which the found values are added
231      */
232     public static void findValuesForPrefix(Namespace namespace,
233             String prefix, TObjectProcedure<SCLValue> proc) {
234         int p = prefix.indexOf('.');
235         if(p > 0) {
236             Namespace childNamespace = namespace.getNamespace(prefix.substring(0, p));
237             if(childNamespace != null)
238                 findValuesForPrefix(childNamespace, prefix.substring(p+1), proc);
239         }
240         else
241             namespace.findValuesForPrefix(prefix, AcceptAllNamespaceFilter.INSTANCE, proc);
242     }
243     
244     public static List<TCon> findTypesForPrefix(Environment environment, String prefix) {
245         final List<TCon> results = new ArrayList<>();
246         findTypesForPrefix(environment.getLocalNamespace(), prefix, new Consumer<TCon>() {
247
248             @Override
249             public void accept(TCon tcon) {
250                 results.add(tcon);
251             }
252         });
253         return results;
254     }
255     
256     /**
257      * Find a list of values in a namespace that share a common prefix.
258      * The name can be a local name or a fully scoped name with modules separated by periods. 
259      * @param namespace  An namespace
260      * @param prefix  A name prefix
261      * @param values  A collection into which the found values are added
262      */
263     public static void findTypesForPrefix(Namespace namespace, String prefix, Consumer<TCon> consumer) {
264         int p = prefix.indexOf('.');
265         if(p > 0) {
266             Namespace childNamespace = namespace.getNamespace(prefix.substring(0, p));
267             if(childNamespace != null)
268                 findTypesForPrefix(childNamespace, prefix.substring(p+1), consumer);
269         }
270         else
271             namespace.findTypesForPrefix(prefix, AcceptAllNamespaceFilter.INSTANCE, consumer);
272     }
273     
274     /* Accessor objects for retrieving values from a namespace. */
275     
276     private static interface NamespaceValueAccessor<T> {
277         public T get(Namespace ns, String name) throws AmbiguousNameException;
278     }
279     
280     private static final NamespaceValueAccessor<SCLValue> getValue = new NamespaceValueAccessor<SCLValue>() {
281                 @Override
282                 public SCLValue get(Namespace ns, String name) throws AmbiguousNameException {
283                         return ns.getValue(name);
284                 }               
285         };
286     
287     private static final NamespaceValueAccessor<SCLRelation> getRelation = new NamespaceValueAccessor<SCLRelation>() {
288                 @Override
289                 public SCLRelation get(Namespace ns, String name) throws AmbiguousNameException {
290                         return ns.getRelation(name);
291                 }               
292         };
293     
294         private static final NamespaceValueAccessor<MappingRelation> getMappingRelation = new NamespaceValueAccessor<MappingRelation>() {
295         @Override
296         public MappingRelation get(Namespace ns, String name) throws AmbiguousNameException {
297             return ns.getMappingRelation(name);
298         }
299     };
300     
301     private static final NamespaceValueAccessor<TransformationRule> getRule = new NamespaceValueAccessor<TransformationRule>() {
302         @Override
303         public TransformationRule get(Namespace ns, String name) throws AmbiguousNameException {
304             return ns.getRule(name);
305         }
306     };
307     
308     private static final NamespaceValueAccessor<SCLEntityType> getEntityType = new NamespaceValueAccessor<SCLEntityType>() {
309                 @Override
310                 public SCLEntityType get(Namespace ns, String name) throws AmbiguousNameException {
311                         return ns.getEntityType(name);
312                 }               
313         };
314     
315     private static final NamespaceValueAccessor<TypeDescriptor> getTypeDescriptor = new NamespaceValueAccessor<TypeDescriptor>() {
316                 @Override
317                 public TypeDescriptor get(Namespace ns, String name) throws AmbiguousNameException {
318                         return ns.getTypeDescriptor(name);
319                 }               
320         };
321     
322     private static final NamespaceValueAccessor<EffectConstructor> getEffectConstructor = new NamespaceValueAccessor<EffectConstructor>() {
323                 @Override
324                 public EffectConstructor get(Namespace ns, String name) throws AmbiguousNameException {
325                         return ns.getEffectConstructor(name);
326                 }               
327         };
328     
329     private static final NamespaceValueAccessor<TypeClass> getTypeClass = new NamespaceValueAccessor<TypeClass>() {
330                 @Override
331                 public TypeClass get(Namespace ns, String name) throws AmbiguousNameException {
332                         return ns.getTypeClass(name);
333                 }               
334         };
335     
336         private static <T> T getEnvironmentEntry(Environment environment, String localName, NamespaceValueAccessor<T> accessor) throws AmbiguousNameException {
337         Namespace namespace = environment.getLocalNamespace();
338         int curPos = 0;
339         while(true) {
340             int pos = localName.indexOf('.', curPos);
341             if(pos < 0)
342                 return accessor.get(namespace, localName.substring(curPos));
343             Namespace newNamespace = namespace.getNamespace(localName.substring(curPos, pos));
344             if(newNamespace == null)
345                 return accessor.get(namespace, localName.substring(curPos));
346             namespace = newNamespace;
347             curPos = pos + 1;
348         }
349     }
350 }