1 package org.simantics.scl.compiler.elaboration.expressions;
\r
3 import gnu.trove.map.hash.TObjectIntHashMap;
\r
4 import gnu.trove.set.hash.THashSet;
\r
5 import gnu.trove.set.hash.TIntHashSet;
\r
7 import org.simantics.scl.compiler.common.names.Name;
\r
8 import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
\r
9 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
\r
10 import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
\r
11 import org.simantics.scl.compiler.elaboration.expressions.accessor.FieldAccessor;
\r
12 import org.simantics.scl.compiler.errors.Locations;
\r
13 import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator;
\r
14 import org.simantics.scl.compiler.types.Type;
\r
15 import org.simantics.scl.compiler.types.Types;
\r
16 import org.simantics.scl.compiler.types.exceptions.MatchException;
\r
18 public class EFieldAccess extends SimplifiableExpression {
\r
20 private static final Type VARIABLE = Types.con("Simantics/Variables", "Variable");
\r
23 FieldAccessor[] accessors;
\r
25 public EFieldAccess(Expression parent, FieldAccessor[] accessors) {
\r
26 if(parent instanceof EFieldAccess) {
\r
27 EFieldAccess parentAccess = (EFieldAccess)parent;
\r
28 parent = parentAccess.parent;
\r
29 accessors = concat(parentAccess.accessors, accessors);
\r
31 this.parent = parent;
\r
32 this.accessors = accessors;
\r
36 public void collectRefs(TObjectIntHashMap<Object> allRefs,
\r
38 parent.collectRefs(allRefs, refs);
\r
39 for(FieldAccessor accessor : accessors)
\r
40 accessor.collectRefs(allRefs, refs);
\r
44 public void collectVars(TObjectIntHashMap<Variable> allVars,
\r
46 parent.collectVars(allVars, vars);
\r
47 for(FieldAccessor accessor : accessors)
\r
48 accessor.collectVars(allVars, vars);
\r
51 private boolean returnsValue() {
\r
52 FieldAccessor lastAccessor = accessors[accessors.length-1];
\r
53 return lastAccessor.accessSeparator=='#' && !lastAccessor.isVariableId();
\r
57 protected void updateType() throws MatchException {
\r
58 // Type is already updated in checkBasicType
\r
62 public Expression checkBasicType(TypingContext context, Type requiredType) {
\r
64 setType(requiredType);
\r
67 context.subsume(this, requiredType);
\r
69 parent = parent.checkType(context, VARIABLE);
\r
70 for(FieldAccessor accessor : accessors)
\r
71 accessor.checkType(context);
\r
72 context.declareEffect(getLocation(), Types.READ_GRAPH);
\r
77 public void collectFreeVariables(THashSet<Variable> vars) {
\r
78 parent.collectFreeVariables(vars);
\r
79 for(FieldAccessor accessor : accessors)
\r
80 accessor.collectFreeVariables(vars);
\r
83 private static final Name CHILD = Name.create("Simantics/Variables", "child_");
\r
84 private static final Name PROPERTY = Name.create("Simantics/Variables", "property");
\r
85 private static final Name PROPERTY_VALUE = Name.create("Simantics/Variables", "untypedPropertyValue");
\r
88 public Expression simplify(SimplificationContext context) {
\r
89 // Simplify subexpressions
\r
90 parent = parent.simplify(context);
\r
91 for(FieldAccessor accessor : accessors)
\r
92 accessor.simplify(context);
\r
95 Expression result = parent;
\r
96 for(int i=0;i<accessors.length;++i) {
\r
97 FieldAccessor accessor = accessors[i];
\r
98 if(accessor.accessSeparator == '.')
\r
99 result = new EApply(
\r
102 context.getConstant(CHILD),
\r
104 accessor.asExpression()
\r
106 else if(i < accessors.length-1)
\r
107 result = new EApply(
\r
110 context.getConstant(PROPERTY),
\r
112 accessor.asExpression()
\r
114 else if(accessor.isVariableId())
\r
117 result = new EApply(
\r
120 context.getConstant(PROPERTY_VALUE, getType()),
\r
122 accessor.asExpression()
\r
128 private static FieldAccessor[] concat(FieldAccessor[] accessors1,
\r
129 FieldAccessor[] accessors2) {
\r
130 FieldAccessor[] result = new FieldAccessor[accessors1.length + accessors2.length];
\r
131 System.arraycopy(accessors1, 0, result, 0, accessors1.length);
\r
132 System.arraycopy(accessors2, 0, result, accessors1.length, accessors2.length);
\r
137 public Expression resolve(TranslationContext context) {
\r
138 parent = parent.resolve(context);
\r
139 for(FieldAccessor accessor : accessors)
\r
140 accessor.resolve(context);
\r
145 public Expression decorate(ExpressionDecorator decorator) {
\r
146 return decorator.decorate(this);
\r
150 public void collectEffects(THashSet<Type> effects) {
\r
152 effects.add(Types.READ_GRAPH);
\r
156 public void setLocationDeep(long loc) {
\r
157 if(location == Locations.NO_LOCATION) {
\r
159 parent.setLocationDeep(loc);
\r
160 for(FieldAccessor accessor : accessors)
\r
161 accessor.setLocationDeep(loc);
\r
166 public void accept(ExpressionVisitor visitor) {
\r
167 visitor.visit(this);
\r
171 public void forVariables(VariableProcedure procedure) {
\r
172 parent.forVariables(procedure);
\r
173 for(FieldAccessor accessor : accessors)
\r
174 accessor.forVariables(procedure);
\r
178 public Expression accept(ExpressionTransformer transformer) {
\r
179 return transformer.transform(this);
\r