]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EFieldAccess.java
4ebd0248d5f799d1fdfe2023cee77f93d0db7f31
[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;
2
3 import org.simantics.scl.compiler.common.names.Names;
4 import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
5 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
6 import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
7 import org.simantics.scl.compiler.elaboration.expressions.accessor.FieldAccessor;
8 import org.simantics.scl.compiler.errors.Locations;
9 import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator;
10 import org.simantics.scl.compiler.types.Type;
11 import org.simantics.scl.compiler.types.Types;
12 import org.simantics.scl.compiler.types.exceptions.MatchException;
13
14 import gnu.trove.map.hash.TObjectIntHashMap;
15 import gnu.trove.set.hash.THashSet;
16 import gnu.trove.set.hash.TIntHashSet;
17
18 public class EFieldAccess extends SimplifiableExpression {
19
20     private static final Type VARIABLE = Types.con("Simantics/Variables", "Variable");
21     
22     Expression parent;
23     FieldAccessor[] accessors;
24
25     public EFieldAccess(Expression parent, FieldAccessor[] accessors) {
26         if(parent instanceof EFieldAccess) {
27             EFieldAccess parentAccess = (EFieldAccess)parent;
28             parent = parentAccess.parent;
29             accessors = concat(parentAccess.accessors, accessors);
30         }
31         this.parent = parent;
32         this.accessors = accessors;
33     }
34
35     @Override
36     public void collectRefs(TObjectIntHashMap<Object> allRefs,
37             TIntHashSet refs) {
38         parent.collectRefs(allRefs, refs);
39         for(FieldAccessor accessor : accessors)
40             accessor.collectRefs(allRefs, refs);
41     }
42
43     @Override
44     public void collectVars(TObjectIntHashMap<Variable> allVars,
45             TIntHashSet vars) {
46         parent.collectVars(allVars, vars);
47         for(FieldAccessor accessor : accessors)
48             accessor.collectVars(allVars, vars);
49     }
50
51     private boolean returnsValue() {
52         FieldAccessor lastAccessor = accessors[accessors.length-1];
53         return lastAccessor.accessSeparator=='#' && !lastAccessor.isVariableId();
54     }
55
56     @Override
57     protected void updateType() throws MatchException {
58         // Type is already updated in checkBasicType
59     }
60     
61     @Override
62     public Expression checkBasicType(TypingContext context, Type requiredType) {
63         if(returnsValue())
64             setType(requiredType);
65         else {
66             setType(VARIABLE);
67             context.subsume(this, requiredType);
68         }
69         parent = parent.checkType(context, VARIABLE);
70         for(FieldAccessor accessor : accessors)
71             accessor.checkType(context);
72         context.declareEffect(getLocation(), Types.READ_GRAPH);
73         return this;
74     }
75
76     @Override
77     public void collectFreeVariables(THashSet<Variable> vars) {
78         parent.collectFreeVariables(vars);
79         for(FieldAccessor accessor : accessors)
80             accessor.collectFreeVariables(vars);
81     }
82
83     @Override
84     public Expression simplify(SimplificationContext context) {
85         // Simplify subexpressions
86         parent = parent.simplify(context);
87         for(FieldAccessor accessor : accessors)
88             accessor.simplify(context);
89         
90         // ...
91         Expression result = parent;
92         for(int i=0;i<accessors.length;++i) {
93             FieldAccessor accessor = accessors[i];
94             if(accessor.accessSeparator == '.')
95                 result = new EApply(
96                         getLocation(),
97                         Types.READ_GRAPH,
98                         context.getConstant(Names.Simantics_Variables_child_),
99                         result,
100                         accessor.asExpression()
101                         );
102             else if(i < accessors.length-1)
103                 result = new EApply(
104                         getLocation(),
105                         Types.READ_GRAPH,
106                         context.getConstant(Names.Simantics_Variables_property),
107                         result,
108                         accessor.asExpression()
109                         );
110             else if(accessor.isVariableId())
111                 ;
112             else
113                 result = new EApply(
114                         getLocation(),
115                         Types.READ_GRAPH,
116                         context.getConstant(Names.Simantics_Variables_untypedPropertyValue, getType()),
117                         result,
118                         accessor.asExpression()
119                         );
120         }
121         return result;
122     }
123
124     private static FieldAccessor[] concat(FieldAccessor[] accessors1,
125             FieldAccessor[] accessors2) {
126         FieldAccessor[] result = new FieldAccessor[accessors1.length + accessors2.length];
127         System.arraycopy(accessors1, 0, result, 0, accessors1.length);
128         System.arraycopy(accessors2, 0, result, accessors1.length, accessors2.length);
129         return result;
130     }
131
132     @Override
133     public Expression resolve(TranslationContext context) {
134         parent = parent.resolve(context);
135         for(FieldAccessor accessor : accessors)
136             accessor.resolve(context);
137         return this;
138     }
139
140     @Override
141     public Expression decorate(ExpressionDecorator decorator) {
142         return decorator.decorate(this);
143     }
144
145     @Override
146     public void collectEffects(THashSet<Type> effects) {
147         // FIXME
148         effects.add(Types.READ_GRAPH);
149     }
150     
151     @Override
152     public void setLocationDeep(long loc) {
153         if(location == Locations.NO_LOCATION) {
154             location = loc;
155             parent.setLocationDeep(loc);
156             for(FieldAccessor accessor : accessors)
157                 accessor.setLocationDeep(loc);
158         }
159     }
160     
161     @Override
162     public void accept(ExpressionVisitor visitor) {
163         visitor.visit(this);
164     }
165
166     @Override
167     public void forVariables(VariableProcedure procedure) {
168         parent.forVariables(procedure);
169         for(FieldAccessor accessor : accessors)
170             accessor.forVariables(procedure);
171     }
172     
173     @Override
174     public Expression accept(ExpressionTransformer transformer) {
175         return transformer.transform(this);
176     }
177
178 }