protected ArrayState UpdateArrayAbstractValue(APC pc, BoxedVariable <Variable> arr, NormalizedExpression <BoxedVariable <Variable> > index,
                                                              NonRelationalValueAbstraction <BoxedVariable <Variable>, BoxedExpression> ael, ArrayState prevState)
                {
                    Contract.Requires(prevState != null);
                    Contract.Ensures(Contract.Result <ArrayState>() != null);

                    ArraySegmentation <NonRelationalValueAbstraction <BoxedVariable <Variable>, BoxedExpression>, BoxedVariable <Variable>, BoxedExpression>
                    prev, updated;

                    if (prevState.Array.TryGetValue(arr, out prev))
                    {
                        if (index != null)
                        {
                            IAbstractDomain prevAel;

                            if (prev.TryGetAbstractValue(index, prevState.Numerical, out prevAel) &&
                                prevAel is NonRelationalValueAbstraction <BoxedVariable <Variable>, BoxedExpression> )
                            {
                                ael = ael.Meet(prevAel as NonRelationalValueAbstraction <BoxedVariable <Variable>, BoxedExpression>);
                            }

                            if (prev.TrySetAbstractValue(index, ael, prevState.Numerical, out updated))
                            {
                                prevState.Array[arr] = updated;
                            }
                        }
                    }

                    return(prevState);
                }
        public static INumericalAbstractDomain <Variable, Expression> TestTrue <Variable, Expression>(
            this INumericalAbstractDomain <Variable, Expression> aState,
            Variable v, NonRelationalValueAbstraction <Variable, Expression> nonRelationalValue,
            IExpressionEncoder <Variable, Expression> encoder)
        {
            Contract.Requires(v != null);
            Contract.Requires(aState != null);
            Contract.Requires(nonRelationalValue != null);
            Contract.Requires(encoder != null);

            Contract.Ensures(Contract.Result <INumericalAbstractDomain <Variable, Expression> >() != null);

            if (nonRelationalValue.IsBottom)
            {
                Contract.Assume(aState.Bottom as INumericalAbstractDomain <Variable, Expression> != null); // F: Adding the assumption as we do not track types

                return(aState.Bottom as INumericalAbstractDomain <Variable, Expression>);
            }

            if (nonRelationalValue.IsTop)
            {
                return(aState);
            }

            var result = aState;

            // Assume the interval
            if (nonRelationalValue.Interval.IsNormal())
            {
                result.AssumeInDisInterval(v, nonRelationalValue.Interval);
            }

            var vExp = encoder.VariableFor(v);

            // Assume the equalities
            if (nonRelationalValue.Equalities.IsNormal())
            {
                result = result.TestTrueEqual(vExp, nonRelationalValue.Equalities, encoder);
            }

            // Assume the strict upper bounds
            if (nonRelationalValue.StrictUpperBounds.IsNormal())
            {
                result = result.TestTrueLessThan(vExp, nonRelationalValue.StrictUpperBounds, encoder);
            }

            // Assume the weak upper bounds
            if (nonRelationalValue.WeakUpperBounds.IsNormal())
            {
                result = result.TestTrueLessEqualThan(vExp, nonRelationalValue.WeakUpperBounds, encoder);
            }

            return(result);
        }
                public override ArrayState Ldelem(APC pc, Type type, Variable dest, Variable array, Variable index, ArrayState data)
                {
                    var mySubState = Select(data);
                    var bArray     = new BoxedVariable <Variable>(array);
                    ArraySegmentation <NonRelationalValueAbstraction <BoxedVariable <Variable>, BoxedExpression>, BoxedVariable <Variable>, BoxedExpression>
                    existentialSegmentation;

                    var noConstraints = SetOfConstraints <BoxedVariable <Variable> > .Unknown;
                    var newElement    = new NonRelationalValueAbstraction <BoxedVariable <Variable>, BoxedExpression>(DisInterval.UnknownInterval, SymbolicExpressionTracker <BoxedVariable <Variable>, BoxedExpression> .Unknown,
                                                                                                                      new SetOfConstraints <BoxedVariable <Variable> >(new BoxedVariable <Variable>(dest)),
                                                                                                                      noConstraints, noConstraints, noConstraints, noConstraints);


                    if (mySubState.TryGetValue(bArray, out existentialSegmentation))
                    {
                        if (existentialSegmentation.IsNormal())
                        {
                            var newSegmentation = new ArraySegmentation <NonRelationalValueAbstraction <BoxedVariable <Variable>, BoxedExpression>, BoxedVariable <Variable>, BoxedExpression>
                                                      (new NonNullList <SegmentLimit <BoxedVariable <Variable> > >()
                            {
                                existentialSegmentation.Limits.AsIndexable()[0], existentialSegmentation.LastLimit
                            },
                                                      new NonNullList <NonRelationalValueAbstraction <BoxedVariable <Variable>, BoxedExpression> >()
                            {
                                newElement
                            },
                                                      existentialSegmentation.Elements.AsIndexable()[0].Bottom, this.ExpressionManager);

                            var meet = existentialSegmentation.Meet(newSegmentation);

                            mySubState.Update(bArray, meet);

                            return(data.UpdatePluginAt(this.Id, mySubState));
                        }
                    }
                    else // materialize
                    {
                        existentialSegmentation = MaterializeArray(this.Context.MethodContext.CFG.Post(pc),
                                                                   mySubState, data.Numerical.CheckIfNonZero, array, newElement, newElement.Bottom);

                        // Segmentation may fail
                        if (existentialSegmentation != null)
                        {
                            mySubState.Update(bArray, existentialSegmentation);

                            return(data.UpdatePluginAt(this.Id, mySubState));
                        }
                    }

                    return(data);
                }
                protected ArrayState AssumeWithArrayRefinement(APC pc, bool positive, BoxedExpression comparison, ArrayState prevState)
                {
                    Contract.Requires(comparison != null);
                    Contract.Requires(prevState != null);
                    Contract.Ensures(Contract.Result <ArrayState>() != null);

                    // Default NonRelational values
                    var interval          = DisInterval.UnknownInterval;
                    var symbExpression    = SymbolicExpressionTracker <BoxedVariable <Variable>, BoxedExpression> .Unknown;
                    var equalities        = SetOfConstraints <BoxedVariable <Variable> > .Unknown;
                    var disequalities     = SetOfConstraints <BoxedVariable <Variable> > .Unknown;
                    var weakUpperBounds   = SetOfConstraints <BoxedVariable <Variable> > .Unknown;
                    var strictUpperBounds = SetOfConstraints <BoxedVariable <Variable> > .Unknown;
                    var existential       = SetOfConstraints <BoxedVariable <Variable> > .Unknown;

                    Pair <BoxedVariable <Variable>, BoxedVariable <Variable> > refined;
                    Variable left, right;
                    int      k;

                    #region left != right ?
                    if (positive && comparison.IsCheckExp1NotEqExp2(out left, out right))
                    {
                        // refined.One[refined.Two] != right
                        var b = prevState.CanRefineToArrayLoad(new BoxedVariable <Variable>(left), out refined);
                        if (!b)
                        {
                            // left != refined.One[refined.Two]
                            b = prevState.CanRefineToArrayLoad(new BoxedVariable <Variable>(right), out refined);

                            // Swap roles
                            var tmp = left;
                            left  = right;
                            right = tmp;
                        }

                        if (b)
                        {
                            // invariant: "left" is the one to refine.

                            // TODO: right now we are ignoring the case when both are arrays

                            interval = prevState.IntervalIfNotNull(left);

                            var ael = new NonRelationalValueAbstraction <BoxedVariable <Variable>, BoxedExpression>
                                          (interval, symbExpression, equalities,
                                          new SetOfConstraints <BoxedVariable <Variable> >(new BoxedVariable <Variable>(right)),
                                          weakUpperBounds, strictUpperBounds, existential);

                            var index = ToBoxedExpression(pc, refined.Two).ToNormalizedExpression <Variable>();

                            return(UpdateArrayAbstractValue(pc, refined.One, index, ael, prevState));
                        }
                    }
                    #endregion

                    #region left != k ?
                    BinaryOperator bop;
                    if (comparison.IsCheckExpOpConst(out bop, out left, out k) &&
                        prevState.CanRefineToArrayLoad(new BoxedVariable <Variable>(left), out refined))
                    {
                        switch (bop)
                        {
                        case BinaryOperator.Ceq:
                        {
                            interval = positive ? DisInterval.For(k) : DisInterval.NotInThisInterval(DisInterval.For(k));
                            break;
                        }

                        case BinaryOperator.Cne_Un:
                        {
                            interval = positive ? DisInterval.NotInThisInterval(DisInterval.For(k)) : DisInterval.For(k);
                            break;
                        }

                        default:
                        {
                            return(prevState);
                        }
                        }

                        var ael = new NonRelationalValueAbstraction <BoxedVariable <Variable>, BoxedExpression>
                                      (interval, symbExpression, equalities, disequalities, weakUpperBounds, strictUpperBounds, existential);

                        var index = ToBoxedExpression(pc, refined.Two).Stripped().ToNormalizedExpression <Variable>();

                        return(UpdateArrayAbstractValue(pc, refined.One, index, ael, prevState));
                    }
                    #endregion

                    #region left == 0
                    if (comparison.TryGetFrameworkVariable(out left) &&
                        prevState.CanRefineToArrayLoad(new BoxedVariable <Variable>(left), out refined))
                    {
                        interval = !positive ? DisInterval.Zero : DisInterval.NotZero;

                        var ael = new NonRelationalValueAbstraction <BoxedVariable <Variable>, BoxedExpression>
                                      (interval, symbExpression, equalities, disequalities, weakUpperBounds, strictUpperBounds, existential);

                        var index = ToBoxedExpression(pc, refined.Two).Stripped().ToNormalizedExpression <Variable>();

                        return(UpdateArrayAbstractValue(pc, refined.One, index, ael, prevState));
                    }
                    #endregion

                    return(prevState);
                }
                protected bool TryInferNonRelationalProperty(BoxedExpression index, BoxedExpression body,
                                                             INumericalAbstractDomain <BoxedVariable <Variable>, BoxedExpression> dom,
                                                             out BoxedExpression array, out NonRelationalValueAbstraction <BoxedVariable <Variable>, BoxedExpression> elementsProperty)
                {
                    Contract.Ensures(!Contract.Result <bool>() || Contract.ValueAtReturn(out array) != null);
                    Contract.Ensures(!Contract.Result <bool>() || Contract.ValueAtReturn(out elementsProperty) != null);

                    BoxedExpression.ArrayIndexExpression <Type> arrayExp;
                    if (body.TryFindArrayExp(index, out arrayExp))
                    {
                        array = arrayExp.Array;
                        Contract.Assert(array != null);

                        var slackVar    = new BoxedVariable <Variable>(true);
                        var slackExp    = BoxedExpression.Var(slackVar);
                        var renamedBody = body.Substitute(arrayExp, slackExp);
                        var nonTrivial  = false;

                        var symbolicConditions = SymbolicExpressionTracker <BoxedVariable <Variable>, BoxedExpression> .Unknown;
                        var equalities         = SetOfConstraints <BoxedVariable <Variable> > .Unknown;
                        var disequalities      = SetOfConstraints <BoxedVariable <Variable> > .Unknown;
                        var weakUpperBounds    = SetOfConstraints <BoxedVariable <Variable> > .Unknown;
                        var strictUpperBounds  = SetOfConstraints <BoxedVariable <Variable> > .Unknown;
                        var existential        = SetOfConstraints <BoxedVariable <Variable> > .Unknown;

                        #region Look for an interval
                        var augmentedDom = dom.TestTrue(renamedBody) as INumericalAbstractDomain <BoxedVariable <Variable>, BoxedExpression>;
                        var intv         = augmentedDom.BoundsFor(slackVar);

                        if (intv.IsNormal)
                        {
                            nonTrivial = true;
                        }

                        // TODO: upgrade the non-relational values to disintervals, to avoid those checks
                        if (intv.IsTop && augmentedDom.CheckIfNonZero(slackExp).IsTrue())
                        {
                            intv       = DisInterval.For(1);
                            nonTrivial = true;
                        }
                        #endregion

                        #region Look for equalities

                        BoxedExpression left, right;
                        if (renamedBody.IsCheckExp1EqExp2(out left, out right))
                        {
                            Variable eq;
                            // a[i] == v
                            if (
                                (left.Equals(slackExp) && right.TryGetFrameworkVariable(out eq))
                                ||
                                (right.Equals(slackExp) && left.TryGetFrameworkVariable(out eq))
                                )
                            {
                                equalities = new SetOfConstraints <BoxedVariable <Variable> >(ToBoxedVariable(eq));
                                nonTrivial = true;
                            }
                        }

                        #endregion

                        if (nonTrivial)
                        {
                            elementsProperty = new NonRelationalValueAbstraction <BoxedVariable <Variable>, BoxedExpression>(
                                intv, symbolicConditions, equalities, disequalities, weakUpperBounds, strictUpperBounds, existential);

                            return(true);
                        }
                        else
                        {
                            elementsProperty = default(NonRelationalValueAbstraction <BoxedVariable <Variable>, BoxedExpression>);
                            return(false);
                        }
                    }

                    array            = default(BoxedExpression);
                    elementsProperty = default(NonRelationalValueAbstraction <BoxedVariable <Variable>, BoxedExpression>);
                    return(false);
                }