package ai.domain.expressions;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.ConditionalExpression;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.InfixExpression;
import org.eclipse.jdt.core.dom.SimpleName;
import ai.domain.DomainIntf;
import ai.domain.bool.Bool;
import ai.domain.expressions.bool.BooleanConditionEvaluatorIntf;
import ai.domain.expressions.bool.BooleanEvaluationState;
import ai.domain.expressions.bool.BooleanEvaluator;
import ai.domain.expressions.bool.ComparisonEvaluatorIntf;
public class MainExpressionEvaluator<DI extends DomainIntf<DI>> implements ExpressionEvaluatorIntf<DI> {
private class MyVisitor extends ASTVisitor {
@Override
public boolean preVisit2(ASTNode node) {
if (!(node instanceof Expression))
return false; // FIXME: do not go further??
if (state.isBottom()) //no need to go inside
return false;
Expression expr = (Expression) node;
for (ExpressionEvaluatorIntf<DI> evaluator : evaluators) {
DI result = evaluator.evaluate(expr, state);
if (result != null) {// handled
state = result;
return false;
}
}
//we do not go into qualified names
if (node.getNodeType() == ASTNode.QUALIFIED_NAME)
return false;
if (node.getNodeType() == ASTNode.CONDITIONAL_EXPRESSION) {
ConditionalExpression cond = (ConditionalExpression) node;
BooleanEvaluationState<DI> bes = bCondEval.evaluateCondition(state, cond.getExpression());
state = bes.conditionMet;
cond.getThenExpression().accept(this);
DI thenResult = state;
state = bes.conditionNotMet;
cond.getElseExpression().accept(this);
DI elseResult = state;
state = thenResult.join(elseResult);
return false;
}
return true;
}
}
private final List<ExpressionEvaluatorIntf<DI>> evaluators;
private DI state;
private MyVisitor visitor;
private final List<ComparisonEvaluatorIntf<DI>> comparisonEvaluators;
private final BooleanConditionEvaluatorIntf<DI> bCondEval;
private MainExpressionEvaluator(BooleanConditionEvaluatorIntf<DI> bCondEval) {
this.evaluators = new LinkedList<ExpressionEvaluatorIntf<DI>>();
this.comparisonEvaluators = new LinkedList<ComparisonEvaluatorIntf<DI>>();
this.visitor = new MyVisitor();
this.bCondEval = bCondEval;
}
public void addEvaluator(ExpressionEvaluatorIntf<DI> evaluator) {
evaluators.add(evaluator);
}
public void addComparisonEvaluator(ComparisonEvaluatorIntf<DI> evaluator) {
comparisonEvaluators.add(evaluator);
}
public BooleanEvaluationState<DI> evaluateComparison(DI input, InfixExpression expr) {
if (input.isBottom())
return BooleanEvaluator.createOutput(input, Bool.TOP);
for (ComparisonEvaluatorIntf<DI> evaluator : comparisonEvaluators) {
BooleanEvaluationState<DI> result = evaluator.evaluateComparison(input, expr);
if (result != null)
return result;
}
//default evaluation
input = evaluate(expr.getLeftOperand(), input);
input = evaluate(expr.getRightOperand(), input);
return BooleanEvaluator.createOutput(input, Bool.TOP);
}
public DI evaluate(Expression expr, DI input) {
if (input.isBottom())
return input;
state = input;
expr.accept(visitor);
return state;
}
@Override
public DI evaluate(SimpleName name, Expression initializerOrNull, DI input,
boolean asAssignment) {
if (input.isBottom())
return input;
for (ExpressionEvaluatorIntf<DI> evaluator : evaluators) {
DI result = evaluator.evaluate(name, initializerOrNull, input, asAssignment);
if (result != null)
return result;
}
state = input;
if (initializerOrNull != null)
initializerOrNull.accept(visitor);
return state;
}
@Override
public DI evaluateNewArgument(SimpleName argument, DI input) {
if (input.isBottom())
return input;
for (ExpressionEvaluatorIntf<DI> evaluator : evaluators) {
DI result = evaluator.evaluateNewArgument(argument, input);
if (result != null)
return result;
}
return input;
}
public static <DI extends DomainIntf<DI>> MainExpressionEvaluator<DI> create(BooleanConditionEvaluatorIntf<DI> bCondEval){
return new MainExpressionEvaluator<DI>(bCondEval);
}
}