import org.cojen.classfile.TypeDesc;
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
+import org.simantics.scl.compiler.constants.NoRepConstant;
import org.simantics.scl.compiler.internal.codegen.continuations.Cont;
import org.simantics.scl.compiler.internal.codegen.continuations.ContRef;
import org.simantics.scl.compiler.internal.codegen.continuations.ReturnCont;
public void simplify(SSASimplificationContext context) {
for(SSABlock block = firstBlock; block != null; block = block.next)
block.simplify(context);
- if(firstBlock == lastBlock && firstBlock.firstStatement == firstBlock.lastStatement &&
- firstBlock.firstStatement instanceof LetFunctions) {
- simplifySingleLambda(context);
+ if(firstBlock == lastBlock && firstBlock.firstStatement == firstBlock.lastStatement) {
+ if(firstBlock.firstStatement instanceof LetApply)
+ simplifySingleApply(context);
+ else if(firstBlock.firstStatement instanceof LetFunctions)
+ simplifySingleLambda(context);
}
}
+
+ /**
+ * Simplifies the following kind of function definition
+ * \x -> f x
+ * to
+ * f
+ */
+ private void simplifySingleApply(SSASimplificationContext context) {
+ if(!(parent instanceof LetFunctions) || parent.getFirstClosure().next != null)
+ return;
+ LetApply apply = (LetApply)firstBlock.firstStatement;
+ if(!(firstBlock.exit instanceof Jump))
+ return;
+ Jump exit = (Jump)firstBlock.exit;
+ if(exit.getTarget().getBinding() != returnCont)
+ return;
+ if(exit.getParameter(0).getBinding() != apply.getTarget())
+ return;
+ BoundVar[] functionParameters = getParameters();
+ ValRef[] applyParameters = apply.getParameters();
+ if(functionParameters.length > applyParameters.length)
+ return;
+ int extraApplyParameters = applyParameters.length - functionParameters.length;
+ for(int i=0;i<functionParameters.length;++i)
+ if(!representSameValues(functionParameters[i], applyParameters[extraApplyParameters+i]))
+ return;
+ for(int i=0;i<extraApplyParameters;++i) {
+ Val b = applyParameters[i].getBinding();
+ if(b instanceof BoundVar) {
+ BoundVar bv = (BoundVar)b;
+ if(bv == target || bv.getParent() == firstBlock)
+ return;
+ }
+ }
+ if(!(target instanceof BoundVar))
+ return;
+
+ // Transform
+
+ LetFunctions binder = (LetFunctions)parent;
+ SSAFunction parentFunction = binder.getParentFunction();
+ if(extraApplyParameters > 0) {
+ //System.out.println("-------------------------------------------------------------");
+ //System.out.println(parentFunction);
+ //System.out.println("-------------------------------------------------------------");
+ apply.setTarget((BoundVar)target);
+ apply.setParameters(Arrays.copyOf(applyParameters, extraApplyParameters));
+ apply.insertBefore(binder);
+ binder.detach();
+ //System.out.println(parentFunction);
+ //System.out.println("-------------------------------------------------------------");
+ }
+ else {
+ binder.detach();
+ ((BoundVar)target).replaceBy(apply.getFunction());
+ }
+ context.markModified("SSAFunction.eta-reduce");
+ }
+
+ private boolean representSameValues(BoundVar boundVar, ValRef valRef) {
+ Val val = valRef.getBinding();
+ if(val == boundVar && valRef.getTypeParameters().length == 0)
+ return true;
+ if(val instanceof NoRepConstant && Types.equals(valRef.getType(), boundVar.getType()))
+ return true;
+ return false;
+ }
+
+ /**
+ * Simplifies the following kind of function definition
+ * \x -> \y -> e
+ * to
+ * \x y -> e
+ */
private void simplifySingleLambda(SSASimplificationContext context) {
LetFunctions letF = (LetFunctions)firstBlock.firstStatement;
if(!(letF.getFirstClosure() instanceof SSAFunction))
lastBlock = f.lastBlock;
firstBlock.firstStatement = firstBlock.lastStatement = null;
- setReturnCont(f.getReturnCont());
+ setReturnCont(f.getReturnCont());
effect = f.effect;
BoundVar[] newParameters = BoundVar.copy(f.firstBlock.parameters);
firstBlock.setParameters(BoundVar.concat(getParameters(), newParameters));
import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
import org.simantics.scl.compiler.constants.BooleanConstant;
import org.simantics.scl.compiler.constants.IntegerConstant;
+import org.simantics.scl.compiler.constants.NoRepConstant;
import org.simantics.scl.compiler.internal.codegen.continuations.BranchRef;
import org.simantics.scl.compiler.internal.codegen.continuations.Cont;
import org.simantics.scl.compiler.internal.codegen.continuations.ContRef;
context.markModified("switch-to-if");
newExit.simplify(context);
}
- else if(branches.length == 1 && branches[0].constructor == null) {
+ else if(branches.length == 1 && isConstructorParameterless(branches[0])) {
scrutinee.remove();
getParent().setExit(new Jump(branches[0].cont));
}
}
+
+ private static boolean isConstructorParameterless(BranchRef branch) {
+ return branch.constructor == null || branch.constructor instanceof NoRepConstant;
+ }
@Override
public void collectFreeVariables(SSAFunction function,