1 package org.simantics.scl.compiler.elaboration.expressions;
5 import org.simantics.scl.compiler.common.names.Names;
6 import org.simantics.scl.compiler.constants.Constant;
7 import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
8 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
9 import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
10 import org.simantics.scl.compiler.elaboration.expressions.EAmbiguous.Alternative;
11 import org.simantics.scl.compiler.elaboration.expressions.accessor.FieldAccessor;
12 import org.simantics.scl.compiler.elaboration.expressions.accessor.IdAccessor;
13 import org.simantics.scl.compiler.errors.Locations;
14 import org.simantics.scl.compiler.internal.header.ModuleHeader;
15 import org.simantics.scl.compiler.types.Type;
16 import org.simantics.scl.compiler.types.Types;
17 import org.simantics.scl.compiler.types.exceptions.MatchException;
19 public class EFieldAccess extends SimplifiableExpression {
21 private static final Type VARIABLE = Types.con("Simantics/Variables", "Variable");
23 public Expression parent;
24 public FieldAccessor accessor;
25 boolean lastAccessor = true;
27 public EFieldAccess(Expression parent, FieldAccessor accessor) {
29 this.accessor = accessor;
30 if(parent instanceof EFieldAccess)
31 ((EFieldAccess)parent).lastAccessor = false;
34 private boolean returnsValue() {
35 return accessor.accessSeparator == '#' && !accessor.isVariableId();
39 protected void updateType() throws MatchException {
40 // Type is already updated in checkBasicType
43 private Expression resolveAccessor(TypingContext context, Type requiredType) {
44 if(!(accessor instanceof IdAccessor))
46 IdAccessor idAccessor = (IdAccessor)accessor;
47 if(idAccessor.accessSeparator != '.')
49 List<Constant> accessors = context.getEnvironment().getFieldAccessors(idAccessor.fieldName);
50 if(accessors == null) {
51 context.getErrorLog().log(idAccessor.location, "Couldn't resolve accessor ." + idAccessor.fieldName + ".");
52 return new EError(location);
54 Expression accessorExpression;
55 if(accessors.size() == 1)
56 accessorExpression = new ELiteral(accessors.get(0));
58 Alternative[] alternatives = new Alternative[accessors.size()];
59 for(int i=0;i<alternatives.length;++i) {
61 alternatives[i] = new Alternative() {
63 public Expression realize() {
64 return new ELiteral(accessors.get(index));
67 public Type getType() {
68 return accessors.get(index).getType();
71 public String toString() {
72 return accessors.get(index).toString();
76 accessorExpression = new EAmbiguous(alternatives);
77 accessorExpression.location = location;
79 return new EApply(location, accessorExpression, parent).checkType(context, requiredType);
83 public Expression checkBasicType(TypingContext context, Type requiredType) {
84 ModuleHeader header = context.getCompilationContext().header;
85 if(header != null && header.fields) {
86 Expression expression = resolveAccessor(context, requiredType);
87 if(expression != null)
93 setType(requiredType);
96 context.subsume(this, requiredType);
98 parent = parent.checkType(context, VARIABLE);
99 accessor.checkType(context);
100 context.declareEffect(getLocation(), Types.READ_GRAPH);
105 public Expression simplify(SimplificationContext context) {
106 // Simplify subexpressions
107 parent = parent.simplify(context);
108 accessor.simplify(context);
110 if(accessor.accessSeparator == '.')
114 context.getConstant(Names.Simantics_Variables_child_),
116 accessor.asExpression()
118 else if(!lastAccessor)
122 context.getConstant(Names.Simantics_Variables_property),
124 accessor.asExpression()
126 else if(accessor.isVariableId())
132 context.getConstant(Names.Simantics_Variables_untypedPropertyValue, getType()),
134 accessor.asExpression()
139 public Expression resolve(TranslationContext context) {
140 parent = parent.resolve(context);
141 accessor.resolve(context);
146 public void setLocationDeep(long loc) {
147 if(location == Locations.NO_LOCATION) {
149 parent.setLocationDeep(loc);
150 accessor.setLocationDeep(loc);
155 public void accept(ExpressionVisitor visitor) {
160 public Expression accept(ExpressionTransformer transformer) {
161 return transformer.transform(this);