--- /dev/null
+package org.simantics.scl.compiler.internal.codegen.references;\r
+\r
+import java.util.ArrayList;\r
+import java.util.List;\r
+\r
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
+import org.simantics.scl.compiler.internal.codegen.ssa.SSAFunction;\r
+import org.simantics.scl.compiler.internal.codegen.ssa.binders.ValRefBinder;\r
+import org.simantics.scl.compiler.internal.codegen.ssa.statements.LetApply;\r
+import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder;\r
+import org.simantics.scl.compiler.internal.codegen.utils.SSASimplificationContext;\r
+import org.simantics.scl.compiler.internal.codegen.utils.TransientClassBuilder;\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
+\r
+public final class ValRef implements IVal {\r
+ public static final ValRef[] EMPTY_ARRAY = new ValRef[0];\r
+\r
+ Val binding;\r
+ ValRef prev; // FreeVars with the same binding form a linked list\r
+ ValRef next; \r
+ ValRefBinder parent;\r
+ Type[] parameters;\r
+ \r
+ /**\r
+ * Just for deserialization\r
+ */\r
+ public ValRef(Type[] parameters) {\r
+ this.parameters = parameters;\r
+ }\r
+ \r
+ ValRef(Val binding, Type[] parameters) {\r
+ //System.out.println("+ " + bindin g);\r
+ this.parameters = parameters; \r
+ setBinding(binding);\r
+ } \r
+ \r
+ public void setBinding(Val binding) {\r
+ this.binding = binding;\r
+ \r
+ ValRef head = binding.occurrence;\r
+ binding.occurrence = this;\r
+ this.next = head;\r
+ this.prev = null;\r
+ if(head != null)\r
+ head.prev = this;\r
+ }\r
+ \r
+ int removeModiId = -1;\r
+ public void remove() {\r
+ //System.out.println("- " + binding);\r
+ if(prev == null)\r
+ try {\r
+ binding.occurrence = next;\r
+ } catch(NullPointerException e) {\r
+ System.err.println("removeModiId = " + removeModiId);\r
+ System.err.println("current ModiId = " + SSASimplificationContext.modiId);\r
+ throw new InternalCompilerError("The ValRef has already been removed.");\r
+ }\r
+ else\r
+ prev.next = next;\r
+ if(next != null)\r
+ next.prev = prev;\r
+ if(SCLCompilerConfiguration.DEBUG) {\r
+ next = null;\r
+ prev = null;\r
+ binding = null;\r
+ }\r
+ removeModiId = SSASimplificationContext.modiId;\r
+ }\r
+ \r
+ public Val getBinding() {\r
+ return binding;\r
+ }\r
+ \r
+ public ValRef getNext() {\r
+ return next;\r
+ }\r
+ \r
+ public static Val[] getBindings(ValRef[] refs) {\r
+ Val[] result = new Val[refs.length];\r
+ for(int i=0;i<refs.length;++i)\r
+ result[i] = refs[i].getBinding();\r
+ return result;\r
+ }\r
+\r
+ @Override\r
+ public ValRef createOccurrence() {\r
+ return binding.createOccurrence(parameters);\r
+ }\r
+\r
+ @Override\r
+ public ValRef createOccurrence(Type... otherParameters) {\r
+ return binding.createOccurrence(Types.concat(parameters, otherParameters));\r
+ }\r
+ \r
+ @Override\r
+ public IVal createSpecialization(Type... otherParameters) {\r
+ return new ValSpecialization(binding, Types.concat(parameters, otherParameters));\r
+ }\r
+\r
+ public void setParent(ValRefBinder parent) {\r
+ this.parent = parent;\r
+ }\r
+ \r
+ @Override\r
+ public Type getType() {\r
+ if(parameters.length == 0)\r
+ return binding.getType();\r
+ else\r
+ return Types.instantiate(binding.getType(), parameters); \r
+ }\r
+ \r
+ public static ValRef[] createOccurrences(IVal[] vals) {\r
+ ValRef[] result = new ValRef[vals.length];\r
+ for(int i=0;i<vals.length;++i)\r
+ result[i] = vals[i].createOccurrence();\r
+ return result;\r
+ }\r
+ \r
+ public static <T extends IVal> ValRef[] createOccurrences(List<T> vals) {\r
+ ValRef[] result = new ValRef[vals.size()];\r
+ for(int i=0;i<vals.size();++i)\r
+ result[i] = vals.get(i).createOccurrence();\r
+ return result;\r
+ }\r
+ \r
+ public Type[] getTypeParameters() {\r
+ return parameters;\r
+ }\r
+ \r
+ public Type getTypeParameter(int i) {\r
+ return parameters[i];\r
+ }\r
+\r
+ public static ValRef[] concat(ValRef[] refs1, ValRef[] refs2) {\r
+ ValRef[] result = new ValRef[refs1.length + refs2.length];\r
+ for(int i=0;i<refs1.length;++i)\r
+ result[i] = refs1[i];\r
+ for(int i=0;i<refs2.length;++i)\r
+ result[refs1.length + i] = refs2[i];\r
+ return result;\r
+ }\r
+ \r
+ @Override\r
+ public void push(MethodBuilder mb) {\r
+ binding.push(mb);\r
+ }\r
+ \r
+ public ValRefBinder getParent() {\r
+ return parent;\r
+ }\r
+ \r
+ public SSAFunction getParentFunction() {\r
+ return parent.getParentFunction();\r
+ }\r
+ \r
+ public void replace(TVar[] vars, Type[] replacements) {\r
+ for(int i=0;i<parameters.length;++i) {\r
+ Type oldType = parameters[i];\r
+ Type newType = parameters[i].replace(vars, replacements);\r
+ if(oldType != newType) {\r
+ Type[] newParameters = new Type[parameters.length];\r
+ for(int j=0;j<i;++j)\r
+ newParameters[j] = parameters[j];\r
+ newParameters[i] = newType;\r
+ for(int j=i+1;j<parameters.length;++j)\r
+ newParameters[j] = parameters[j].replace(vars, replacements);\r
+ this.parameters = newParameters;\r
+ return;\r
+ }\r
+ \r
+ }\r
+ }\r
+\r
+ public void setTypeParameters(Type[] parameters) {\r
+ this.parameters = parameters;\r
+ }\r
+ \r
+ public static ValRef[] copy(ValRef[] refs) {\r
+ ValRef[] result = new ValRef[refs.length];\r
+ for(int i=0;i<refs.length;++i)\r
+ result[i] = refs[i].copy();\r
+ return result;\r
+ }\r
+\r
+ public ValRef copy() {\r
+ return binding.createOccurrence(parameters);\r
+ }\r
+\r
+ public void collectFreeVariables(SSAFunction function,\r
+ ArrayList<ValRef> vars) {\r
+ if(binding instanceof BoundVar) {\r
+ BoundVar var = (BoundVar)binding;\r
+ if(var.getFunctionParent() != function)\r
+ vars.add(this);\r
+ }\r
+ }\r
+\r
+ public void replaceBy(Val binding) {\r
+ remove();\r
+ setBinding(binding);\r
+ }\r
+ \r
+ @Override\r
+ public Type apply(MethodBuilder mb, Type[] typeParameters,\r
+ Val... parameters) {\r
+ return binding.apply(mb, Types.concat(this.parameters, typeParameters), parameters);\r
+ }\r
+\r
+ /**\r
+ * Replaces this reference with an application\r
+ */\r
+ public void replaceByApply(Val function, Val ... parameters) {\r
+ getParent().replaceByApply(this, function, this.parameters, parameters);\r
+ }\r
+ \r
+ @Override\r
+ public Object realizeValue(TransientClassBuilder classLoader) {\r
+ return binding.realizeValue(classLoader); \r
+ }\r
+\r
+ @Override\r
+ public void setLabel(String label) {\r
+ }\r
+\r
+ public void updateParentEffect() {\r
+ if(parent instanceof LetApply) {\r
+ LetApply apply = (LetApply)parent;\r
+ if(apply.getFunction() == this)\r
+ apply.updateEffect();\r
+ }\r
+ }\r
+}\r