package de.skuzzle.polly.core.parser.ast.lang.operators;
import java.util.ArrayList;
import java.util.List;
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.Type;
import de.skuzzle.polly.core.parser.ast.expressions.Expression;
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.NumberLiteral;
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.core.parser.problems.ProblemReporter;
import de.skuzzle.polly.core.parser.problems.Problems;
import de.skuzzle.polly.tools.collections.Stack;
public class TernaryDotDot extends
TernaryOperator<NumberLiteral, NumberLiteral, NumberLiteral> {
/** Maximum size for generated ListLiterals */
public final static int MAX_LIST_SIZE = 10000;
/**
* Creates a ListLiteral that contains numbers from <code>first</code> until
* <code>second</code>
*
* @param first First number in the generated list.
* @param second Last number in the generated list.
* @param step Step between each generated number.
* @param resultPos Suitable position for the resulting literal.
* @param reporter ProblemReporter to report possible errors.
* @return New ListLiteral containing the sequence of numbers.
* @throws ASTTraversalException If start or end definitions are illegal.
*/
public static ListLiteral createSequence(NumberLiteral first, NumberLiteral second,
NumberLiteral step, Position resultPos, ProblemReporter reporter)
throws ASTTraversalException {
double start = first.getValue();
double end = second.getValue();
double s = step.getValue();
double values = start;
if (start > end && s > 0.0) {
reporter.runtimeProblem(Problems.ILLEGAL_INDIZES, resultPos, start, end);
} else if (start > end) {
double tmp = start;
start = end;
end = tmp;
}
double listSize = Math.abs(end - start) / s;
if (listSize > MAX_LIST_SIZE) {
reporter.runtimeProblem(Problems.LIST_SIZE, resultPos, listSize,
MAX_LIST_SIZE);
}
final List<Expression> content = new ArrayList<Expression>();
while (start <= end) {
content.add(new NumberLiteral(resultPos, values));
values += s;
start += Math.abs(s);
}
final ListLiteral ll = new ListLiteral(resultPos, content);
ll.addType(ll.getUnique());
ll.setUnique(Type.NUM.listOf());
return ll;
}
public TernaryDotDot() {
super(OpType.DOTDOT);
this.initTypes(Type.NUM.listOf(), Type.NUM, Type.NUM, Type.NUM);
}
@Override
protected void exec(Stack<Literal> stack, Namespace ns, NumberLiteral first,
NumberLiteral second, NumberLiteral third, Position resultPos,
ExecutionVisitor execVisitor) throws ASTTraversalException {
switch (this.getOp()) {
case DOTDOT:
stack.push(createSequence(first, second, third, resultPos,
execVisitor.getReporter()));
break;
default:
this.invalidOperatorType(this.getOp());
}
}
}