]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EFieldAccess.java
bcb7bf37b867d300306aa17ed8e4727c0e94212b
[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 gnu.trove.map.hash.TObjectIntHashMap;\r
4 import gnu.trove.set.hash.THashSet;\r
5 import gnu.trove.set.hash.TIntHashSet;\r
6 \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
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     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
86 \r
87     @Override\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
93         \r
94         // ...\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
100                         getLocation(),\r
101                         Types.READ_GRAPH,\r
102                         context.getConstant(CHILD),\r
103                         result,\r
104                         accessor.asExpression()\r
105                         );\r
106             else if(i < accessors.length-1)\r
107                 result = new EApply(\r
108                         getLocation(),\r
109                         Types.READ_GRAPH,\r
110                         context.getConstant(PROPERTY),\r
111                         result,\r
112                         accessor.asExpression()\r
113                         );\r
114             else if(accessor.isVariableId())\r
115                 ;\r
116             else\r
117                 result = new EApply(\r
118                         getLocation(),\r
119                         Types.READ_GRAPH,\r
120                         context.getConstant(PROPERTY_VALUE, getType()),\r
121                         result,\r
122                         accessor.asExpression()\r
123                         );\r
124         }\r
125         return result;\r
126     }\r
127 \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
133         return result;\r
134     }\r
135 \r
136     @Override\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
141         return this;\r
142     }\r
143 \r
144     @Override\r
145     public Expression decorate(ExpressionDecorator decorator) {\r
146         return decorator.decorate(this);\r
147     }\r
148 \r
149     @Override\r
150     public void collectEffects(THashSet<Type> effects) {\r
151         // FIXME\r
152         effects.add(Types.READ_GRAPH);\r
153     }\r
154     \r
155     @Override\r
156     public void setLocationDeep(long loc) {\r
157         if(location == Locations.NO_LOCATION) {\r
158             location = loc;\r
159             parent.setLocationDeep(loc);\r
160             for(FieldAccessor accessor : accessors)\r
161                 accessor.setLocationDeep(loc);\r
162         }\r
163     }\r
164     \r
165     @Override\r
166     public void accept(ExpressionVisitor visitor) {\r
167         visitor.visit(this);\r
168     }\r
169 \r
170     @Override\r
171     public void forVariables(VariableProcedure procedure) {\r
172         parent.forVariables(procedure);\r
173         for(FieldAccessor accessor : accessors)\r
174             accessor.forVariables(procedure);\r
175     }\r
176     \r
177     @Override\r
178     public Expression accept(ExpressionTransformer transformer) {\r
179         return transformer.transform(this);\r
180     }\r
181 \r
182 }\r