1 package org.simantics.scl.compiler.elaboration.expressions;
5 import org.simantics.scl.compiler.common.names.Names;
6 import org.simantics.scl.compiler.constants.Constant;
7 import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
8 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
9 import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
10 import org.simantics.scl.compiler.elaboration.expressions.EAmbiguous.Alternative;
11 import org.simantics.scl.compiler.elaboration.expressions.accessor.FieldAccessor;
12 import org.simantics.scl.compiler.elaboration.expressions.accessor.IdAccessor;
13 import org.simantics.scl.compiler.errors.Locations;
14 import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator;
15 import org.simantics.scl.compiler.internal.header.ModuleHeader;
16 import org.simantics.scl.compiler.types.Type;
17 import org.simantics.scl.compiler.types.Types;
18 import org.simantics.scl.compiler.types.exceptions.MatchException;
20 import gnu.trove.map.hash.TObjectIntHashMap;
21 import gnu.trove.set.hash.THashSet;
22 import gnu.trove.set.hash.TIntHashSet;
24 public class EFieldAccess extends SimplifiableExpression {
26 private static final Type VARIABLE = Types.con("Simantics/Variables", "Variable");
29 FieldAccessor accessor;
30 boolean lastAccessor = true;
32 public EFieldAccess(Expression parent, FieldAccessor accessor) {
34 this.accessor = accessor;
35 if(parent instanceof EFieldAccess)
36 ((EFieldAccess)parent).lastAccessor = false;
40 public void collectRefs(TObjectIntHashMap<Object> allRefs,
42 parent.collectRefs(allRefs, refs);
43 accessor.collectRefs(allRefs, refs);
47 public void collectVars(TObjectIntHashMap<Variable> allVars,
49 parent.collectVars(allVars, vars);
50 accessor.collectVars(allVars, vars);
53 private boolean returnsValue() {
54 return accessor.accessSeparator == '#' && !accessor.isVariableId();
58 protected void updateType() throws MatchException {
59 // Type is already updated in checkBasicType
62 private Expression resolveAccessor(TypingContext context, Type requiredType) {
63 if(!(accessor instanceof IdAccessor))
65 IdAccessor idAccessor = (IdAccessor)accessor;
66 if(idAccessor.accessSeparator != '.')
68 List<Constant> accessors = context.getEnvironment().getFieldAccessors(idAccessor.fieldName);
69 if(accessors == null) {
70 context.getErrorLog().log("Couldn't resolve accessor ." + idAccessor.fieldName + ".");
71 return new EError(location);
73 Expression accessorExpression;
74 if(accessors.size() == 1)
75 accessorExpression = new ELiteral(accessors.get(0));
77 Alternative[] alternatives = new Alternative[accessors.size()];
78 for(int i=0;i<alternatives.length;++i) {
80 alternatives[i] = new Alternative() {
82 public Expression realize() {
83 return new ELiteral(accessors.get(index));
86 public Type getType() {
87 return accessors.get(index).getType();
91 accessorExpression = new EAmbiguous(alternatives);
93 return new EApply(location, accessorExpression, parent).checkType(context, requiredType);
97 public Expression checkBasicType(TypingContext context, Type requiredType) {
98 ModuleHeader header = context.getCompilationContext().header;
99 if(header != null && header.fields) {
100 Expression expression = resolveAccessor(context, requiredType);
101 if(expression != null)
107 setType(requiredType);
110 context.subsume(this, requiredType);
112 parent = parent.checkType(context, VARIABLE);
113 accessor.checkType(context);
114 context.declareEffect(getLocation(), Types.READ_GRAPH);
119 public void collectFreeVariables(THashSet<Variable> vars) {
120 parent.collectFreeVariables(vars);
121 accessor.collectFreeVariables(vars);
125 public Expression simplify(SimplificationContext context) {
126 // Simplify subexpressions
127 parent = parent.simplify(context);
128 accessor.simplify(context);
130 if(accessor.accessSeparator == '.')
134 context.getConstant(Names.Simantics_Variables_child_),
136 accessor.asExpression()
138 else if(!lastAccessor)
142 context.getConstant(Names.Simantics_Variables_property),
144 accessor.asExpression()
146 else if(accessor.isVariableId())
152 context.getConstant(Names.Simantics_Variables_untypedPropertyValue, getType()),
154 accessor.asExpression()
159 public Expression resolve(TranslationContext context) {
160 parent = parent.resolve(context);
161 accessor.resolve(context);
166 public Expression decorate(ExpressionDecorator decorator) {
167 return decorator.decorate(this);
171 public void collectEffects(THashSet<Type> effects) {
173 effects.add(Types.READ_GRAPH);
177 public void setLocationDeep(long loc) {
178 if(location == Locations.NO_LOCATION) {
180 parent.setLocationDeep(loc);
181 accessor.setLocationDeep(loc);
186 public void accept(ExpressionVisitor visitor) {
191 public void forVariables(VariableProcedure procedure) {
192 parent.forVariables(procedure);
193 accessor.forVariables(procedure);
197 public Expression accept(ExpressionTransformer transformer) {
198 return transformer.transform(this);