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.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;
27 import gnu.trove.procedure.TObjectProcedure;
29 public class Environments {
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.
38 public static SCLValue getValue(Environment environment, String localName) throws AmbiguousNameException {
39 return getEnvironmentEntry(environment, localName, getValue);
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.
50 public static SCLRelation getRelation(Environment environment, String localName) throws AmbiguousNameException {
51 return getEnvironmentEntry(environment, localName, getRelation);
54 public static MappingRelation getMappingRelation(Environment environment, String localName) throws AmbiguousNameException {
55 return getEnvironmentEntry(environment, localName, getMappingRelation);
58 public static TransformationRule getRule(Environment environment, String localName) throws AmbiguousNameException {
59 return getEnvironmentEntry(environment, localName, getRule);
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.
70 public static SCLEntityType getEntityType(Environment environment, String localName) throws AmbiguousNameException {
71 return getEnvironmentEntry(environment, localName, getEntityType);
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.
82 public static TypeDescriptor getTypeDescriptor(Environment environment, String localName) throws AmbiguousNameException {
83 return getEnvironmentEntry(environment, localName, getTypeDescriptor);
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.
94 public static EffectConstructor getEffectConstructor(Environment environment, String localName) throws AmbiguousNameException {
95 return getEnvironmentEntry(environment, localName, getEffectConstructor);
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.
106 public static TypeClass getTypeClass(Environment environment, String localName) throws AmbiguousNameException {
107 return getEnvironmentEntry(environment, localName, getTypeClass);
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.
118 public static Name getValueName(Environment environment, String localName) throws AmbiguousNameException {
119 SCLValue value = getValue(environment, localName);
123 return value.getName();
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.
134 public static TCon getTypeDescriptorName(Environment environment, String localName) throws AmbiguousNameException {
135 TypeDescriptor typeDescriptor = getTypeDescriptor(environment, localName);
136 if(typeDescriptor == null)
139 return typeDescriptor.name;
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.
150 public static TCon getEffectConstructorName(Environment environment, String localName) throws AmbiguousNameException {
151 EffectConstructor effectConstructor = getEffectConstructor(environment, localName);
152 if(effectConstructor == null)
155 return effectConstructor.name;
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.
166 public static TCon getTypeClassName(Environment environment, String localName) throws AmbiguousNameException {
167 TypeClass typeClass = getTypeClass(environment, localName);
168 if(typeClass == null)
171 return typeClass.name;
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
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;
186 TypeAst typeAst = (TypeAst)parser.parseType();
187 TypeTranslationContext context = new TypeTranslationContext(compilationContext);
188 Type type = context.toType(typeAst);
189 if(compilationContext.errorLog.isEmpty())
191 } catch(SCLSyntaxErrorException e) {
192 compilationContext.errorLog.log(e.location, e.getMessage());
193 } catch(Exception e) {
194 compilationContext.errorLog.log(e);
196 throw new SCLExpressionCompilationException(compilationContext.errorLog.getErrors());
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
206 public static void findValuesForPrefix(Environment environment,
207 String prefix, TObjectProcedure<SCLValue> proc) {
208 findValuesForPrefix(environment.getLocalNamespace(), prefix, proc);
211 public static List<SCLValue> findValuesForPrefix(Environment environment,
213 final ArrayList<SCLValue> result = new ArrayList<SCLValue>();
214 findValuesForPrefix(environment, prefix,
215 new TObjectProcedure<SCLValue>() {
217 public boolean execute(SCLValue value) {
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
232 public static void findValuesForPrefix(Namespace namespace,
233 String prefix, TObjectProcedure<SCLValue> proc) {
234 int p = prefix.indexOf('.');
236 Namespace childNamespace = namespace.getNamespace(prefix.substring(0, p));
237 if(childNamespace != null)
238 findValuesForPrefix(childNamespace, prefix.substring(p+1), proc);
241 namespace.findValuesForPrefix(prefix, AcceptAllNamespaceFilter.INSTANCE, proc);
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>() {
249 public void accept(TCon tcon) {
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
263 public static void findTypesForPrefix(Namespace namespace, String prefix, Consumer<TCon> consumer) {
264 int p = prefix.indexOf('.');
266 Namespace childNamespace = namespace.getNamespace(prefix.substring(0, p));
267 if(childNamespace != null)
268 findTypesForPrefix(childNamespace, prefix.substring(p+1), consumer);
271 namespace.findTypesForPrefix(prefix, AcceptAllNamespaceFilter.INSTANCE, consumer);
274 /* Accessor objects for retrieving values from a namespace. */
276 private static interface NamespaceValueAccessor<T> {
277 public T get(Namespace ns, String name) throws AmbiguousNameException;
280 private static final NamespaceValueAccessor<SCLValue> getValue = new NamespaceValueAccessor<SCLValue>() {
282 public SCLValue get(Namespace ns, String name) throws AmbiguousNameException {
283 return ns.getValue(name);
287 private static final NamespaceValueAccessor<SCLRelation> getRelation = new NamespaceValueAccessor<SCLRelation>() {
289 public SCLRelation get(Namespace ns, String name) throws AmbiguousNameException {
290 return ns.getRelation(name);
294 private static final NamespaceValueAccessor<MappingRelation> getMappingRelation = new NamespaceValueAccessor<MappingRelation>() {
296 public MappingRelation get(Namespace ns, String name) throws AmbiguousNameException {
297 return ns.getMappingRelation(name);
301 private static final NamespaceValueAccessor<TransformationRule> getRule = new NamespaceValueAccessor<TransformationRule>() {
303 public TransformationRule get(Namespace ns, String name) throws AmbiguousNameException {
304 return ns.getRule(name);
308 private static final NamespaceValueAccessor<SCLEntityType> getEntityType = new NamespaceValueAccessor<SCLEntityType>() {
310 public SCLEntityType get(Namespace ns, String name) throws AmbiguousNameException {
311 return ns.getEntityType(name);
315 private static final NamespaceValueAccessor<TypeDescriptor> getTypeDescriptor = new NamespaceValueAccessor<TypeDescriptor>() {
317 public TypeDescriptor get(Namespace ns, String name) throws AmbiguousNameException {
318 return ns.getTypeDescriptor(name);
322 private static final NamespaceValueAccessor<EffectConstructor> getEffectConstructor = new NamespaceValueAccessor<EffectConstructor>() {
324 public EffectConstructor get(Namespace ns, String name) throws AmbiguousNameException {
325 return ns.getEffectConstructor(name);
329 private static final NamespaceValueAccessor<TypeClass> getTypeClass = new NamespaceValueAccessor<TypeClass>() {
331 public TypeClass get(Namespace ns, String name) throws AmbiguousNameException {
332 return ns.getTypeClass(name);
336 private static <T> T getEnvironmentEntry(Environment environment, String localName, NamespaceValueAccessor<T> accessor) throws AmbiguousNameException {
337 Namespace namespace = environment.getLocalNamespace();
340 int pos = localName.indexOf('.', curPos);
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;