import java.util.ArrayList;\r
\r
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;\r
+import org.simantics.scl.compiler.constants.Constant;\r
import org.simantics.scl.compiler.constants.SCLConstant;\r
import org.simantics.scl.compiler.internal.codegen.references.BoundVar;\r
import org.simantics.scl.compiler.internal.codegen.references.ValRef;\r
+import org.simantics.scl.compiler.internal.codegen.ssa.SSAClosure;\r
import org.simantics.scl.compiler.internal.codegen.ssa.SSAFunction;\r
import org.simantics.scl.compiler.internal.codegen.ssa.SSAStatement;\r
-import org.simantics.scl.compiler.internal.codegen.ssa.binders.FunctionBinder;\r
+import org.simantics.scl.compiler.internal.codegen.ssa.binders.ClosureBinder;\r
import org.simantics.scl.compiler.internal.codegen.utils.CopyContext;\r
import org.simantics.scl.compiler.internal.codegen.utils.MethodBuilder;\r
import org.simantics.scl.compiler.internal.codegen.utils.PrintingContext;\r
import org.simantics.scl.compiler.internal.codegen.utils.SSALambdaLiftingContext;\r
import org.simantics.scl.compiler.internal.codegen.utils.SSASimplificationContext;\r
import org.simantics.scl.compiler.internal.codegen.utils.SSAValidationContext;\r
+import org.simantics.scl.compiler.internal.codegen.utils.ValRefVisitor;\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
import gnu.trove.map.hash.THashMap;\r
import gnu.trove.set.hash.THashSet;\r
\r
-public class LetFunctions extends SSAStatement implements FunctionBinder {\r
+public class LetFunctions extends SSAStatement implements ClosureBinder {\r
long recursiveGroupLocation;\r
- SSAFunction firstFunction;\r
+ SSAClosure firstClosure;\r
\r
public LetFunctions() {\r
}\r
\r
- public LetFunctions(SSAFunction function) {\r
- firstFunction = function;\r
- function.setParent(this);\r
+ public LetFunctions(SSAClosure closure) {\r
+ firstClosure = closure;\r
+ closure.setParent(this);\r
}\r
\r
@Override\r
public void toString(PrintingContext context) {\r
- for(SSAFunction function = firstFunction; function != null; function = function.getNext()) {\r
+ for(SSAClosure closure = firstClosure; closure != null; closure = closure.getNext()) {\r
context.indentation();\r
- context.append(function.getTarget());\r
- context.append("(" + function.getTarget().occurrenceCount() + ")");\r
+ context.append(closure.getTarget());\r
+ context.append("(" + closure.getTarget().occurrenceCount() + ")");\r
context.append(" :: ");\r
- context.append(function.getTarget().getType());\r
+ context.append(closure.getTarget().getType());\r
context.append(" = \n");\r
context.indent();\r
- function.toString(context);\r
+ closure.toString(context);\r
context.dedent();\r
}\r
}\r
\r
- public void addFunction(SSAFunction function) {\r
- function.setParent(this); \r
- function.setNext(firstFunction);\r
- if(firstFunction != null)\r
- firstFunction.setPrev(function);\r
- firstFunction = function;\r
+ public void addClosure(SSAClosure closure) {\r
+ closure.setParent(this); \r
+ closure.setNext(firstClosure);\r
+ if(firstClosure != null)\r
+ firstClosure.setPrev(closure);\r
+ firstClosure = closure;\r
}\r
\r
@Override\r
\r
@Override\r
public void validate(SSAValidationContext context) {\r
- for(SSAFunction function = firstFunction; function != null; function = function.getNext()) {\r
- if(!(function.getTarget() instanceof BoundVar))\r
+ for(SSAClosure closure = firstClosure; closure != null; closure = closure.getNext()) {\r
+ if(!(closure.getTarget() instanceof BoundVar))\r
throw new InternalCompilerError();\r
- function.validate(context);\r
+ closure.validate(context);\r
}\r
}\r
\r
@Override\r
public void destroy() {\r
- for(SSAFunction function = firstFunction; function != null; function = function.getNext())\r
- function.destroy();\r
+ for(SSAClosure closure = firstClosure; closure != null; closure = closure.getNext())\r
+ closure.destroy();\r
}\r
\r
@Override\r
public SSAStatement copy(CopyContext context) {\r
LetFunctions result = new LetFunctions();\r
- for(SSAFunction function = firstFunction; function != null; function = function.getNext()) {\r
- SSAFunction newFunction = function.copy(context);\r
- newFunction.setTarget(context.copy(function.getTarget()));\r
- result.addFunction(newFunction);\r
+ for(SSAClosure closure = firstClosure; closure != null; closure = closure.getNext()) {\r
+ SSAClosure newFunction = closure.copy(context);\r
+ newFunction.setTarget(context.copy(closure.getTarget()));\r
+ result.addClosure(newFunction);\r
}\r
return result; \r
}\r
\r
@Override\r
public void replace(TVar[] vars, Type[] replacements) {\r
- for(SSAFunction function = firstFunction; function != null; function = function.getNext()) {\r
- ((BoundVar)function.getTarget()).replace(vars, replacements);\r
- function.replace(vars, replacements);\r
+ for(SSAClosure closure = firstClosure; closure != null; closure = closure.getNext()) {\r
+ ((BoundVar)closure.getTarget()).replace(vars, replacements);\r
+ closure.replace(vars, replacements);\r
}\r
}\r
\r
@Override\r
public void addBoundVariablesTo(SSAValidationContext context) {\r
- for(SSAFunction function = firstFunction; function != null; function = function.getNext())\r
- context.validBoundVariables.add((BoundVar)function.getTarget()); \r
+ for(SSAClosure closure = firstClosure; closure != null; closure = closure.getNext())\r
+ context.validBoundVariables.add((BoundVar)closure.getTarget()); \r
}\r
\r
@Override\r
- public SSAFunction getFirstFunction() {\r
- return firstFunction;\r
+ public SSAClosure getFirstClosure() {\r
+ return firstClosure;\r
}\r
\r
@Override\r
- public void setFirstFunction(SSAFunction function) {\r
- this.firstFunction = function; \r
+ public void setFirstClosure(SSAClosure function) {\r
+ this.firstClosure = function; \r
if(function == null)\r
detach();\r
}\r
boolean hasValues = false;\r
boolean isRecursive = false;\r
\r
- // Lambda lift functions and collect free variables\r
+ // Lambda lift substructure and collect free variables\r
THashSet<BoundVar> targets = new THashSet<BoundVar>();\r
ArrayList<ValRef> freeVars = new ArrayList<ValRef>(); \r
- for(SSAFunction function = firstFunction; \r
- function != null; \r
- function = function.getNext()) {\r
- hasValues |= function.getArity() == 0;\r
- function.lambdaLift(context);\r
- targets.add((BoundVar)function.getTarget());\r
- function.collectFreeVariables(freeVars);\r
+ for(SSAClosure closure = firstClosure; \r
+ closure != null; \r
+ closure = closure.getNext()) {\r
+ hasValues |= closure.isValue();\r
+ closure.lambdaLift(context);\r
+ targets.add((BoundVar)closure.getTarget());\r
+ closure.collectFreeVariables(freeVars);\r
+ }\r
+ \r
+ if(!(firstClosure instanceof SSAFunction) && firstClosure.getNext() == null) {\r
+ THashMap<BoundVar, BoundVar> varMap = new THashMap<BoundVar, BoundVar>(); \r
+ ArrayList<BoundVar> oldVarsList = new ArrayList<BoundVar>(4);\r
+ ArrayList<BoundVar> newVarsList = new ArrayList<BoundVar>(4);\r
+ BoundVar newTarget = null;\r
+ for(ValRef ref : freeVars) {\r
+ BoundVar var = (BoundVar)ref.getBinding();\r
+ if(targets.contains(var)) {\r
+ if(newTarget == null)\r
+ newTarget = new BoundVar(var.getType());\r
+ ref.replaceBy(newTarget);\r
+ continue;\r
+ }\r
+ BoundVar newVar = varMap.get(var);\r
+ if(newVar == null) {\r
+ newVar = new BoundVar(var.getType());\r
+ oldVarsList.add(var);\r
+ newVarsList.add(newVar);\r
+ varMap.put(var, newVar);\r
+ }\r
+ ref.replaceBy(newVar);\r
+ }\r
+ Constant constant = firstClosure.liftClosure(newTarget, newVarsList.toArray(new BoundVar[newVarsList.size()]));\r
+ new LetApply(targets.iterator().next(), Types.PROC, constant.createOccurrence(), ValRef.createOccurrences(oldVarsList))\r
+ .insertBefore(this);\r
+ detach();\r
+ context.addClosure(firstClosure);\r
+ return;\r
}\r
\r
// Classify by BoundVars\r
if(boundVars.add(var))\r
boundVarsList.add(var);\r
newFreeVars.add(ref);\r
- /*BoundVar inVar = map.get(outVar);\r
- if(inVar == null) {\r
- inVar = new BoundVar(outVar.getType());\r
- map.put(outVar, inVar);\r
- outParameters.add(outVar);\r
- inParameters.add(inVar);\r
- }\r
- ref.replaceBy(inVar);*/\r
}\r
BoundVar[] outVars = boundVarsList.toArray(new BoundVar[boundVarsList.size()]);\r
freeVars = newFreeVars;\r
\r
// Modify functions\r
- THashMap<SSAFunction, THashMap<BoundVar, BoundVar>> varMap = new THashMap<SSAFunction, THashMap<BoundVar, BoundVar>>();\r
- THashMap<SSAFunction, BoundVar[]> inVarsMap = new THashMap<SSAFunction, BoundVar[]>();\r
- THashMap<SSAFunction, BoundVar> oldTargets = new THashMap<SSAFunction, BoundVar>();\r
- for(SSAFunction function = firstFunction; \r
- function != null; \r
- function = function.getNext()) {\r
- THashMap<BoundVar, BoundVar> map = new THashMap<BoundVar, BoundVar>(2*outVars.length);\r
+ THashMap<SSAClosure, THashMap<BoundVar, BoundVar>> varMap = new THashMap<SSAClosure, THashMap<BoundVar, BoundVar>>();\r
+ THashMap<SSAClosure, BoundVar[]> inVarsMap = new THashMap<SSAClosure, BoundVar[]>();\r
+ THashMap<SSAClosure, BoundVar> oldTargets = new THashMap<SSAClosure, BoundVar>();\r
+ for(SSAClosure closure = firstClosure; \r
+ closure != null; \r
+ closure = closure.getNext()) {\r
+ THashMap<BoundVar, BoundVar> map = new THashMap<BoundVar, BoundVar>(outVars.length);\r
BoundVar[] inVars = new BoundVar[outVars.length]; \r
for(int i=0;i<inVars.length;++i) {\r
inVars[i] = new BoundVar(outVars[i].getType());\r
map.put(outVars[i], inVars[i]);\r
}\r
- inVarsMap.put(function, inVars);\r
- varMap.put(function, map);\r
+ inVarsMap.put(closure, inVars);\r
+ varMap.put(closure, map);\r
\r
- function.addParametersInFront(inVars); \r
- SCLConstant functionConstant = new SCLConstant(context.createName(), function.getType());\r
+ closure.parametrize(inVars); \r
+ SCLConstant functionConstant = new SCLConstant(context.createName(), closure.getType());\r
context.addConstant(functionConstant); \r
- oldTargets.put(function, (BoundVar)function.getTarget());\r
- function.setTarget(functionConstant);\r
- functionConstant.setDefinition(function); \r
+ oldTargets.put(closure, (BoundVar)closure.getTarget());\r
+ closure.setTarget(functionConstant);\r
+ functionConstant.setDefinition((SSAFunction)closure); \r
functionConstant.setPrivate(true);\r
// TODO handle type parameters\r
\r
ValRef.createOccurrences(outVars)).insertBefore(this);*/\r
}\r
\r
- for(SSAFunction function = firstFunction; \r
- function != null; \r
- function = function.getNext()) {\r
- BoundVar oldTarget = oldTargets.get(function);\r
+ for(SSAClosure closure = firstClosure; \r
+ closure != null; \r
+ closure = closure.getNext()) {\r
+ BoundVar oldTarget = oldTargets.get(closure);\r
for(ValRef ref : oldTarget.getOccurences()) {\r
SSAFunction parent = ref.getParentFunction();\r
BoundVar[] vars = inVarsMap.get(parent);\r
if(vars == null)\r
vars = outVars;\r
if(vars.length > 0)\r
- ref.replaceByApply(function.getTarget(), vars);\r
+ ref.replaceByApply(closure.getTarget(), vars);\r
else\r
- ref.replaceBy(function.getTarget());\r
+ ref.replaceBy(closure.getTarget());\r
}\r
}\r
\r
\r
@Override\r
public void simplify(SSASimplificationContext context) {\r
- for(SSAFunction function = firstFunction; \r
+ for(SSAClosure function = firstClosure; \r
function != null; \r
function = function.getNext())\r
function.simplify(context);\r
public void setRecursiveGroupLocation(long recursiveGroupLocation) {\r
this.recursiveGroupLocation = recursiveGroupLocation;\r
}\r
+ \r
+ @Override\r
+ public void forValRefs(ValRefVisitor visitor) {\r
+ for(SSAClosure closure = firstClosure; closure != null; closure = closure.getNext())\r
+ closure.forValRefs(visitor); \r
+ }\r
}\r