]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EFieldAccess.java
(refs #7278, refs #7279) Small fixes to InternalCompilerExceptions
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / expressions / EFieldAccess.java
index 4ebd0248d5f799d1fdfe2023cee77f93d0db7f31..0d3e2eeaf3600e32aa1ca5206293f40d4182006d 100644 (file)
@@ -1,12 +1,18 @@
 package org.simantics.scl.compiler.elaboration.expressions;
 
+import java.util.List;
+
 import org.simantics.scl.compiler.common.names.Names;
+import org.simantics.scl.compiler.constants.Constant;
 import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;
 import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
 import org.simantics.scl.compiler.elaboration.contexts.TypingContext;
+import org.simantics.scl.compiler.elaboration.expressions.EAmbiguous.Alternative;
 import org.simantics.scl.compiler.elaboration.expressions.accessor.FieldAccessor;
+import org.simantics.scl.compiler.elaboration.expressions.accessor.IdAccessor;
 import org.simantics.scl.compiler.errors.Locations;
 import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator;
+import org.simantics.scl.compiler.internal.header.ModuleHeader;
 import org.simantics.scl.compiler.types.Type;
 import org.simantics.scl.compiler.types.Types;
 import org.simantics.scl.compiler.types.exceptions.MatchException;
@@ -20,37 +26,32 @@ public class EFieldAccess extends SimplifiableExpression {
     private static final Type VARIABLE = Types.con("Simantics/Variables", "Variable");
     
     Expression parent;
-    FieldAccessor[] accessors;
+    FieldAccessor accessor;
+    boolean lastAccessor = true;
 
-    public EFieldAccess(Expression parent, FieldAccessor[] accessors) {
-        if(parent instanceof EFieldAccess) {
-            EFieldAccess parentAccess = (EFieldAccess)parent;
-            parent = parentAccess.parent;
-            accessors = concat(parentAccess.accessors, accessors);
-        }
+    public EFieldAccess(Expression parent, FieldAccessor accessor) {
         this.parent = parent;
-        this.accessors = accessors;
+        this.accessor = accessor;
+        if(parent instanceof EFieldAccess)
+               ((EFieldAccess)parent).lastAccessor = false;
     }
 
     @Override
     public void collectRefs(TObjectIntHashMap<Object> allRefs,
             TIntHashSet refs) {
         parent.collectRefs(allRefs, refs);
-        for(FieldAccessor accessor : accessors)
-            accessor.collectRefs(allRefs, refs);
+        accessor.collectRefs(allRefs, refs);
     }
 
     @Override
     public void collectVars(TObjectIntHashMap<Variable> allVars,
             TIntHashSet vars) {
         parent.collectVars(allVars, vars);
-        for(FieldAccessor accessor : accessors)
-            accessor.collectVars(allVars, vars);
+        accessor.collectVars(allVars, vars);
     }
 
     private boolean returnsValue() {
-        FieldAccessor lastAccessor = accessors[accessors.length-1];
-        return lastAccessor.accessSeparator=='#' && !lastAccessor.isVariableId();
+       return accessor.accessSeparator == '#' && !accessor.isVariableId();
     }
 
     @Override
@@ -58,8 +59,51 @@ public class EFieldAccess extends SimplifiableExpression {
         // Type is already updated in checkBasicType
     }
     
+    private Expression resolveAccessor(TypingContext context, Type requiredType) {
+        if(!(accessor instanceof IdAccessor))
+            return null;
+        IdAccessor idAccessor = (IdAccessor)accessor;
+        if(idAccessor.accessSeparator != '.')
+            return null;
+        List<Constant> accessors = context.getEnvironment().getFieldAccessors(idAccessor.fieldName);
+        if(accessors == null) {
+            context.getErrorLog().log("Couldn't resolve accessor ." + idAccessor.fieldName + ".");
+            return new EError(location);
+        }
+        Expression accessorExpression;
+        if(accessors.size() == 1)
+            accessorExpression = new ELiteral(accessors.get(0));
+        else {
+            Alternative[] alternatives = new Alternative[accessors.size()];
+            for(int i=0;i<alternatives.length;++i) {
+                final int index = i;
+                alternatives[i] = new Alternative() {
+                    @Override
+                    public Expression realize() {
+                        return new ELiteral(accessors.get(index));
+                    }
+                    @Override
+                    public Type getType() {
+                        return accessors.get(index).getType();
+                    }
+                };
+            }
+            accessorExpression = new EAmbiguous(alternatives);
+            accessorExpression.location = location;
+        }
+        return new EApply(location, accessorExpression, parent).checkType(context, requiredType);
+    }
+    
     @Override
     public Expression checkBasicType(TypingContext context, Type requiredType) {
+        ModuleHeader header = context.getCompilationContext().header;
+        if(header != null && header.fields) {
+            Expression expression = resolveAccessor(context, requiredType);
+            if(expression != null)
+                return expression;
+        }
+        
+        // Default case
         if(returnsValue())
             setType(requiredType);
         else {
@@ -67,8 +111,7 @@ public class EFieldAccess extends SimplifiableExpression {
             context.subsume(this, requiredType);
         }
         parent = parent.checkType(context, VARIABLE);
-        for(FieldAccessor accessor : accessors)
-            accessor.checkType(context);
+        accessor.checkType(context);
         context.declareEffect(getLocation(), Types.READ_GRAPH);
         return this;
     }
@@ -76,64 +119,47 @@ public class EFieldAccess extends SimplifiableExpression {
     @Override
     public void collectFreeVariables(THashSet<Variable> vars) {
         parent.collectFreeVariables(vars);
-        for(FieldAccessor accessor : accessors)
-            accessor.collectFreeVariables(vars);
+        accessor.collectFreeVariables(vars);
     }
 
     @Override
     public Expression simplify(SimplificationContext context) {
         // Simplify subexpressions
         parent = parent.simplify(context);
-        for(FieldAccessor accessor : accessors)
-            accessor.simplify(context);
+        accessor.simplify(context);
         
-        // ...
-        Expression result = parent;
-        for(int i=0;i<accessors.length;++i) {
-            FieldAccessor accessor = accessors[i];
-            if(accessor.accessSeparator == '.')
-                result = new EApply(
-                        getLocation(),
-                        Types.READ_GRAPH,
-                        context.getConstant(Names.Simantics_Variables_child_),
-                        result,
-                        accessor.asExpression()
-                        );
-            else if(i < accessors.length-1)
-                result = new EApply(
-                        getLocation(),
-                        Types.READ_GRAPH,
-                        context.getConstant(Names.Simantics_Variables_property),
-                        result,
-                        accessor.asExpression()
-                        );
-            else if(accessor.isVariableId())
-                ;
-            else
-                result = new EApply(
-                        getLocation(),
-                        Types.READ_GRAPH,
-                        context.getConstant(Names.Simantics_Variables_untypedPropertyValue, getType()),
-                        result,
-                        accessor.asExpression()
-                        );
-        }
-        return result;
-    }
-
-    private static FieldAccessor[] concat(FieldAccessor[] accessors1,
-            FieldAccessor[] accessors2) {
-        FieldAccessor[] result = new FieldAccessor[accessors1.length + accessors2.length];
-        System.arraycopy(accessors1, 0, result, 0, accessors1.length);
-        System.arraycopy(accessors2, 0, result, accessors1.length, accessors2.length);
-        return result;
+        if(accessor.accessSeparator == '.')
+               return new EApply(
+                               getLocation(),
+                               Types.READ_GRAPH,
+                               context.getConstant(Names.Simantics_Variables_child_),
+                               parent,
+                               accessor.asExpression()
+                               );
+        else if(!lastAccessor)
+               return new EApply(
+                               getLocation(),
+                               Types.READ_GRAPH,
+                               context.getConstant(Names.Simantics_Variables_property),
+                               parent,
+                               accessor.asExpression()
+                               );
+        else if(accessor.isVariableId())
+               return parent;
+        else
+               return new EApply(
+                               getLocation(),
+                               Types.READ_GRAPH,
+                               context.getConstant(Names.Simantics_Variables_untypedPropertyValue, getType()),
+                               parent,
+                               accessor.asExpression()
+                               );
     }
 
     @Override
     public Expression resolve(TranslationContext context) {
         parent = parent.resolve(context);
-        for(FieldAccessor accessor : accessors)
-            accessor.resolve(context);
+        accessor.resolve(context);
         return this;
     }
 
@@ -153,8 +179,7 @@ public class EFieldAccess extends SimplifiableExpression {
         if(location == Locations.NO_LOCATION) {
             location = loc;
             parent.setLocationDeep(loc);
-            for(FieldAccessor accessor : accessors)
-                accessor.setLocationDeep(loc);
+            accessor.setLocationDeep(loc);
         }
     }
     
@@ -166,8 +191,7 @@ public class EFieldAccess extends SimplifiableExpression {
     @Override
     public void forVariables(VariableProcedure procedure) {
         parent.forVariables(procedure);
-        for(FieldAccessor accessor : accessors)
-            accessor.forVariables(procedure);
+        accessor.forVariables(procedure);
     }
     
     @Override