+
+ /**
+ * 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
+ */