]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/references/Val.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / internal / codegen / references / Val.java
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/references/Val.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/references/Val.java
new file mode 100644 (file)
index 0000000..392dfb2
--- /dev/null
@@ -0,0 +1,193 @@
+package org.simantics.scl.compiler.internal.codegen.references;\r
+\r
+import gnu.trove.map.hash.THashMap;\r
+\r
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
+import org.simantics.scl.compiler.internal.codegen.types.BTypes;\r
+import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder;\r
+import org.simantics.scl.compiler.top.SCLCompilerConfiguration;\r
+import org.simantics.scl.compiler.types.TVar;\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
+\r
+public abstract class Val implements IVal {\r
+    \r
+    public static final Val[] EMPTY_ARRAY = new Val[0];\r
+    \r
+    transient ValRef occurrence;\r
+    \r
+    @Override\r
+    public final ValRef createOccurrence() {\r
+        return new ValRef(this, Type.EMPTY_ARRAY);\r
+    }\r
+    \r
+    @Override\r
+    public final ValRef createOccurrence(Type ... parameters) {\r
+        return new ValRef(this, parameters);\r
+    }\r
+    \r
+    @Override\r
+    public IVal createSpecialization(Type... parameters) {\r
+        return new ValSpecialization(this, parameters);\r
+    }\r
+    \r
+    public final void replaceBy(ValRef other) {\r
+        if(other.parameters.length == 0)\r
+            replaceBy(other.binding);\r
+        else\r
+            replaceBy(other.binding, other.parameters);\r
+    }\r
+    \r
+    public final ValRef getOccurrence() {\r
+        return occurrence;\r
+    }\r
+    \r
+    private void replaceBy(Val other) {\r
+        ValRef cur = occurrence;\r
+        if(cur != null) {\r
+            while(true) {\r
+                //System.out.println("+ " + other + " - " + cur.binding);\r
+                if(SCLCompilerConfiguration.DEBUG) {\r
+                    if(cur.binding != this)\r
+                        throw new InternalCompilerError("Invalid ValRef encountered when replacing " + this + " by " + other + ".");\r
+                }                \r
+                cur.binding = other;\r
+                cur.updateParentEffect();\r
+                if(cur.next == null)\r
+                    break;\r
+                else\r
+                    cur = cur.next;\r
+            }\r
+            cur.next = other.occurrence;\r
+            if(other.occurrence != null)\r
+                other.occurrence.prev = cur;\r
+            other.occurrence = occurrence;\r
+            occurrence = null;\r
+        }        \r
+    }\r
+    \r
+    private void replaceBy(Val other, Type[] parameters) {\r
+        if(other == this || other == null)\r
+            throw new InternalCompilerError();\r
+        ValRef cur = occurrence;\r
+        if(cur != null) {\r
+            while(true) {\r
+                //System.out.println("+ " + other + " - " + cur.binding);\r
+                if(SCLCompilerConfiguration.DEBUG) {\r
+                    if(cur.binding != this)\r
+                        throw new InternalCompilerError("Invalid ValRef encountered when replacing " + this + " by " + other + ".");\r
+                }\r
+                cur.binding = other;\r
+                cur.parameters = Types.concat(parameters, cur.parameters);\r
+                cur.updateParentEffect();\r
+                if(cur.next == null)\r
+                    break;\r
+                else\r
+                    cur = cur.next;\r
+            }\r
+            cur.next = other.occurrence;\r
+            if(other.occurrence != null)\r
+                other.occurrence.prev = cur;\r
+            other.occurrence = occurrence;\r
+            occurrence = null;\r
+        }\r
+    }\r
+    \r
+    public void replaceBy(Val other, TVar[] from, Type[] to) {\r
+        if(other == this || other == null)\r
+            throw new InternalCompilerError();\r
+        if(from.length == 0)\r
+            replaceBy(other, to);\r
+        else {\r
+            ValRef cur = occurrence;\r
+            if(cur != null) {\r
+                while(true) {\r
+                    //System.out.println("+ " + other + " - " + cur.binding);\r
+                    if(SCLCompilerConfiguration.DEBUG) {\r
+                        if(cur.binding != this)\r
+                            throw new InternalCompilerError("Invalid ValRef encountered when replacing " + this + " by " + other + ".");\r
+                    }\r
+                    cur.binding = other;\r
+                    cur.parameters = Types.replace(to, from, cur.parameters);\r
+                    cur.updateParentEffect();\r
+                    if(cur.next == null)\r
+                        break;\r
+                    else\r
+                        cur = cur.next;\r
+                }\r
+                cur.next = other.occurrence;\r
+                if(other.occurrence != null)\r
+                    other.occurrence.prev = cur;\r
+                other.occurrence = occurrence;\r
+                occurrence = null;\r
+            }\r
+        }        \r
+    }\r
+    \r
+    public abstract Type getType();\r
+\r
+    /**\r
+     * Returns the number of ValRefs of this Val.\r
+     * @return\r
+     */\r
+    public final int occurrenceCount() {\r
+        int count = 0;\r
+        for(ValRef ref = occurrence;ref != null;ref=ref.getNext())\r
+            ++count;\r
+        return count;\r
+    }\r
+    \r
+\r
+    public final boolean hasMoreThanOneOccurences() {\r
+        return occurrence != null && occurrence.getNext() != null;\r
+    }\r
+\r
+    public final boolean hasNoOccurences() {\r
+        return occurrence == null;\r
+    }\r
+\r
+    public abstract Val copy(THashMap<TVar, TVar> tvarMap);\r
+    \r
+    public ValRef[] getOccurences() {\r
+        int count = occurrenceCount();\r
+        if(count == 0)\r
+            return ValRef.EMPTY_ARRAY;\r
+        ValRef[] result = new ValRef[count];\r
+        ValRef cur = occurrence;\r
+        for(int i=0;i<count;++i,cur=cur.getNext())\r
+            result[i] = cur;\r
+        return result;\r
+    }\r
+\r
+    public abstract int getEffectiveArity();\r
+    \r
+    /**\r
+     * Applies given values to this constant. Pushes the result to stack and \r
+     * returns the type of the result value.\r
+     */\r
+    @Override    \r
+    public Type apply(MethodBuilder mb, Type[] typeParameters, Val ... parameters) {\r
+        push(mb);\r
+        if(parameters.length == 0) \r
+            return getType();\r
+        Type returnType;\r
+        try {\r
+            returnType = BTypes.matchFunction(getType(), parameters.length)[parameters.length];            \r
+        } catch (MatchException e) {\r
+            throw new InternalCompilerError();\r
+        }\r
+        mb.pushBoxed(parameters);\r
+        mb.genericApply(parameters.length); \r
+        mb.unbox(returnType);\r
+        return returnType;\r
+    }\r
+    \r
+    @Override\r
+    public void setLabel(String label) {   \r
+    }\r
+    \r
+    public void prepare(MethodBuilder mb) {        \r
+    }\r
+}\r