]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/SCLConstant.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.scl.compiler / src / org / simantics / scl / compiler / constants / SCLConstant.java
index ce39a6780e4ba8920360ca15a241d6ad543f54fa..14bcbcaf65e84e645e99948b02c80a508033ef83 100644 (file)
-package org.simantics.scl.compiler.constants;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Arrays;\r
-\r
-import org.simantics.scl.compiler.common.names.Name;\r
-import org.simantics.scl.compiler.common.names.Named;\r
-import org.simantics.scl.compiler.internal.codegen.optimization.Optimization;\r
-import org.simantics.scl.compiler.internal.codegen.optimization.OptimizationMap;\r
-import org.simantics.scl.compiler.internal.codegen.references.BoundVar;\r
-import org.simantics.scl.compiler.internal.codegen.references.Val;\r
-import org.simantics.scl.compiler.internal.codegen.references.ValRef;\r
-import org.simantics.scl.compiler.internal.codegen.ssa.SSABlock;\r
-import org.simantics.scl.compiler.internal.codegen.ssa.SSAFunction;\r
-import org.simantics.scl.compiler.internal.codegen.ssa.exits.Jump;\r
-import org.simantics.scl.compiler.internal.codegen.ssa.statements.LetApply;\r
-import org.simantics.scl.compiler.internal.codegen.ssa.statements.LetFunctions;\r
-import org.simantics.scl.compiler.internal.codegen.utils.SSASimplificationContext;\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 class SCLConstant extends DelegateConstant implements Named {\r
-\r
-    public Name name; // Needed only for debugging\r
-    public SSAFunction definition;\r
-    public SSAFunction inlinableDefinition;\r
-    public int inlineArity = Integer.MAX_VALUE;\r
-    public int inlinePhaseMask = 0xffffffff;\r
-    public boolean isPrivate = false;    \r
-    \r
-    public SCLConstant(Name name, Type type) {\r
-        super(type);\r
-        this.name = name;\r
-    }\r
-    \r
-    public void setInlineArity(int inlineArity, int inlinePhaseMask) {\r
-        this.inlineArity = inlineArity;\r
-        this.inlinePhaseMask = inlinePhaseMask;\r
-        //System.out.println(name + " " + inlineArity + " " + inlinePhaseMask);\r
-    }\r
-    \r
-    public void setPrivate(boolean isPrivate) {\r
-        this.isPrivate = isPrivate;\r
-    }\r
-    \r
-    public void setDefinition(SSAFunction definition) {\r
-        this.definition = definition;\r
-    }\r
-    \r
-    public SSAFunction getDefinition() {\r
-        return definition;\r
-    }\r
-\r
-    @Override\r
-    public void inline(SSASimplificationContext context, LetApply apply) {\r
-        if(inlineTailCallToSelf(context, apply)) {\r
-            return;\r
-        }\r
-        /*if(tryBetaReduce(context, apply)) {\r
-            return;\r
-        }*/\r
-        if(basicInline(context, apply)) {\r
-            return;\r
-        }\r
-        trySpecialize(context, apply);\r
-        \r
-        Optimization opt = OptimizationMap.OPTIMIZATIONS.get(name);\r
-        if(opt != null)\r
-            opt.inline(context, apply);\r
-    }\r
-\r
-    static int inlineCount = 0;\r
-    \r
-    private boolean canInlineInPhase(int phase) {\r
-        return ((inlinePhaseMask >> phase)&1) == 1;\r
-    }\r
-    \r
-    private boolean basicInline(SSASimplificationContext context, LetApply apply) {\r
-        if(!canInlineInPhase(context.getPhase())) {\r
-            //System.out.println("Cannot optimize " + name + " in phase " + context.getPhase());\r
-            return false;\r
-        }\r
-        ValRef functionRef = apply.getFunction();\r
-        ValRef[] parameters = apply.getParameters();\r
-        SSAFunction def = inlinableDefinition == null ? definition : inlinableDefinition;\r
-        if(parameters.length < inlineArity &&\r
-                (!isPrivate \r
-                        || parameters.length != def.getArity() \r
-                        || hasMoreThanOneOccurences()))\r
-            return false;\r
-        \r
-        //if(def.getArity() == 0)\r
-        //    return false; // FIXME\r
-        \r
-        //System.out.println("basicInline: " + apply);\r
-        //System.out.println("def: " + def);\r
-        \r
-        if(isPrivate && !hasMoreThanOneOccurences())\r
-            context.removeConstant(name);\r
-        else\r
-            def = (SSAFunction)def.copy();\r
-        \r
-        if(parameters.length >= def.getArity()) {\r
-            if(parameters.length != def.getArity())\r
-                apply.split(def.getArity());\r
-            apply.inline(def);\r
-            context.markModified("SCLConstant.beta-constant " + getName());\r
-        }\r
-        else /*if(parameters.length < def.getArity())*/ {\r
-            def.applyTypes(functionRef.getTypeParameters());\r
-            def.apply(parameters);\r
-                        \r
-            def.setTarget(apply.getTarget());\r
-            new LetFunctions(def).insertBefore(apply);\r
-\r
-            apply.remove();\r
-            context.markModified("SCLConstant.partial-beta-constant " + getName());\r
-        }\r
-                        \r
-        /*Name newName = Name.create(name.module,\r
-                name.name + "_S" + (++inlineCount));\r
-        SCLConstant newConstant = new SCLConstant(newName, type);\r
-        newConstant.setPrivate(true);\r
-        newConstant.setDefinition(definition.copy());    */    \r
-        /*System.out.println("*** 1 *************************************");\r
-        System.out.println(definition);\r
-        System.out.println("*** 2 *************************************");\r
-        System.out.println(newConstant.definition);\r
-        \r
-        function.remove();\r
-        apply.setFunction(newConstant.createOccurrence(function.getTypeParameters()));\r
-        \r
-        context.addConstant(newConstant);\r
-        \r
-        context.markModified();\r
-        \r
-        newConstant.trySpecialize(context, apply);\r
-        */\r
-        \r
-        return true;\r
-    }\r
-\r
-    private boolean inlineTailCallToSelf(SSASimplificationContext context, LetApply apply) {\r
-        SSAFunction thisFunction = apply.getParent().getParent();\r
-        if(thisFunction != definition)\r
-            return false;\r
-        ValRef ref = apply.getTarget().getOccurrence();\r
-        if(ref == null || ref.getNext() != null)\r
-            return false;\r
-        if(!(ref.getParent() instanceof Jump))\r
-            return false;\r
-        Jump jump = (Jump)ref.getParent();\r
-        if(jump.getParameters().length != 1)\r
-            return false;\r
-        if(jump.getTarget().getBinding() != thisFunction.getReturnCont())\r
-            return false;\r
-        if(apply.getParameters().length != thisFunction.getArity())\r
-            return false;\r
-        \r
-        jump.getTarget().remove();\r
-        jump.setTarget(thisFunction.getFirstBlock().createOccurrence());\r
-        jump.setParameters(apply.getParameters());\r
-        \r
-        apply.getFunction().remove();\r
-        apply.detach();\r
-        \r
-        context.markModified("SCLConstant.simplify-tail-call");\r
-        \r
-        return true;\r
-    }\r
-\r
-    private void trySpecialize(SSASimplificationContext context, LetApply apply) {\r
-        if(!isPrivate)\r
-            return;\r
-        if(hasMoreThanOneOccurences())\r
-            return;\r
-        if(apply.getParent().getParent() == definition)\r
-            return;\r
-\r
-        // Specialization of type parameters\r
-        {\r
-            ValRef functionRef = apply.getFunction();\r
-            Type[] pValues = functionRef.getTypeParameters();   \r
-            boolean hasComplexTypes = false;\r
-            for(Type type : pValues)\r
-                if(!(Types.canonical(type) instanceof TVar)) {\r
-                    hasComplexTypes = true;\r
-                    break;\r
-                }\r
-            if(hasComplexTypes) {                \r
-                /*PrintingContext pc = new PrintingContext();\r
-                pc.append(">> BEFORE >>\n");\r
-                definition.toString(pc);*/   \r
-                \r
-                TVar[] pVars = definition.getTypeParameters();\r
-                TVar[] pVarsTail;\r
-                if(pVars.length == pValues.length)\r
-                    pVarsTail = TVar.EMPTY_ARRAY;\r
-                else {\r
-                    pVarsTail = Arrays.copyOfRange(pVars, pValues.length, pVars.length);\r
-                    pVars = Arrays.copyOf(pVars, pValues.length);\r
-                }\r
-                type = Types.instantiate(type, pValues);\r
-                /*pc.append("REPLACE: ");\r
-                pc.append(pVars);\r
-                pc.append(" -> ");\r
-                pc.append(pValues);\r
-                pc.append('\n');*/\r
-                definition.replace(pVars, pValues);\r
-                TVar[] newParameters = Types.freeVarsArray(pValues);\r
-                type = Types.forAll(newParameters, type);\r
-                functionRef.setTypeParameters(newParameters);\r
-                definition.setTypeParameters(Types.concat(newParameters, pVarsTail));               \r
-                \r
-                /*pc.append(">> AFTER >>\n");\r
-                definition.toString(pc);\r
-                System.out.println(pc);*/\r
-                context.markModified("SCLConstant.specialize-types");\r
-            }\r
-        }\r
-        \r
-        if(!definition.getFirstBlock().hasNoOccurences())\r
-            // TODO We can flex this requirement if all jumps to the first block\r
-            //      give same values to the first block\r
-            return;\r
-        \r
-        // Specialization of parameters\r
-        ValRef[] parameters = apply.getParameters();\r
-        ValRef[] specialization = null;\r
-        int arity = Math.min(parameters.length, definition.getArity());\r
-        for(int i=0;i<arity;++i) {\r
-            Val val = parameters[i].getBinding();\r
-            if(val instanceof Constant) {\r
-                if(specialization == null)\r
-                    specialization = new ValRef[arity];\r
-                specialization[i] = parameters[i];\r
-            }\r
-        }\r
-        \r
-        if(specialization != null)\r
-            specialize(context, apply, specialization);\r
-    }\r
-\r
-    private void specialize(SSASimplificationContext context, LetApply apply,\r
-            ValRef[] specialization) {\r
-        /*System.out.println("=== SPECIALIZE ====================");\r
-        System.out.println(apply);\r
-        System.out.println("--------");\r
-        System.out.println(definition);\r
-        System.out.println("========");*/\r
-        // *** Modify apply *******************************        \r
-        {\r
-            // Handle old parameters\r
-            ValRef[] oldParameters = apply.getParameters();\r
-            int newParameterCount = oldParameters.length - specialization.length;\r
-            for(int i=0;i<specialization.length;++i)\r
-                if(specialization[i] == null)\r
-                    ++newParameterCount;            \r
-\r
-            if(newParameterCount == 0) {\r
-                // If apply would be degenerated, remove it\r
-                apply.getTarget().replaceBy(apply.getFunction());\r
-                apply.remove();\r
-            }            \r
-            else {\r
-                // Create new parameter array\r
-                ValRef[] newParameters = new ValRef[newParameterCount];\r
-                int k=0;\r
-                for(int i=0;i<specialization.length;++i)\r
-                    if(specialization[i] == null)\r
-                        newParameters[k++] = oldParameters[i];\r
-                    else\r
-                        oldParameters[i].remove();                        \r
-                for(int i=specialization.length;i<oldParameters.length;++i)\r
-                    newParameters[k++] = oldParameters[i];\r
-                        \r
-                apply.setParameters(newParameters);\r
-            }\r
-        }\r
-        \r
-        // *** Modify definition **************************        \r
-        {\r
-            SSABlock firstBlock = definition.getFirstBlock();\r
-            BoundVar[] parameters = firstBlock.getParameters();\r
-            ArrayList<BoundVar> newParameters = new ArrayList<BoundVar>(parameters.length); \r
-            for(int i=0;i<specialization.length;++i)\r
-                if(specialization[i] != null)\r
-                    parameters[i].replaceBy(specialization[i]);\r
-                else\r
-                    newParameters.add(parameters[i]);\r
-            for(int i=specialization.length;i<parameters.length;++i)\r
-                newParameters.add(parameters[i]);\r
-            firstBlock.setParameters(newParameters.toArray(new BoundVar[newParameters.size()]));\r
-            \r
-            type = definition.getType();\r
-        }\r
-        \r
-        /*System.out.println(apply);\r
-        System.out.println("--------");\r
-        System.out.println(definition);*/\r
-        context.markModified("SCLConstant.specialize");  \r
-    }\r
-\r
-    @Override\r
-    public String toString() {\r
-        char c = name.name.charAt(0);\r
-        if(Character.isJavaIdentifierStart(c) || name.name.charAt(0) == '(' || c == '[')\r
-            return name.name;\r
-        else\r
-            return "(" + name.name + ")";\r
-    }\r
-\r
-    @Override\r
-    public Name getName() {\r
-        return name;\r
-    }\r
-\r
-    public Constant getBase() {\r
-        return base;\r
-    }\r
-    \r
-    public boolean isPrivate() {\r
-        return isPrivate;\r
-    }\r
-\r
-    private boolean simplifyConstantFunction(SSASimplificationContext context) {\r
-        ValRef constant = definition.isEqualToConstant();\r
-        if(constant == null)\r
-            return false;\r
-        Val binding = constant.getBinding();\r
-        if(binding == this)\r
-            return false;\r
-        if(binding instanceof Constant) {\r
-            /*System.out.println(name + " -> " + constant.getBinding());\r
-            System.out.println("replace: " + this);\r
-            System.out.println("of type: " + this.getType());\r
-            System.out.println("by: " + binding);\r
-            System.out.println("of type: " + binding.getType());\r
-            System.out.println("parameters: " + Types.toString(definition.getTypeParameters()));\r
-            System.out.println("parameters2: " + Types.toString(constant.getTypeParameters()));\r
-            System.out.println("private: " + isPrivate);*/            \r
-            replaceBy(binding,\r
-                    definition.getTypeParameters(), \r
-                    constant.getTypeParameters());                \r
-            if(isPrivate) {\r
-                definition.destroy();\r
-                context.removeConstant(name);\r
-            }\r
-            context.markModified("SCLConstant.simplify-constant");\r
-            return true;\r
-        }\r
-        return false;\r
-    }\r
-    \r
-    public void simplify(SSASimplificationContext context) {\r
-        if(!hasNoOccurences() /* TODO why this condition is needed? */) {\r
-            if(simplifyConstantFunction(context))\r
-                return;\r
-        }\r
-        /*if(isPrivate)\r
-            definition.tryToMakeMonadic(context);*/\r
-        definition.simplify(context);\r
-        if(inlineArity == Integer.MAX_VALUE && definition.isSimpleEnoughForInline()) {\r
-            inlineArity = definition.getArity();\r
-            inlinableDefinition = (SSAFunction)definition.copy();\r
-            context.markModified("mark inlineable " + name);\r
-            // FIXME this will make self calling function inlinable that may crash the compiler\r
-        }\r
-    }\r
-\r
-    public void saveInlinableDefinition() {\r
-        if(inlineArity < Integer.MAX_VALUE)\r
-            inlinableDefinition = (SSAFunction)definition.copy();\r
-    }\r
-}\r
+package org.simantics.scl.compiler.constants;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import org.simantics.scl.compiler.common.names.Name;
+import org.simantics.scl.compiler.common.names.Named;
+import org.simantics.scl.compiler.internal.codegen.optimization.Optimization;
+import org.simantics.scl.compiler.internal.codegen.optimization.OptimizationMap;
+import org.simantics.scl.compiler.internal.codegen.references.BoundVar;
+import org.simantics.scl.compiler.internal.codegen.references.Val;
+import org.simantics.scl.compiler.internal.codegen.references.ValRef;
+import org.simantics.scl.compiler.internal.codegen.ssa.SSABlock;
+import org.simantics.scl.compiler.internal.codegen.ssa.SSAFunction;
+import org.simantics.scl.compiler.internal.codegen.ssa.exits.Jump;
+import org.simantics.scl.compiler.internal.codegen.ssa.statements.LetApply;
+import org.simantics.scl.compiler.internal.codegen.ssa.statements.LetFunctions;
+import org.simantics.scl.compiler.internal.codegen.utils.SSASimplificationContext;
+import org.simantics.scl.compiler.types.TVar;
+import org.simantics.scl.compiler.types.Type;
+import org.simantics.scl.compiler.types.Types;
+
+public class SCLConstant extends DelegateConstant implements Named {
+
+    public Name name; // Needed only for debugging
+    public SSAFunction definition;
+    public SSAFunction inlinableDefinition;
+    public int inlineArity = Integer.MAX_VALUE;
+    public int inlinePhaseMask = 0xffffffff;
+    public boolean isPrivate = false;    
+    
+    public SCLConstant(Name name, Type type) {
+        super(type);
+        this.name = name;
+    }
+    
+    public void setInlineArity(int inlineArity, int inlinePhaseMask) {
+        this.inlineArity = inlineArity;
+        this.inlinePhaseMask = inlinePhaseMask;
+        //System.out.println(name + " " + inlineArity + " " + inlinePhaseMask);
+    }
+    
+    public void setPrivate(boolean isPrivate) {
+        this.isPrivate = isPrivate;
+    }
+    
+    public void setDefinition(SSAFunction definition) {
+        this.definition = definition;
+    }
+    
+    public SSAFunction getDefinition() {
+        return definition;
+    }
+
+    @Override
+    public void inline(SSASimplificationContext context, LetApply apply) {
+        if(inlineTailCallToSelf(context, apply)) {
+            return;
+        }
+        /*if(tryBetaReduce(context, apply)) {
+            return;
+        }*/
+        if(basicInline(context, apply)) {
+            return;
+        }
+        trySpecialize(context, apply);
+        
+        Optimization opt = OptimizationMap.OPTIMIZATIONS.get(name);
+        if(opt != null)
+            opt.inline(context, apply);
+    }
+
+    static int inlineCount = 0;
+    
+    private boolean canInlineInPhase(int phase) {
+        return ((inlinePhaseMask >> phase)&1) == 1;
+    }
+    
+    private boolean basicInline(SSASimplificationContext context, LetApply apply) {
+        if(!canInlineInPhase(context.getPhase())) {
+            //System.out.println("Cannot optimize " + name + " in phase " + context.getPhase());
+            return false;
+        }
+        ValRef functionRef = apply.getFunction();
+        ValRef[] parameters = apply.getParameters();
+        SSAFunction def = inlinableDefinition == null ? definition : inlinableDefinition;
+        if(parameters.length < inlineArity &&
+                (!isPrivate 
+                        || parameters.length != def.getArity() 
+                        || hasMoreThanOneOccurences()))
+            return false;
+        
+        //if(def.getArity() == 0)
+        //    return false; // FIXME
+        
+        //System.out.println("basicInline: " + apply);
+        //System.out.println("def: " + def);
+        
+        if(isPrivate && !hasMoreThanOneOccurences())
+            context.removeConstant(name);
+        else
+            def = (SSAFunction)def.copy();
+        
+        if(parameters.length >= def.getArity()) {
+            if(parameters.length != def.getArity())
+                apply.split(def.getArity());
+            apply.inline(def);
+            context.markModified("SCLConstant.beta-constant " + getName());
+        }
+        else /*if(parameters.length < def.getArity())*/ {
+            def.applyTypes(functionRef.getTypeParameters());
+            def.apply(parameters);
+                        
+            def.setTarget(apply.getTarget());
+            new LetFunctions(def).insertBefore(apply);
+
+            apply.remove();
+            context.markModified("SCLConstant.partial-beta-constant " + getName());
+        }
+                        
+        /*Name newName = Name.create(name.module,
+                name.name + "_S" + (++inlineCount));
+        SCLConstant newConstant = new SCLConstant(newName, type);
+        newConstant.setPrivate(true);
+        newConstant.setDefinition(definition.copy());    */    
+        /*System.out.println("*** 1 *************************************");
+        System.out.println(definition);
+        System.out.println("*** 2 *************************************");
+        System.out.println(newConstant.definition);
+        
+        function.remove();
+        apply.setFunction(newConstant.createOccurrence(function.getTypeParameters()));
+        
+        context.addConstant(newConstant);
+        
+        context.markModified();
+        
+        newConstant.trySpecialize(context, apply);
+        */
+        
+        return true;
+    }
+
+    private boolean inlineTailCallToSelf(SSASimplificationContext context, LetApply apply) {
+        SSAFunction thisFunction = apply.getParent().getParent();
+        if(thisFunction != definition)
+            return false;
+        ValRef ref = apply.getTarget().getOccurrence();
+        if(ref == null || ref.getNext() != null)
+            return false;
+        if(!(ref.getParent() instanceof Jump))
+            return false;
+        Jump jump = (Jump)ref.getParent();
+        if(jump.getParameters().length != 1)
+            return false;
+        if(jump.getTarget().getBinding() != thisFunction.getReturnCont())
+            return false;
+        if(apply.getParameters().length != thisFunction.getArity())
+            return false;
+        
+        jump.getTarget().remove();
+        jump.setTarget(thisFunction.getFirstBlock().createOccurrence());
+        jump.setParameters(apply.getParameters());
+        
+        apply.getFunction().remove();
+        apply.detach();
+        
+        context.markModified("SCLConstant.simplify-tail-call");
+        
+        return true;
+    }
+
+    private void trySpecialize(SSASimplificationContext context, LetApply apply) {
+        if(!isPrivate)
+            return;
+        if(hasMoreThanOneOccurences())
+            return;
+        if(apply.getParent().getParent() == definition)
+            return;
+
+        // Specialization of type parameters
+        {
+            ValRef functionRef = apply.getFunction();
+            Type[] pValues = functionRef.getTypeParameters();   
+            boolean hasComplexTypes = false;
+            for(Type type : pValues)
+                if(!(Types.canonical(type) instanceof TVar)) {
+                    hasComplexTypes = true;
+                    break;
+                }
+            if(hasComplexTypes) {                
+                /*PrintingContext pc = new PrintingContext();
+                pc.append(">> BEFORE >>\n");
+                definition.toString(pc);*/   
+                
+                TVar[] pVars = definition.getTypeParameters();
+                TVar[] pVarsTail;
+                if(pVars.length == pValues.length)
+                    pVarsTail = TVar.EMPTY_ARRAY;
+                else {
+                    pVarsTail = Arrays.copyOfRange(pVars, pValues.length, pVars.length);
+                    pVars = Arrays.copyOf(pVars, pValues.length);
+                }
+                type = Types.instantiate(type, pValues);
+                /*pc.append("REPLACE: ");
+                pc.append(pVars);
+                pc.append(" -> ");
+                pc.append(pValues);
+                pc.append('\n');*/
+                definition.replace(pVars, pValues);
+                TVar[] newParameters = Types.freeVarsArray(pValues);
+                type = Types.forAll(newParameters, type);
+                functionRef.setTypeParameters(newParameters);
+                definition.setTypeParameters(Types.concat(newParameters, pVarsTail));               
+                
+                /*pc.append(">> AFTER >>\n");
+                definition.toString(pc);
+                System.out.println(pc);*/
+                context.markModified("SCLConstant.specialize-types");
+            }
+        }
+        
+        if(!definition.getFirstBlock().hasNoOccurences())
+            // TODO We can flex this requirement if all jumps to the first block
+            //      give same values to the first block
+            return;
+        
+        // Specialization of parameters
+        ValRef[] parameters = apply.getParameters();
+        ValRef[] specialization = null;
+        int arity = Math.min(parameters.length, definition.getArity());
+        for(int i=0;i<arity;++i) {
+            Val val = parameters[i].getBinding();
+            if(val instanceof Constant) {
+                if(specialization == null)
+                    specialization = new ValRef[arity];
+                specialization[i] = parameters[i];
+            }
+        }
+        
+        if(specialization != null)
+            specialize(context, apply, specialization);
+    }
+
+    private void specialize(SSASimplificationContext context, LetApply apply,
+            ValRef[] specialization) {
+        /*System.out.println("=== SPECIALIZE ====================");
+        System.out.println(apply);
+        System.out.println("--------");
+        System.out.println(definition);
+        System.out.println("========");*/
+        // *** Modify apply *******************************        
+        {
+            // Handle old parameters
+            ValRef[] oldParameters = apply.getParameters();
+            int newParameterCount = oldParameters.length - specialization.length;
+            for(int i=0;i<specialization.length;++i)
+                if(specialization[i] == null)
+                    ++newParameterCount;            
+
+            if(newParameterCount == 0) {
+                // If apply would be degenerated, remove it
+                apply.getTarget().replaceBy(apply.getFunction());
+                apply.remove();
+            }            
+            else {
+                // Create new parameter array
+                ValRef[] newParameters = new ValRef[newParameterCount];
+                int k=0;
+                for(int i=0;i<specialization.length;++i)
+                    if(specialization[i] == null)
+                        newParameters[k++] = oldParameters[i];
+                    else
+                        oldParameters[i].remove();                        
+                for(int i=specialization.length;i<oldParameters.length;++i)
+                    newParameters[k++] = oldParameters[i];
+                        
+                apply.setParameters(newParameters);
+            }
+        }
+        
+        // *** Modify definition **************************        
+        {
+            SSABlock firstBlock = definition.getFirstBlock();
+            BoundVar[] parameters = firstBlock.getParameters();
+            ArrayList<BoundVar> newParameters = new ArrayList<BoundVar>(parameters.length); 
+            for(int i=0;i<specialization.length;++i)
+                if(specialization[i] != null)
+                    parameters[i].replaceBy(specialization[i]);
+                else
+                    newParameters.add(parameters[i]);
+            for(int i=specialization.length;i<parameters.length;++i)
+                newParameters.add(parameters[i]);
+            firstBlock.setParameters(newParameters.toArray(new BoundVar[newParameters.size()]));
+            
+            type = definition.getType();
+        }
+        
+        /*System.out.println(apply);
+        System.out.println("--------");
+        System.out.println(definition);*/
+        context.markModified("SCLConstant.specialize");  
+    }
+
+    @Override
+    public String toString() {
+        char c = name.name.charAt(0);
+        if(Character.isJavaIdentifierStart(c) || name.name.charAt(0) == '(' || c == '[')
+            return name.name;
+        else
+            return "(" + name.name + ")";
+    }
+
+    @Override
+    public Name getName() {
+        return name;
+    }
+
+    public Constant getBase() {
+        return base;
+    }
+    
+    public boolean isPrivate() {
+        return isPrivate;
+    }
+
+    private boolean simplifyConstantFunction(SSASimplificationContext context) {
+        ValRef constant = definition.isEqualToConstant();
+        if(constant == null)
+            return false;
+        Val binding = constant.getBinding();
+        if(binding == this)
+            return false;
+        if(binding instanceof Constant) {
+            /*System.out.println(name + " -> " + constant.getBinding());
+            System.out.println("replace: " + this);
+            System.out.println("of type: " + this.getType());
+            System.out.println("by: " + binding);
+            System.out.println("of type: " + binding.getType());
+            System.out.println("parameters: " + Types.toString(definition.getTypeParameters()));
+            System.out.println("parameters2: " + Types.toString(constant.getTypeParameters()));
+            System.out.println("private: " + isPrivate);*/            
+            replaceBy(binding,
+                    definition.getTypeParameters(), 
+                    constant.getTypeParameters());                
+            if(isPrivate) {
+                definition.destroy();
+                context.removeConstant(name);
+            }
+            context.markModified("SCLConstant.simplify-constant");
+            return true;
+        }
+        return false;
+    }
+    
+    public void simplify(SSASimplificationContext context) {
+        if(!hasNoOccurences() /* TODO why this condition is needed? */) {
+            if(simplifyConstantFunction(context))
+                return;
+        }
+        /*if(isPrivate)
+            definition.tryToMakeMonadic(context);*/
+        definition.simplify(context);
+        if(inlineArity == Integer.MAX_VALUE && definition.isSimpleEnoughForInline()) {
+            inlineArity = definition.getArity();
+            inlinableDefinition = (SSAFunction)definition.copy();
+            context.markModified("mark inlineable " + name);
+            // FIXME this will make self calling function inlinable that may crash the compiler
+        }
+    }
+
+    public void saveInlinableDefinition() {
+        if(inlineArity < Integer.MAX_VALUE)
+            inlinableDefinition = (SSAFunction)definition.copy();
+    }
+}