package ql.ast.visitor.evaluator;
import ql.Value;
import ql.ast.Expression;
import ql.ast.Statement;
import ql.ast.expression.Identifier;
import ql.ast.expression.arithmetic.Add;
import ql.ast.expression.arithmetic.Divide;
import ql.ast.expression.arithmetic.Multiply;
import ql.ast.expression.arithmetic.Negation;
import ql.ast.expression.arithmetic.Positive;
import ql.ast.expression.arithmetic.Subtract;
import ql.ast.expression.booleanalgebra.And;
import ql.ast.expression.booleanalgebra.Not;
import ql.ast.expression.booleanalgebra.Or;
import ql.ast.expression.literal.BooleanLiteral;
import ql.ast.expression.literal.FloatLiteral;
import ql.ast.expression.literal.IntegerLiteral;
import ql.ast.expression.literal.MoneyLiteral;
import ql.ast.expression.literal.StringLiteral;
import ql.ast.expression.relational.Equal;
import ql.ast.expression.relational.Greater;
import ql.ast.expression.relational.GreaterOrEqual;
import ql.ast.expression.relational.Lower;
import ql.ast.expression.relational.LowerOrEqual;
import ql.ast.expression.relational.NotEqual;
import ql.ast.visitor.ExpressionVisitor;
import ql.ast.visitor.StatementVisitor;
import ql.ast.visitor.TypeVisitor;
import ql.value.UndefinedValue;
public class Evaluator extends StatementVisitor<Value> implements ExpressionVisitor<Value>, TypeVisitor<Void> {
private ValueEnvironment valueEnv;
private Evaluator(ValueEnvironment valueEnv) {
this.valueEnv = valueEnv;
super.setExpressionVisitor(this);
super.setTypeVisitor(this);
}
public static Value check(Statement tree, ValueEnvironment valueEnvironment) {
Evaluator evaluator = new Evaluator(valueEnvironment);
return tree.accept(evaluator);
}
public static Value check(Expression tree, ValueEnvironment valueEnvironment) {
Evaluator evaluator = new Evaluator(valueEnvironment);
return tree.accept(evaluator);
}
@Override
public Value visit(Positive pos) {
Value expressionValue = pos.getExpression().accept(this);
return expressionValue.positive();
}
@Override
public Value visit(Not not) {
Value expressionValue = not.getExpression().accept(this);
return expressionValue.not();
}
@Override
public Value visit(Negation neg) {
Value expressionValue = neg.getExpression().accept(this);
return expressionValue.negative();
}
@Override
public Value visit(Or or) {
Value leftValue = or.getLeft().accept(this);
Value rightValue = or.getRight().accept(this);
return leftValue.or(rightValue);
}
@Override
public Value visit(NotEqual nEq) {
Value leftValue = nEq.getLeft().accept(this);
Value rightValue = nEq.getRight().accept(this);
return leftValue.notEqualTo(rightValue);
}
@Override
public Value visit(Lower lt) {
Value leftValue = lt.getLeft().accept(this);
Value rightValue = lt.getRight().accept(this);
return leftValue.lowerThan(rightValue);
}
@Override
public Value visit(LowerOrEqual lEq) {
Value leftValue = lEq.getLeft().accept(this);
Value rightValue = lEq.getRight().accept(this);
return leftValue.lowerOrEqual(rightValue);
}
@Override
public Value visit(Greater gt) {
Value leftValue = gt.getLeft().accept(this);
Value rightValue = gt.getRight().accept(this);
return leftValue.greaterThan(rightValue);
}
@Override
public Value visit(GreaterOrEqual gEq) {
Value leftValue = gEq.getLeft().accept(this);
Value rightValue = gEq.getRight().accept(this);
return leftValue.greaterOrEqual(rightValue);
}
@Override
public Value visit(Equal eq) {
Value leftValue = eq.getLeft().accept(this);
Value rightValue = eq.getRight().accept(this);
return leftValue.equalTo(rightValue);
}
@Override
public Value visit(And and) {
Value leftValue = and.getLeft().accept(this);
Value rightValue = and.getRight().accept(this);
return leftValue.and(rightValue);
}
@Override
public Value visit(StringLiteral stringLiteral) {
return stringLiteral.getValue();
}
@Override
public Value visit(IntegerLiteral integerLiteral) {
return integerLiteral.getValue();
}
@Override
public Value visit(FloatLiteral floatLiteral) {
return floatLiteral.getValue();
}
@Override
public Value visit(BooleanLiteral booleanLiteral) {
return booleanLiteral.getValue();
}
@Override
public Value visit(MoneyLiteral moneyLiteral) {
return moneyLiteral.getValue();
}
@Override
public Value visit(Add add) {
Value leftValue = add.getLeft().accept(this);
Value rightValue = add.getRight().accept(this);
return leftValue.add(rightValue);
}
@Override
public Value visit(Divide div) {
Value leftValue = div.getLeft().accept(this);
Value rightValue = div.getRight().accept(this);
return leftValue.divide(rightValue);
}
@Override
public Value visit(Multiply mul) {
Value leftValue = mul.getLeft().accept(this);
Value rightValue = mul.getRight().accept(this);
return leftValue.multiply(rightValue);
}
@Override
public Value visit(Subtract sub) {
Value leftValue = sub.getLeft().accept(this);
Value rightValue = sub.getRight().accept(this);
return leftValue.subtract(rightValue);
}
@Override
public Value visit (Identifier identifier) {
Value val = valueEnv.resolve(identifier);
if (val == null) {
return new UndefinedValue();
}
return val;
}
}