]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EFieldAccess.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / elaboration / expressions / EFieldAccess.java
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EFieldAccess.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EFieldAccess.java
new file mode 100644 (file)
index 0000000..bcb7bf3
--- /dev/null
@@ -0,0 +1,182 @@
+package org.simantics.scl.compiler.elaboration.expressions;\r
+\r
+import gnu.trove.map.hash.TObjectIntHashMap;\r
+import gnu.trove.set.hash.THashSet;\r
+import gnu.trove.set.hash.TIntHashSet;\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
+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