]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/statements/LetFunctions.java
Merged changes from feature/scl to master.
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / internal / codegen / ssa / statements / LetFunctions.java
index 25d9c2544bffd4ab6bb8470ead45408e0900d683..ee5dcc7148533bfcaf8a8e44ee7d426b794ce1ca 100644 (file)
@@ -3,57 +3,61 @@ package org.simantics.scl.compiler.internal.codegen.ssa.statements;
 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
@@ -63,52 +67,52 @@ public class LetFunctions extends SSAStatement implements FunctionBinder {
 \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
@@ -132,16 +136,46 @@ public class LetFunctions extends SSAStatement implements FunctionBinder {
         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
@@ -157,40 +191,32 @@ public class LetFunctions extends SSAStatement implements FunctionBinder {
             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
@@ -199,19 +225,19 @@ public class LetFunctions extends SSAStatement implements FunctionBinder {
                     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
@@ -233,7 +259,7 @@ public class LetFunctions extends SSAStatement implements FunctionBinder {
     \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
@@ -242,4 +268,10 @@ public class LetFunctions extends SSAStatement implements FunctionBinder {
     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