1 package org.simantics.scl.compiler.elaboration.expressions;
\r
3 import org.simantics.scl.compiler.common.names.Names;
\r
4 import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
\r
5 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
\r
6 import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
\r
7 import org.simantics.scl.compiler.elaboration.expressions.accessor.FieldAccessor;
\r
8 import org.simantics.scl.compiler.errors.Locations;
\r
9 import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator;
\r
10 import org.simantics.scl.compiler.types.Type;
\r
11 import org.simantics.scl.compiler.types.Types;
\r
12 import org.simantics.scl.compiler.types.exceptions.MatchException;
\r
14 import gnu.trove.map.hash.TObjectIntHashMap;
\r
15 import gnu.trove.set.hash.THashSet;
\r
16 import gnu.trove.set.hash.TIntHashSet;
\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
84 public Expression simplify(SimplificationContext context) {
\r
85 // Simplify subexpressions
\r
86 parent = parent.simplify(context);
\r
87 for(FieldAccessor accessor : accessors)
\r
88 accessor.simplify(context);
\r
91 Expression result = parent;
\r
92 for(int i=0;i<accessors.length;++i) {
\r
93 FieldAccessor accessor = accessors[i];
\r
94 if(accessor.accessSeparator == '.')
\r
95 result = new EApply(
\r
98 context.getConstant(Names.Simantics_Variables_child_),
\r
100 accessor.asExpression()
\r
102 else if(i < accessors.length-1)
\r
103 result = new EApply(
\r
106 context.getConstant(Names.Simantics_Variables_property),
\r
108 accessor.asExpression()
\r
110 else if(accessor.isVariableId())
\r
113 result = new EApply(
\r
116 context.getConstant(Names.Simantics_Variables_untypedPropertyValue, getType()),
\r
118 accessor.asExpression()
\r
124 private static FieldAccessor[] concat(FieldAccessor[] accessors1,
\r
125 FieldAccessor[] accessors2) {
\r
126 FieldAccessor[] result = new FieldAccessor[accessors1.length + accessors2.length];
\r
127 System.arraycopy(accessors1, 0, result, 0, accessors1.length);
\r
128 System.arraycopy(accessors2, 0, result, accessors1.length, accessors2.length);
\r
133 public Expression resolve(TranslationContext context) {
\r
134 parent = parent.resolve(context);
\r
135 for(FieldAccessor accessor : accessors)
\r
136 accessor.resolve(context);
\r
141 public Expression decorate(ExpressionDecorator decorator) {
\r
142 return decorator.decorate(this);
\r
146 public void collectEffects(THashSet<Type> effects) {
\r
148 effects.add(Types.READ_GRAPH);
\r
152 public void setLocationDeep(long loc) {
\r
153 if(location == Locations.NO_LOCATION) {
\r
155 parent.setLocationDeep(loc);
\r
156 for(FieldAccessor accessor : accessors)
\r
157 accessor.setLocationDeep(loc);
\r
162 public void accept(ExpressionVisitor visitor) {
\r
163 visitor.visit(this);
\r
167 public void forVariables(VariableProcedure procedure) {
\r
168 parent.forVariables(procedure);
\r
169 for(FieldAccessor accessor : accessors)
\r
170 accessor.forVariables(procedure);
\r
174 public Expression accept(ExpressionTransformer transformer) {
\r
175 return transformer.transform(this);
\r