package calculator.interpreter.ast.logic;
import calculator.interpreter.Environment;
import calculator.interpreter.EvalException;
import calculator.interpreter.ast.Expression;
import calculator.interpreter.ast.InfixOp;
/**
* Base class for comparison operators
*/
public abstract class ComparisonOp extends InfixOp {
@SuppressWarnings("unchecked")
@Override
public Object eval(Environment env) {
Comparable f = checkComparable(env, first);
Comparable s = checkComparable(env, second);
if (f.getClass() != s.getClass()) {
throw new EvalException(this,
"Only values of the same type could be compared: "
+ f.getClass().getName() + " != " + s.getClass().getName());
}
return compared(f.compareTo(s));
}
/**
* Check if the value is comparable
*
* @param env the evaluation environment
* @param e the expression to evaluate
* @return the result of expression
*/
private Comparable<?> checkComparable(Environment env, Expression e) {
Object o = e.eval(env);
if (o == null || !(o instanceof Comparable)) {
throw new EvalException(this, "The expression at "
+ e.location.toShortString() + " has evaluated to " + o + " : "
+ (o == null ? null : o.getClass().getName())
+ " which is not comparable.");
}
return (Comparable<?>) o;
}
/**
* Convert result of comparison operation to boolean
*
* @param result the result of {@link Comparable#compareTo(Object)}.
* @return a boolean value
*/
protected abstract boolean compared(int result);
}