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.chr.CHRRuleset;
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.TypeClass;
14 import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor;
15 import org.simantics.scl.compiler.elaboration.relations.SCLEntityType;
16 import org.simantics.scl.compiler.elaboration.relations.SCLRelation;
17 import org.simantics.scl.compiler.elaboration.rules.MappingRelation;
18 import org.simantics.scl.compiler.elaboration.rules.TransformationRule;
19 import org.simantics.scl.compiler.environment.filter.AcceptAllNamespaceFilter;
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 TypeDescriptor getTypeDescriptor(Environment environment, String localName) throws AmbiguousNameException {
84 return getEnvironmentEntry(environment, localName, getTypeDescriptor);
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);
111 public static CHRRuleset getRuleset(Environment environment, String localName) throws AmbiguousNameException {
112 return getEnvironmentEntry(environment, localName, getRuleset);
116 * Get the Name object representing an SCL value defined in a given environment.
117 * The name can be a local name or a fully scoped name with modules separated by periods.
118 * @param environment the environment
119 * @param localName the name to be searched for
120 * @return A Name instance, or null if not found.
121 * @throws AmbiguousNameException if the same name is used in multiple imported modules.
123 public static Name getValueName(Environment environment, String localName) throws AmbiguousNameException {
124 SCLValue value = getValue(environment, localName);
128 return value.getName();
132 * Get the TCon object representing a type declared in a given environment.
133 * The name can be a local name or a fully scoped name with modules separated by periods.
134 * @param environment the environment
135 * @param localName the name to be searched for
136 * @return A TCon instance, or null if not found.
137 * @throws AmbiguousNameException if the same name is used in multiple imported modules.
139 public static TCon getTypeDescriptorName(Environment environment, String localName) throws AmbiguousNameException {
140 TypeDescriptor typeDescriptor = getTypeDescriptor(environment, localName);
141 if(typeDescriptor == null)
144 return typeDescriptor.name;
148 * Get the TCon object representing an effect declared in a given environment.
149 * The name can be a local name or a fully scoped name with modules separated by periods.
150 * @param environment the environment
151 * @param localName the name to be searched for
152 * @return A TCon instance, or null if not found.
153 * @throws AmbiguousNameException if the same name is used in multiple imported modules.
155 public static TCon getEffectConstructorName(Environment environment, String localName) throws AmbiguousNameException {
156 EffectConstructor effectConstructor = getEffectConstructor(environment, localName);
157 if(effectConstructor == null)
160 return effectConstructor.name;
164 * Get the TCon object representing a type class declared in a given environment.
165 * The name can be a local name or a fully scoped name with modules separated by periods.
166 * @param environment the environment
167 * @param localName the name to be searched for
168 * @return A TCon instance, or null if not found.
169 * @throws AmbiguousNameException if the same name is used in multiple imported modules.
171 public static TCon getTypeClassName(Environment environment, String localName) throws AmbiguousNameException {
172 TypeClass typeClass = getTypeClass(environment, localName);
173 if(typeClass == null)
176 return typeClass.name;
180 * Parse a given SCL type expression into a Type defined in a given environment.
181 * @param environment the environment
182 * @param typeText an SCL language type expression
183 * @return A Type instance
184 * @throws SCLExpressionCompilationException if the expression compilation fails
186 public static Type getType(Environment environment, String typeText) throws SCLExpressionCompilationException {
187 SCLParserImpl parser = new SCLParserImpl(new StringReader(typeText));
188 CompilationContext compilationContext = new CompilationContext();
189 compilationContext.environment = environment;
191 TypeAst typeAst = (TypeAst)parser.parseType();
192 TypeTranslationContext context = new TypeTranslationContext(compilationContext);
193 Type type = context.toType(typeAst);
194 if(compilationContext.errorLog.hasNoErrors())
196 } catch(SCLSyntaxErrorException e) {
197 compilationContext.errorLog.log(e.location, e.getMessage());
198 } catch(Exception e) {
199 compilationContext.errorLog.log(e);
201 throw new SCLExpressionCompilationException(compilationContext.errorLog.getErrors());
205 * Find a list of values in an environment that share a common prefix.
206 * The name can be a local name or a fully scoped name with modules separated by periods.
207 * @param environment An environment
208 * @param prefix A name prefix
209 * @param values A collection into which the found values are added
211 public static void findValuesForPrefix(Environment environment,
212 String prefix, TObjectProcedure<SCLValue> proc) {
213 findValuesForPrefix(environment.getLocalNamespace(), prefix, proc);
216 public static List<SCLValue> findValuesForPrefix(Environment environment,
218 final ArrayList<SCLValue> result = new ArrayList<SCLValue>();
219 findValuesForPrefix(environment, prefix,
220 new TObjectProcedure<SCLValue>() {
222 public boolean execute(SCLValue value) {
231 * Find a list of values in a namespace that share a common prefix.
232 * The name can be a local name or a fully scoped name with modules separated by periods.
233 * @param namespace An namespace
234 * @param prefix A name prefix
235 * @param values A collection into which the found values are added
237 public static void findValuesForPrefix(Namespace namespace,
238 String prefix, TObjectProcedure<SCLValue> proc) {
239 int p = prefix.indexOf('.');
241 Namespace childNamespace = namespace.getNamespace(prefix.substring(0, p));
242 if(childNamespace != null)
243 findValuesForPrefix(childNamespace, prefix.substring(p+1), proc);
245 namespace.findValuesForPrefix(prefix, AcceptAllNamespaceFilter.INSTANCE, proc);
248 namespace.findValuesForPrefix(prefix, AcceptAllNamespaceFilter.INSTANCE, proc);
251 public static List<TCon> findTypesForPrefix(Environment environment, String prefix) {
252 final List<TCon> results = new ArrayList<>();
253 findTypesForPrefix(environment.getLocalNamespace(), prefix, new Consumer<TCon>() {
256 public void accept(TCon tcon) {
264 * Find a list of values in a namespace that share a common prefix.
265 * The name can be a local name or a fully scoped name with modules separated by periods.
266 * @param namespace An namespace
267 * @param prefix A name prefix
268 * @param values A collection into which the found values are added
270 public static void findTypesForPrefix(Namespace namespace, String prefix, Consumer<TCon> consumer) {
271 int p = prefix.indexOf('.');
273 Namespace childNamespace = namespace.getNamespace(prefix.substring(0, p));
274 if(childNamespace != null)
275 findTypesForPrefix(childNamespace, prefix.substring(p+1), consumer);
278 namespace.findTypesForPrefix(prefix, AcceptAllNamespaceFilter.INSTANCE, consumer);
281 /* Accessor objects for retrieving values from a namespace. */
283 private static interface NamespaceValueAccessor<T> {
284 public T get(Namespace ns, String name) throws AmbiguousNameException;
287 private static final NamespaceValueAccessor<SCLValue> getValue = new NamespaceValueAccessor<SCLValue>() {
289 public SCLValue get(Namespace ns, String name) throws AmbiguousNameException {
290 return ns.getValue(name);
294 private static final NamespaceValueAccessor<SCLRelation> getRelation = new NamespaceValueAccessor<SCLRelation>() {
296 public SCLRelation get(Namespace ns, String name) throws AmbiguousNameException {
297 return ns.getRelation(name);
301 private static final NamespaceValueAccessor<MappingRelation> getMappingRelation = new NamespaceValueAccessor<MappingRelation>() {
303 public MappingRelation get(Namespace ns, String name) throws AmbiguousNameException {
304 return ns.getMappingRelation(name);
308 private static final NamespaceValueAccessor<TransformationRule> getRule = new NamespaceValueAccessor<TransformationRule>() {
310 public TransformationRule get(Namespace ns, String name) throws AmbiguousNameException {
311 return ns.getRule(name);
315 private static final NamespaceValueAccessor<SCLEntityType> getEntityType = new NamespaceValueAccessor<SCLEntityType>() {
317 public SCLEntityType get(Namespace ns, String name) throws AmbiguousNameException {
318 return ns.getEntityType(name);
322 private static final NamespaceValueAccessor<TypeDescriptor> getTypeDescriptor = new NamespaceValueAccessor<TypeDescriptor>() {
324 public TypeDescriptor get(Namespace ns, String name) throws AmbiguousNameException {
325 return ns.getTypeDescriptor(name);
329 private static final NamespaceValueAccessor<EffectConstructor> getEffectConstructor = new NamespaceValueAccessor<EffectConstructor>() {
331 public EffectConstructor get(Namespace ns, String name) throws AmbiguousNameException {
332 return ns.getEffectConstructor(name);
336 private static final NamespaceValueAccessor<TypeClass> getTypeClass = new NamespaceValueAccessor<TypeClass>() {
338 public TypeClass get(Namespace ns, String name) throws AmbiguousNameException {
339 return ns.getTypeClass(name);
343 private static final NamespaceValueAccessor<CHRRuleset> getRuleset = new NamespaceValueAccessor<CHRRuleset>() {
345 public CHRRuleset get(Namespace ns, String name) throws AmbiguousNameException {
346 return ns.getRuleset(name);
350 private static <T> T getEnvironmentEntry(Environment environment, String localName, NamespaceValueAccessor<T> accessor) throws AmbiguousNameException {
351 Namespace namespace = environment.getLocalNamespace();
354 int pos = localName.indexOf('.', curPos);
356 return accessor.get(namespace, localName.substring(curPos));
357 Namespace newNamespace = namespace.getNamespace(localName.substring(curPos, pos));
358 if(newNamespace == null)
359 return accessor.get(namespace, localName.substring(curPos));
360 namespace = newNamespace;