package de.skuzzle.polly.core.parser.ast.lang.functions;
import java.util.Arrays;
import de.skuzzle.polly.core.parser.Position;
import de.skuzzle.polly.core.parser.ast.declarations.Namespace;
import de.skuzzle.polly.core.parser.ast.declarations.types.ProductType;
import de.skuzzle.polly.core.parser.ast.declarations.types.Type;
import de.skuzzle.polly.core.parser.ast.declarations.types.TypeVar;
import de.skuzzle.polly.core.parser.ast.expressions.Call;
import de.skuzzle.polly.core.parser.ast.expressions.Expression;
import de.skuzzle.polly.core.parser.ast.expressions.literals.FunctionLiteral;
import de.skuzzle.polly.core.parser.ast.expressions.literals.ListLiteral;
import de.skuzzle.polly.core.parser.ast.expressions.literals.Literal;
import de.skuzzle.polly.core.parser.ast.expressions.literals.ProductLiteral;
import de.skuzzle.polly.core.parser.ast.lang.TernaryOperator;
import de.skuzzle.polly.core.parser.ast.visitor.ASTTraversalException;
import de.skuzzle.polly.core.parser.ast.visitor.ExecutionVisitor;
import de.skuzzle.polly.tools.collections.Stack;
/**
* <p>Fold left function for list literals. It takes a list, a function and an argument.
* Then, the function starts with the argument as $result and subsequently stores the
* application of the function with parameters $result and the next list element back
* to $result.</p>
*
* <p>Type information: <code>A foldLeft(List<A>, \(A: A, B), A)</code></p>
*
* @author Simon Taddiken
*/
public class FoldLeft extends TernaryOperator<ListLiteral, FunctionLiteral, Literal> {
public FoldLeft() {
super(OpType.FOLD_LEFT);
final TypeVar a = Type.newTypeVar("A");
final TypeVar b = Type.newTypeVar("B");
this.initTypes(a, b.listOf(), a.mapFrom(new ProductType(a, b)), a);
}
@Override
protected void exec(Stack<Literal> stack, Namespace ns, ListLiteral first,
FunctionLiteral second, Literal third, Position resultPos,
ExecutionVisitor execVisitor) throws ASTTraversalException {
Literal result = third;
for (final Expression exp : first.getContent()) {
final Call call = new Call(resultPos, second,
new ProductLiteral(resultPos,
Arrays.asList(new Expression[] {result, exp})));
call.visit(execVisitor);
result = stack.pop();
}
stack.push(result);
}
}