package ai.domain.bool;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jdt.core.dom.ArrayAccess;
import org.eclipse.jdt.core.dom.Assignment;
import org.eclipse.jdt.core.dom.CastExpression;
import org.eclipse.jdt.core.dom.ClassInstanceCreation;
import org.eclipse.jdt.core.dom.ConstructorInvocation;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.FieldAccess;
import org.eclipse.jdt.core.dom.InfixExpression;
import org.eclipse.jdt.core.dom.InstanceofExpression;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.NullLiteral;
import org.eclipse.jdt.core.dom.QualifiedName;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
import org.eclipse.jdt.core.dom.SuperFieldAccess;
import org.eclipse.jdt.core.dom.SuperMethodInvocation;
import ai.common.Pair;
import ai.domain.AbstractSemanticsIntf;
import ai.domain.Variable;
import ai.domain.expressions.MainExpressionEvaluator;
import ai.domain.expressions.bool.BooleanEvaluationState;
import ai.domain.expressions.bool.BooleanEvaluator;
import ai.domain.expressions.bool.BooleanExpressionSemantics;
import ai.domain.generic.NonRelationalDomain;
import ai.domain.intervals.eval.EvaluationUtils;
import ai.domain.widening.DefaultWideningOperator;
import ai.domain.widening.WideningOperator;
/**
* Abstract semantics of non relational domain of booleans.
*
* Here we take advantage of the BooleanConditionEvaluator implementation.
*
* @author kjk@mimuw.edu.pl
*
*/
public class BoolsSemantics implements AbstractSemanticsIntf<NonRelationalDomain<Bool>> {
private class MyBooleanSemantics implements BooleanExpressionSemantics<NonRelationalDomain<Bool>> {
@Override
public BooleanEvaluationState<NonRelationalDomain<Bool>> processBooleanNode(NonRelationalDomain<Bool> input,
ArrayAccess node) {
NonRelationalDomain<Bool> result = defaultEval.evaluate(node.getIndex(), input);
return BooleanEvaluator.createOutput(result, Bool.TOP);
}
@Override
public BooleanEvaluationState<NonRelationalDomain<Bool>> processBooleanNode(NonRelationalDomain<Bool> input,
FieldAccess node) {
NonRelationalDomain<Bool> result = defaultEval.evaluate(node.getExpression(), input);
return BooleanEvaluator.createOutput(result, Bool.TOP);
}
@Override
public BooleanEvaluationState<NonRelationalDomain<Bool>> processBooleanNode(NonRelationalDomain<Bool> input,
InstanceofExpression node) {
return BooleanEvaluator.createOutput(input, Bool.TOP);
}
@Override
public BooleanEvaluationState<NonRelationalDomain<Bool>> processBooleanNode(NonRelationalDomain<Bool> input,
MethodInvocation node) {
for(Object arg: node.arguments())
input = defaultEval.evaluate((Expression) arg, input);
return BooleanEvaluator.createOutput(input, Bool.TOP);
}
@Override
public BooleanEvaluationState<NonRelationalDomain<Bool>> processBooleanNode(NonRelationalDomain<Bool> input,
SimpleName node) {
Bool value;
if (EvaluationUtils.isBooleanType(node)) {
Boolean aValue = EvaluationUtils.tryGetBooleanValue(node);
if (aValue!=null) { // a constant??
value = Bool.get(aValue);
} else {// variable??
Variable var = EvaluationUtils.tryGetVariable(node);
if (var == null){ // not a variable, we know nothing :(
value = Bool.TOP;
} else
value = input.getValueFor(var);
}
} else // boxing
value = Bool.TOP;
return BooleanEvaluator.createOutput(input, value);
}
@Override
public BooleanEvaluationState<NonRelationalDomain<Bool>> processBooleanNode(NonRelationalDomain<Bool> input,
QualifiedName node) {
Boolean aValue = EvaluationUtils.tryGetBooleanValue(node);
Bool value = (aValue!=null) ? Bool.get(aValue) : Bool.TOP;
return BooleanEvaluator.createOutput(input, value);
}
@Override
public BooleanEvaluationState<NonRelationalDomain<Bool>> processBooleanNode(NonRelationalDomain<Bool> input,
NullLiteral node) {
return BooleanEvaluator.createOutput(input, Bool.TOP);
}
@Override
public BooleanEvaluationState<NonRelationalDomain<Bool>> processBooleanNode(NonRelationalDomain<Bool> input,
SuperFieldAccess node) {
Boolean aValue = EvaluationUtils.tryGetBooleanValue(node);
Bool value = (aValue != null) ? Bool.get(aValue) : Bool.TOP;
return BooleanEvaluator.createOutput(input, value);
}
@Override
public BooleanEvaluationState<NonRelationalDomain<Bool>> processBooleanNode(NonRelationalDomain<Bool> input,
SuperMethodInvocation node) {
for (Object arg : node.arguments())
input = defaultEval.evaluate((Expression) arg, input);
return BooleanEvaluator.createOutput(input, Bool.TOP);
}
@Override
public BooleanEvaluationState<NonRelationalDomain<Bool>> processBooleanNode(NonRelationalDomain<Bool> input,
ClassInstanceCreation node) {
for(Object arg: node.arguments())
input = defaultEval.evaluate((Expression)arg, input);
return BooleanEvaluator.createOutput(input, Bool.TOP);
}
@Override
public BooleanEvaluationState<NonRelationalDomain<Bool>> processBooleanNode(NonRelationalDomain<Bool> input,
CastExpression node) {
return BooleanEvaluator.createOutput(defaultEval.evaluate(node.getExpression(), input), Bool.TOP);
}
@Override
public BooleanEvaluationState<NonRelationalDomain<Bool>> processComparison(NonRelationalDomain<Bool> input,
InfixExpression node) {
return defaultEval.evaluateComparison(input, node);
}
@Override
public NonRelationalDomain<Bool> processBooleanAssignment(NonRelationalDomain<Bool> input, Expression toWhat,
Bool value) {
Variable var = EvaluationUtils.tryGetVariable(toWhat);
if (var != null)
return input.updateVariable(var, value);
else // FIXME: ??
return input;
}
@Override
public NonRelationalDomain<Bool> newBooleanVariable(NonRelationalDomain<Bool> input, Variable var,
Bool initialValueOrNull, boolean isArgument) {
if (initialValueOrNull == null) initialValueOrNull = Bool.TOP;
return input.addNewVariable(var, initialValueOrNull, isArgument);
}
@Override
public BooleanEvaluationState<NonRelationalDomain<Bool>> processBooleanBoxing(NonRelationalDomain<Bool> input,
Assignment node) {
input = defaultEval.evaluate(node.getLeftHandSide(), input);
input = defaultEval.evaluate(node.getRightHandSide(), input);
return BooleanEvaluator.createOutput(input, Bool.TOP);
}
}
final MainExpressionEvaluator<NonRelationalDomain<Bool>> defaultEval;
final BooleanEvaluator<NonRelationalDomain<Bool>> beval;
public BoolsSemantics() {
MyBooleanSemantics semantics = new MyBooleanSemantics();
this.beval = new BooleanEvaluator<NonRelationalDomain<Bool>>(semantics);
this.defaultEval = MainExpressionEvaluator.create(this.beval);
defaultEval.addEvaluator(this.beval);
// defaultEval.addComparisonEvaluator(iCondEvaleval);
// this.newConditionEvaluators = new LinkedList<ComparisonEvaluatorIntf<NonRelationalDomain<Bool>>>();
// conditionEvaluators.add(new IntegerBinaryConditionEvaluator<ProductDomain<NonRelationalDomain<Bool>, NonRelationalDomain<Interval>>, Interval>(
// this.ieval, new IntervalBackwardTestSemantics(), exprSemantics));
}
@Override
public NonRelationalDomain<Bool> processEmptyEdge(NonRelationalDomain<Bool> input, List<SimpleName> variablesToRemove) {
for(SimpleName name: variablesToRemove){
Variable var = EvaluationUtils.tryGetVariable(name);
if (var == null)
continue;
input = input.removeVariable(var);
}
return input;
}
@Override
public final NonRelationalDomain<Bool> processNewVariable(NonRelationalDomain<Bool> input,
SimpleName name, Expression initializerOrNull, boolean asAssignment) {
return defaultEval.evaluate(name, initializerOrNull, input, asAssignment);
}
@Override
public NonRelationalDomain<Bool> getInitialValue() {
return NonRelationalDomain.getInitialValue();
}
@Override
public NonRelationalDomain<Bool> processExpression(NonRelationalDomain<Bool> input, Expression expression) {
return defaultEval.evaluate(expression, input);
}
@Override
public Pair<NonRelationalDomain<Bool>, NonRelationalDomain<Bool>> processCondition(NonRelationalDomain<Bool> input,
Expression conditionOrNull) {
if (conditionOrNull == null)
return Pair.create(input, input);
BooleanEvaluationState<NonRelationalDomain<Bool>> x = beval.evaluateCondition(input, conditionOrNull);
return Pair.create(x.conditionMet, x.conditionNotMet);
}
@Override
public NonRelationalDomain<Bool> processArgument(NonRelationalDomain<Bool> input, SimpleName argument) {
return defaultEval.evaluateNewArgument(argument, input);
}
@Override
public NonRelationalDomain<Bool> processFinallyOrException(NonRelationalDomain<Bool> input,
SingleVariableDeclaration excOrNull) {
if (input.isBottom())
return input;
for(Variable var: input.getVariables())
input = input.updateVariable(var, Bool.TOP);
return input;
}
@Override
public NonRelationalDomain<Bool> processConstructorInvocation(NonRelationalDomain<Bool> input,
ConstructorInvocation constructorInvocation) {
if (constructorInvocation.arguments() == null)
return input;
for(Object arg: constructorInvocation.arguments())
input = defaultEval.evaluate((Expression)arg, input);
return input;
}
@Override
public NonRelationalDomain<Bool> processSuperConstructorInvocation(NonRelationalDomain<Bool> input,
SuperConstructorInvocation superConstructorInvocation) {
if (superConstructorInvocation.arguments() == null)
return input;
for(Object arg: superConstructorInvocation.arguments())
input = defaultEval.evaluate((Expression) arg, input);
return input;
}
@Override
public Pair<NonRelationalDomain<Bool>, ArrayList<NonRelationalDomain<Bool>>> processSwitchCases(
NonRelationalDomain<Bool> input, Expression expr, Expression[] switchCases) {
return EvaluationUtils.defaultSwitchProcess(defaultEval, input, expr, switchCases);
}
@Override
public WideningOperator<NonRelationalDomain<Bool>> getWideningOperator() {
return new DefaultWideningOperator<NonRelationalDomain<Bool>>();
}
}