1 package org.simantics.scl.compiler.elaboration.expressions;
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;
14 import gnu.trove.map.hash.TObjectIntHashMap;
15 import gnu.trove.set.hash.THashSet;
16 import gnu.trove.set.hash.TIntHashSet;
18 public class EFieldAccess extends SimplifiableExpression {
20 private static final Type VARIABLE = Types.con("Simantics/Variables", "Variable");
23 FieldAccessor[] accessors;
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);
32 this.accessors = accessors;
36 public void collectRefs(TObjectIntHashMap<Object> allRefs,
38 parent.collectRefs(allRefs, refs);
39 for(FieldAccessor accessor : accessors)
40 accessor.collectRefs(allRefs, refs);
44 public void collectVars(TObjectIntHashMap<Variable> allVars,
46 parent.collectVars(allVars, vars);
47 for(FieldAccessor accessor : accessors)
48 accessor.collectVars(allVars, vars);
51 private boolean returnsValue() {
52 FieldAccessor lastAccessor = accessors[accessors.length-1];
53 return lastAccessor.accessSeparator=='#' && !lastAccessor.isVariableId();
57 protected void updateType() throws MatchException {
58 // Type is already updated in checkBasicType
62 public Expression checkBasicType(TypingContext context, Type requiredType) {
64 setType(requiredType);
67 context.subsume(this, requiredType);
69 parent = parent.checkType(context, VARIABLE);
70 for(FieldAccessor accessor : accessors)
71 accessor.checkType(context);
72 context.declareEffect(getLocation(), Types.READ_GRAPH);
77 public void collectFreeVariables(THashSet<Variable> vars) {
78 parent.collectFreeVariables(vars);
79 for(FieldAccessor accessor : accessors)
80 accessor.collectFreeVariables(vars);
84 public Expression simplify(SimplificationContext context) {
85 // Simplify subexpressions
86 parent = parent.simplify(context);
87 for(FieldAccessor accessor : accessors)
88 accessor.simplify(context);
91 Expression result = parent;
92 for(int i=0;i<accessors.length;++i) {
93 FieldAccessor accessor = accessors[i];
94 if(accessor.accessSeparator == '.')
98 context.getConstant(Names.Simantics_Variables_child_),
100 accessor.asExpression()
102 else if(i < accessors.length-1)
106 context.getConstant(Names.Simantics_Variables_property),
108 accessor.asExpression()
110 else if(accessor.isVariableId())
116 context.getConstant(Names.Simantics_Variables_untypedPropertyValue, getType()),
118 accessor.asExpression()
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);
133 public Expression resolve(TranslationContext context) {
134 parent = parent.resolve(context);
135 for(FieldAccessor accessor : accessors)
136 accessor.resolve(context);
141 public Expression decorate(ExpressionDecorator decorator) {
142 return decorator.decorate(this);
146 public void collectEffects(THashSet<Type> effects) {
148 effects.add(Types.READ_GRAPH);
152 public void setLocationDeep(long loc) {
153 if(location == Locations.NO_LOCATION) {
155 parent.setLocationDeep(loc);
156 for(FieldAccessor accessor : accessors)
157 accessor.setLocationDeep(loc);
162 public void accept(ExpressionVisitor visitor) {
167 public void forVariables(VariableProcedure procedure) {
168 parent.forVariables(procedure);
169 for(FieldAccessor accessor : accessors)
170 accessor.forVariables(procedure);
174 public Expression accept(ExpressionTransformer transformer) {
175 return transformer.transform(this);