]> 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 b49999c06e72c35b021f99bacba81c02b54dd2b9..0d3e2eeaf3600e32aa1ca5206293f40d4182006d 100644 (file)
-package org.simantics.scl.compiler.elaboration.expressions;\r
-\r
-import org.simantics.scl.compiler.common.names.Name;\r
-import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext;\r
-import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;\r
-import org.simantics.scl.compiler.elaboration.contexts.TypingContext;\r
-import org.simantics.scl.compiler.elaboration.expressions.accessor.FieldAccessor;\r
-import org.simantics.scl.compiler.errors.Locations;\r
-import org.simantics.scl.compiler.internal.elaboration.utils.ExpressionDecorator;\r
-import org.simantics.scl.compiler.types.Type;\r
-import org.simantics.scl.compiler.types.Types;\r
-import org.simantics.scl.compiler.types.exceptions.MatchException;\r
-\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-import gnu.trove.set.hash.THashSet;\r
-import gnu.trove.set.hash.TIntHashSet;\r
-\r
-public class EFieldAccess extends SimplifiableExpression {\r
-\r
-    private static final Type VARIABLE = Types.con("Simantics/Variables", "Variable");\r
-    \r
-    Expression parent;\r
-    FieldAccessor[] accessors;\r
-\r
-    public EFieldAccess(Expression parent, FieldAccessor[] accessors) {\r
-        if(parent instanceof EFieldAccess) {\r
-            EFieldAccess parentAccess = (EFieldAccess)parent;\r
-            parent = parentAccess.parent;\r
-            accessors = concat(parentAccess.accessors, accessors);\r
-        }\r
-        this.parent = parent;\r
-        this.accessors = accessors;\r
-    }\r
-\r
-    @Override\r
-    public void collectRefs(TObjectIntHashMap<Object> allRefs,\r
-            TIntHashSet refs) {\r
-        parent.collectRefs(allRefs, refs);\r
-        for(FieldAccessor accessor : accessors)\r
-            accessor.collectRefs(allRefs, refs);\r
-    }\r
-\r
-    @Override\r
-    public void collectVars(TObjectIntHashMap<Variable> allVars,\r
-            TIntHashSet vars) {\r
-        parent.collectVars(allVars, vars);\r
-        for(FieldAccessor accessor : accessors)\r
-            accessor.collectVars(allVars, vars);\r
-    }\r
-\r
-    private boolean returnsValue() {\r
-        FieldAccessor lastAccessor = accessors[accessors.length-1];\r
-        return lastAccessor.accessSeparator=='#' && !lastAccessor.isVariableId();\r
-    }\r
-\r
-    @Override\r
-    protected void updateType() throws MatchException {\r
-        // Type is already updated in checkBasicType\r
-    }\r
-    \r
-    @Override\r
-    public Expression checkBasicType(TypingContext context, Type requiredType) {\r
-        if(returnsValue())\r
-            setType(requiredType);\r
-        else {\r
-            setType(VARIABLE);\r
-            context.subsume(this, requiredType);\r
-        }\r
-        parent = parent.checkType(context, VARIABLE);\r
-        for(FieldAccessor accessor : accessors)\r
-            accessor.checkType(context);\r
-        context.declareEffect(getLocation(), Types.READ_GRAPH);\r
-        return this;\r
-    }\r
-\r
-    @Override\r
-    public void collectFreeVariables(THashSet<Variable> vars) {\r
-        parent.collectFreeVariables(vars);\r
-        for(FieldAccessor accessor : accessors)\r
-            accessor.collectFreeVariables(vars);\r
-    }\r
-\r
-    private static final Name CHILD = Name.create("Simantics/Variables", "child_");\r
-    private static final Name PROPERTY = Name.create("Simantics/Variables", "property");\r
-    private static final Name PROPERTY_VALUE = Name.create("Simantics/Variables", "untypedPropertyValue");\r
-\r
-    @Override\r
-    public Expression simplify(SimplificationContext context) {\r
-        // Simplify subexpressions\r
-        parent = parent.simplify(context);\r
-        for(FieldAccessor accessor : accessors)\r
-            accessor.simplify(context);\r
-        \r
-        // ...\r
-        Expression result = parent;\r
-        for(int i=0;i<accessors.length;++i) {\r
-            FieldAccessor accessor = accessors[i];\r
-            if(accessor.accessSeparator == '.')\r
-                result = new EApply(\r
-                        getLocation(),\r
-                        Types.READ_GRAPH,\r
-                        context.getConstant(CHILD),\r
-                        result,\r
-                        accessor.asExpression()\r
-                        );\r
-            else if(i < accessors.length-1)\r
-                result = new EApply(\r
-                        getLocation(),\r
-                        Types.READ_GRAPH,\r
-                        context.getConstant(PROPERTY),\r
-                        result,\r
-                        accessor.asExpression()\r
-                        );\r
-            else if(accessor.isVariableId())\r
-                ;\r
-            else\r
-                result = new EApply(\r
-                        getLocation(),\r
-                        Types.READ_GRAPH,\r
-                        context.getConstant(PROPERTY_VALUE, getType()),\r
-                        result,\r
-                        accessor.asExpression()\r
-                        );\r
-        }\r
-        return result;\r
-    }\r
-\r
-    private static FieldAccessor[] concat(FieldAccessor[] accessors1,\r
-            FieldAccessor[] accessors2) {\r
-        FieldAccessor[] result = new FieldAccessor[accessors1.length + accessors2.length];\r
-        System.arraycopy(accessors1, 0, result, 0, accessors1.length);\r
-        System.arraycopy(accessors2, 0, result, accessors1.length, accessors2.length);\r
-        return result;\r
-    }\r
-\r
-    @Override\r
-    public Expression resolve(TranslationContext context) {\r
-        parent = parent.resolve(context);\r
-        for(FieldAccessor accessor : accessors)\r
-            accessor.resolve(context);\r
-        return this;\r
-    }\r
-\r
-    @Override\r
-    public Expression decorate(ExpressionDecorator decorator) {\r
-        return decorator.decorate(this);\r
-    }\r
-\r
-    @Override\r
-    public void collectEffects(THashSet<Type> effects) {\r
-        // FIXME\r
-        effects.add(Types.READ_GRAPH);\r
-    }\r
-    \r
-    @Override\r
-    public void setLocationDeep(long loc) {\r
-        if(location == Locations.NO_LOCATION) {\r
-            location = loc;\r
-            parent.setLocationDeep(loc);\r
-            for(FieldAccessor accessor : accessors)\r
-                accessor.setLocationDeep(loc);\r
-        }\r
-    }\r
-    \r
-    @Override\r
-    public void accept(ExpressionVisitor visitor) {\r
-        visitor.visit(this);\r
-    }\r
-\r
-    @Override\r
-    public void forVariables(VariableProcedure procedure) {\r
-        parent.forVariables(procedure);\r
-        for(FieldAccessor accessor : accessors)\r
-            accessor.forVariables(procedure);\r
-    }\r
-    \r
-    @Override\r
-    public Expression accept(ExpressionTransformer transformer) {\r
-        return transformer.transform(this);\r
-    }\r
-\r
-}\r
+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;
+
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.set.hash.THashSet;
+import gnu.trove.set.hash.TIntHashSet;
+
+public class EFieldAccess extends SimplifiableExpression {
+
+    private static final Type VARIABLE = Types.con("Simantics/Variables", "Variable");
+    
+    Expression parent;
+    FieldAccessor accessor;
+    boolean lastAccessor = true;
+
+    public EFieldAccess(Expression parent, FieldAccessor accessor) {
+        this.parent = parent;
+        this.accessor = accessor;
+        if(parent instanceof EFieldAccess)
+               ((EFieldAccess)parent).lastAccessor = false;
+    }
+
+    @Override
+    public void collectRefs(TObjectIntHashMap<Object> allRefs,
+            TIntHashSet refs) {
+        parent.collectRefs(allRefs, refs);
+        accessor.collectRefs(allRefs, refs);
+    }
+
+    @Override
+    public void collectVars(TObjectIntHashMap<Variable> allVars,
+            TIntHashSet vars) {
+        parent.collectVars(allVars, vars);
+        accessor.collectVars(allVars, vars);
+    }
+
+    private boolean returnsValue() {
+       return accessor.accessSeparator == '#' && !accessor.isVariableId();
+    }
+
+    @Override
+    protected void updateType() throws MatchException {
+        // 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 {
+            setType(VARIABLE);
+            context.subsume(this, requiredType);
+        }
+        parent = parent.checkType(context, VARIABLE);
+        accessor.checkType(context);
+        context.declareEffect(getLocation(), Types.READ_GRAPH);
+        return this;
+    }
+
+    @Override
+    public void collectFreeVariables(THashSet<Variable> vars) {
+        parent.collectFreeVariables(vars);
+        accessor.collectFreeVariables(vars);
+    }
+
+    @Override
+    public Expression simplify(SimplificationContext context) {
+        // Simplify subexpressions
+        parent = parent.simplify(context);
+        accessor.simplify(context);
+        
+        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);
+        accessor.resolve(context);
+        return this;
+    }
+
+    @Override
+    public Expression decorate(ExpressionDecorator decorator) {
+        return decorator.decorate(this);
+    }
+
+    @Override
+    public void collectEffects(THashSet<Type> effects) {
+        // FIXME
+        effects.add(Types.READ_GRAPH);
+    }
+    
+    @Override
+    public void setLocationDeep(long loc) {
+        if(location == Locations.NO_LOCATION) {
+            location = loc;
+            parent.setLocationDeep(loc);
+            accessor.setLocationDeep(loc);
+        }
+    }
+    
+    @Override
+    public void accept(ExpressionVisitor visitor) {
+        visitor.visit(this);
+    }
+
+    @Override
+    public void forVariables(VariableProcedure procedure) {
+        parent.forVariables(procedure);
+        accessor.forVariables(procedure);
+    }
+    
+    @Override
+    public Expression accept(ExpressionTransformer transformer) {
+        return transformer.transform(this);
+    }
+
+}