package de.skuzzle.polly.core.parser.ast.lang.operators;
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.Expression;
import de.skuzzle.polly.core.parser.ast.expressions.literals.BooleanLiteral;
import de.skuzzle.polly.core.parser.ast.expressions.literals.Literal;
import de.skuzzle.polly.core.parser.ast.lang.BinaryOperator;
import de.skuzzle.polly.core.parser.ast.visitor.ASTTraversalException;
import de.skuzzle.polly.core.parser.ast.visitor.ExecutionVisitor;
import de.skuzzle.polly.core.parser.ast.visitor.resolving.AbstractTypeResolver;
import de.skuzzle.polly.core.parser.problems.Problems;
import de.skuzzle.polly.tools.collections.Stack;
public class Relational extends BinaryOperator<Literal, Literal> {
public Relational(OpType id) {
super(id);
final TypeVar a = Type.newTypeVar("A");
this.initTypes(Type.BOOLEAN, a, a);
}
@Override
protected void resolve(Expression left, Expression right, Namespace ns,
AbstractTypeResolver typeResolver) throws ASTTraversalException {
if (!left.getUnique().isComparable()) {
typeResolver.getReporter().semanticProblem(Problems.NOT_ORDERED,
left.getPosition(), left.getUnique());
}
}
@Override
protected void exec(Stack<Literal> stack, Namespace ns, Literal left, Literal right,
Position resultPos, ExecutionVisitor execVisitor) throws ASTTraversalException {
if (this.getOp() == OpType.EQ) {
stack.push(new BooleanLiteral(resultPos, left.equals(right)));
return;
} else if (this.getOp() == OpType.NEQ) {
stack.push(new BooleanLiteral(resultPos, !left.equals(right)));
return;
}
if (!left.getUnique().isComparable()) {
execVisitor.getReporter().runtimeProblem(Problems.NOT_COMPARABLE,
left.getPosition(), left.getUnique().getName().getId());
}
if (!right.getUnique().isComparable()) {
execVisitor.getReporter().runtimeProblem(Problems.NOT_COMPARABLE,
right.getPosition(), right.getUnique().getName().getId());
}
if (!left.getUnique().isComparable() || !right.getUnique().isComparable()) {
return;
}
final int comp = left.compareTo(right);
switch (this.getOp()) {
case LT:
stack.push(new BooleanLiteral(resultPos, comp < 0));
break;
case ELT:
stack.push(new BooleanLiteral(resultPos, comp <= 0));
break;
case GT:
stack.push(new BooleanLiteral(resultPos, comp > 0));
break;
case EGT:
stack.push(new BooleanLiteral(resultPos, comp >= 0));
break;
default:
this.invalidOperatorType(this.getOp());
}
}
}