]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EFieldAccess.java
Merge "Re-enabled Acorn transaction cancellation support for testing"
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / expressions / EFieldAccess.java
1 package org.simantics.scl.compiler.elaboration.expressions;\r
2 \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
13 \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
17 \r
18 public class EFieldAccess extends SimplifiableExpression {\r
19 \r
20     private static final Type VARIABLE = Types.con("Simantics/Variables", "Variable");\r
21     \r
22     Expression parent;\r
23     FieldAccessor[] accessors;\r
24 \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
30         }\r
31         this.parent = parent;\r
32         this.accessors = accessors;\r
33     }\r
34 \r
35     @Override\r
36     public void collectRefs(TObjectIntHashMap<Object> allRefs,\r
37             TIntHashSet refs) {\r
38         parent.collectRefs(allRefs, refs);\r
39         for(FieldAccessor accessor : accessors)\r
40             accessor.collectRefs(allRefs, refs);\r
41     }\r
42 \r
43     @Override\r
44     public void collectVars(TObjectIntHashMap<Variable> allVars,\r
45             TIntHashSet vars) {\r
46         parent.collectVars(allVars, vars);\r
47         for(FieldAccessor accessor : accessors)\r
48             accessor.collectVars(allVars, vars);\r
49     }\r
50 \r
51     private boolean returnsValue() {\r
52         FieldAccessor lastAccessor = accessors[accessors.length-1];\r
53         return lastAccessor.accessSeparator=='#' && !lastAccessor.isVariableId();\r
54     }\r
55 \r
56     @Override\r
57     protected void updateType() throws MatchException {\r
58         // Type is already updated in checkBasicType\r
59     }\r
60     \r
61     @Override\r
62     public Expression checkBasicType(TypingContext context, Type requiredType) {\r
63         if(returnsValue())\r
64             setType(requiredType);\r
65         else {\r
66             setType(VARIABLE);\r
67             context.subsume(this, requiredType);\r
68         }\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
73         return this;\r
74     }\r
75 \r
76     @Override\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
81     }\r
82 \r
83     @Override\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
89         \r
90         // ...\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
96                         getLocation(),\r
97                         Types.READ_GRAPH,\r
98                         context.getConstant(Names.Simantics_Variables_child_),\r
99                         result,\r
100                         accessor.asExpression()\r
101                         );\r
102             else if(i < accessors.length-1)\r
103                 result = new EApply(\r
104                         getLocation(),\r
105                         Types.READ_GRAPH,\r
106                         context.getConstant(Names.Simantics_Variables_property),\r
107                         result,\r
108                         accessor.asExpression()\r
109                         );\r
110             else if(accessor.isVariableId())\r
111                 ;\r
112             else\r
113                 result = new EApply(\r
114                         getLocation(),\r
115                         Types.READ_GRAPH,\r
116                         context.getConstant(Names.Simantics_Variables_untypedPropertyValue, getType()),\r
117                         result,\r
118                         accessor.asExpression()\r
119                         );\r
120         }\r
121         return result;\r
122     }\r
123 \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
129         return result;\r
130     }\r
131 \r
132     @Override\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
137         return this;\r
138     }\r
139 \r
140     @Override\r
141     public Expression decorate(ExpressionDecorator decorator) {\r
142         return decorator.decorate(this);\r
143     }\r
144 \r
145     @Override\r
146     public void collectEffects(THashSet<Type> effects) {\r
147         // FIXME\r
148         effects.add(Types.READ_GRAPH);\r
149     }\r
150     \r
151     @Override\r
152     public void setLocationDeep(long loc) {\r
153         if(location == Locations.NO_LOCATION) {\r
154             location = loc;\r
155             parent.setLocationDeep(loc);\r
156             for(FieldAccessor accessor : accessors)\r
157                 accessor.setLocationDeep(loc);\r
158         }\r
159     }\r
160     \r
161     @Override\r
162     public void accept(ExpressionVisitor visitor) {\r
163         visitor.visit(this);\r
164     }\r
165 \r
166     @Override\r
167     public void forVariables(VariableProcedure procedure) {\r
168         parent.forVariables(procedure);\r
169         for(FieldAccessor accessor : accessors)\r
170             accessor.forVariables(procedure);\r
171     }\r
172     \r
173     @Override\r
174     public Expression accept(ExpressionTransformer transformer) {\r
175         return transformer.transform(this);\r
176     }\r
177 \r
178 }\r