package de.skuzzle.polly.core.parser.ast.lang.operators;
import java.util.Random;
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.declarations.types.TypeVar;
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.lang.UnaryOperator;
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;
/**
* Operators that choose random entries from a {@link ListLiteral}.
*
* @author Simon Taddiken
*/
public class RandomListIndex extends UnaryOperator<ListLiteral> {
private final static Random RANDOM = new Random();
public RandomListIndex(OpType op) {
super(op);
final TypeVar a = Type.newTypeVar("A");
this.initTypes(a, a.listOf());
}
@Override
protected void exec(Stack<Literal> stack, Namespace ns, ListLiteral operand,
Position resultPos, ExecutionVisitor execVisitor) throws ASTTraversalException {
int i;
switch (this.getOp()) {
case QUESTION:
i = RANDOM.nextInt(operand.getContent().size());
stack.push((Literal) operand.getContent().get(i));
break;
case QUEST_EXCL:
final int size = operand.getContent().size() - 1;
final double gr = 2.0;
final double g = Math.max(Math.min(RANDOM.nextGaussian(), gr), -gr);
final double f = ((g + gr) / (2.0 * gr));
i = (int) Math.round(f * (double) size);
stack.push((Literal) operand.getContent().get(i));
break;
default:
this.invalidOperatorType(this.getOp());
}
}
}