public static Set <BoxedExpression> ConstantsIfLinearExpression(BoxedExpression exp) { Contract.Requires(exp != null); var visitor = new ConstantsInBoxedExpression(); exp.Dispatch(visitor); Set <BoxedExpression> result; if (!visitor.TryGetConstants(out result)) { result = null; } return(result); }
public bool TryMostGeneralSatisfaction(BoxedExpression input, BoxedExpression var, out BoxedExpression result) { BinaryOperator bop; BoxedExpression left, right; if (input.IsBinaryExpression(out bop, out left, out right) && bop.IsComparisonBinaryOperator()) { var leftVars = left.Variables(); var rightVars = right.Variables(); var vIsLeft = (leftVars.Count == 1 && rightVars.Count == 0); var vIsRight = (leftVars.Count == 0 && rightVars.Count == 1); if (vIsLeft || vIsRight) { // do the swap if (vIsLeft && bop.TryInvert(out bop)) { var tmp = right; right = left; left = tmp; } // Invariant: // + left has no variables // + right has exactly one variable // Build a new expression var newLeft = left.Sub(ConstantsInBoxedExpression.ConstantsIfLinearExpression(right)).EvaluateConstants(this.MetaDataDecoder); if (newLeft != null) { var newRight = rightVars.PickAnElement(); } switch (bop) { case BinaryOperator.Ceq: case BinaryOperator.Cge: case BinaryOperator.Cge_Un: case BinaryOperator.Cle: case BinaryOperator.Cle_Un: { result = newLeft.EvaluateConstants(this.MetaDataDecoder); return(true); } case BinaryOperator.Cgt: case BinaryOperator.Cgt_Un: { // k > x ==> x == k -1 result = MinusOne(newLeft); return(true); } case BinaryOperator.Clt: case BinaryOperator.Clt_Un: { // k < x ==> x == k+1 result = PlusOne(newLeft); return(true); } } } if (leftVars.Count == 1 && rightVars.Count == 1) { left = leftVars.PickAnElement(); right = rightVars.PickAnElement(); if (left.Equals(var) && bop.TryInvert(out bop)) { left = right; right = var; } // invariant the invariant is on the right if (right.Equals(var)) { // TODO: merge with the switch above switch (bop) { case BinaryOperator.Ceq: case BinaryOperator.Cge: case BinaryOperator.Cge_Un: case BinaryOperator.Cle: case BinaryOperator.Cle_Un: { result = left; return(true); } case BinaryOperator.Cgt: case BinaryOperator.Cgt_Un: { // k > x ==> x == k -1 result = MinusOne(left); return(true); } case BinaryOperator.Clt: case BinaryOperator.Clt_Un: { // k < x ==> x == k+1 result = PlusOne(right); return(true); } } } } } result = null; return(false); }