+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