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);
                }
                public override ArrayState Assume(APC pc, string tag, Variable source, object provenance, ArrayState data)
                {
                    Contract.Assume(data != null);

                    if (tag != "false")
                    {
                        Variable v1, v2;
                        if (this.ToBoxedExpression(pc, source).IsCheckExp1EqExp2(out v1, out v2))
                        {
                            data = data.UpdatePluginAt(this.Id, Select(data).TestTrueEqual(new BoxedVariable <Variable>(v1), new BoxedVariable <Variable>(v2)));
                        }
                    }
                    return(data.UpdatePluginAt(this.Id, Select(data).ReduceWith(data.Numerical)));
                }
                public override ArrayState Call <TypeList, ArgList>(APC pc, Method method, bool tail, bool virt, TypeList extraVarargs, Variable dest, ArgList args, ArrayState data)
                {
                    Contract.Assume(data != null);

                    var postPC = this.Context.MethodContext.CFG.Post(pc);

                    if (!this.MethodDriver.ExpressionLayer.ContractDecoder.IsPure(method))
                    {
                        var mySubState = Select(data);
                        // Havoc all the arrays in the arguments that are not marked as pure
                        for (var pos = this.DecoderForMetaData.IsStatic(method) ? 0 : 1; pos < args.Count; pos++)
                        {
                            Variable arrayValue, index;
                            // An array is passed. Havoc the content
                            if (mySubState.ContainsKey(new BoxedVariable <Variable>(args[pos])) && !this.DecoderForMetaData.IsPure(method, pos))
                            {
                                mySubState.RemoveVariable(new BoxedVariable <Variable>(args[pos]));
                            }
                            // an array is passed by ref: Havoc the array
                            else if (this.Context.ValueContext.TryGetArrayFromElementAddress(pc, args[pos], out arrayValue, out index))
                            {
                                mySubState.RemoveVariable(new BoxedVariable <Variable>(arrayValue));
                            }
                        }

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

                    // Materialize the array if any
                    data = MaterializeUnmodifiedIfArray(postPC, dest, data);

                    return(data);
                }
                public override ArrayState Assert(APC pc, string tag, Variable condition, object provenance, ArrayState data)
                {
                    Contract.Ensures(Contract.Result <ArrayState>() != null);

                    Contract.Assume(data != null);

                    var conditionExp = ToBoxedExpression(pc, condition);

                    if (conditionExp == null)
                    {
                        return(data);
                    }

                    // We first check (x == nul) == 0
                    BoxedExpression checkedExp;
                    Variable        var1, var2;

                    if (conditionExp.IsCheckExpNotNotNull(out checkedExp) && checkedExp.TryGetFrameworkVariable(out var1))
                    {
                        return(AssumeCheckOfAnArrayElement(pc, var1, data));
                    }
                    else if (conditionExp.IsCheckExp1EqExp2(out var1, out var2))
                    {
                        var refined = Select(data).TestTrueEqual(new BoxedVariable <Variable>(var1), new BoxedVariable <Variable>(var2));

                        return(data.UpdatePluginAt(this.Id, refined));
                    }
                    else
                    {
                        var t1 = Select(data);

                        // Otherwise see if "assert refined.One[refined.Two]
                        return(AssumeCheckOfAnArrayElement(pc, condition, data));
                    }
                }
                public override ArrayState Ldelem(
                    APC pc, Type type, Variable dest, Variable array, Variable index, ArrayState data)
                {
                    Contract.Assume(data != null);

                    var mySubState = Select(data);

                    var boxedArray = new BoxedVariable <Variable>(array);
                    var boxedIndex = new BoxedVariable <Variable>(index);

                    var symbolicConditions = SymbolicExpressionTracker <BoxedVariable <Variable>, BoxedExpression> .Unknown;

                    ScalarFromArrayTracking prevInfo;

                    if (mySubState.TryGetValue(new BoxedVariable <Variable>(dest), out prevInfo))
                    {
                        Contract.Assert(prevInfo.Conditions != null);
                        symbolicConditions = symbolicConditions.Meet(prevInfo.Conditions);
                    }

                    var isUnModifiedArrayElement = data.IsUnmodifiedArrayElementFromEntry(boxedArray, ToBoxedExpression(pc, index));

                    var newRelation = new ScalarFromArrayTracking(boxedArray, boxedIndex, isUnModifiedArrayElement, symbolicConditions);

                    mySubState[new BoxedVariable <Variable>(dest)] = newRelation;

                    return(data.UpdatePluginAt(this.Id, mySubState));
                }
                public override ArrayState Assume(APC pc, string tag, Variable source, object provenance, ArrayState data)
                {
                    Contract.Assume(data != null);

                    var sourceExp = BoxedExpression.Convert(this.MethodDriver.Context.ExpressionContext.Refine(pc, source), this.MethodDriver.ExpressionDecoder); // Force conversion, as the expression may be very large!

                    if (sourceExp == null)
                    {
                        return(data);
                    }

                    var mySubState = Select(data);

                    #region Get the predicate P(a[exp]), for some 'a' and 'exp'

                    var variablesInExp = sourceExp.Variables <Variable>().ConvertAll(v => new BoxedVariable <Variable>(v));

                    var toUpdate = new List <BoxedVariable <Variable> >();

                    foreach (var pair in mySubState.Elements)
                    {
                        if (variablesInExp.Contains(pair.Key))
                        {
                            toUpdate.Add(pair.Key);
                        }
                    }

                    #region Handle equalities

                    Variable v1, v2;
                    if (sourceExp.IsCheckExp1EqExp2(out v1, out v2)                        // direct syntactical equality
                        ||
                        (tag == "false" && sourceExp.IsCheckExp1NotEqExp2(out v1, out v2)) // double negation
                        )
                    {
                        return(data.UpdatePluginAt(this.Id, mySubState.TestTrueEqual(new BoxedVariable <Variable>(v1), new BoxedVariable <Variable>(v2))));
                    }

                    #endregion

                    // Shortcut: build the negation 'sourceExp == 0'
                    if (tag == "false")
                    {
                        sourceExp = BoxedExpression.Binary(BinaryOperator.Ceq, sourceExp, BoxedExpression.Const(0, this.DecoderForMetaData.System_Int32, this.DecoderForMetaData));
                    }

                    foreach (var key in toUpdate)
                    {
                        Contract.Assume(mySubState[key] != null);
                        mySubState[key] = mySubState[key].AddCondition(key, sourceExp);
                    }

                    #endregion

                    return(data);
                }
                public override ArrayState Assume(APC pc, string tag, Variable source, object provenance, ArrayState data)
                {
                    var md   = this.MethodDriver;
                    var cond = BoxedExpression.Convert(md.Context.ExpressionContext.Refine(pc, source), md.ExpressionDecoder).Simplify(md.MetaDataDecoder);

                    Type     type;
                    Variable var;

                    if (cond != null)
                    {
                        // normalize assume(false) !(...)
                        if (tag == "false" && cond.IsUnary && cond.UnaryOp == UnaryOperator.Not)
                        {
                            cond = cond.UnaryArgument;
                        }

                        if (cond.IsAssumeIsAType(out var, out type))
                        {
                            return(data.UpdatePluginAt(this.Id, Select(data).Update(var, type)));
                        }

                        Variable left, right;
                        if (cond.IsBinary && cond.BinaryOp == BinaryOperator.Cobjeq & cond.BinaryLeft.TryGetFrameworkVariable(out left) && cond.BinaryRight.TryGetFrameworkVariable(out right))
                        {
                            var  runtimeTypes = Select(data);
                            var  boxedLeft    = new BoxedVariable <Variable>(left);
                            var  boxedRight   = new BoxedVariable <Variable>(right);
                            Type t;
                            if (runtimeTypes.TryGetValue(left, out t))
                            {
                                runtimeTypes[boxedRight] = t;
                            }
                            if (runtimeTypes.TryGetValue(right, out t))
                            {
                                runtimeTypes[boxedLeft] = t;
                            }

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

                    return(base.Assume(pc, tag, source, provenance, data));
                }
                public override ArrayState Assume(APC pc, string tag, Variable source, object provenance, ArrayState data)
                {
                    Contract.Assume(data != null);

                    if (tag != "false")
                    {
                        data = this.Assert(pc, "assume", source, provenance, data);

                        Contract.Assert(data != null);

                        var convertedExp = ToBoxedExpression(pc, source);

                        if (convertedExp == null)
                        {
                            // abort
                            return(data);
                        }

                        Variable        v1, v2;
                        BoxedExpression bLeft, bRight, x;
                        int             k;
                        if (convertedExp.IsCheckExp1EqExp2(out bLeft, out bRight) && // bLeft == bRight
                            bRight.IsCheckExp1EqConst(out x, out k) &&                  // bRight == x + 1
                            bLeft.TryGetFrameworkVariable(out v1) &&
                            x.TryGetFrameworkVariable(out v2)
                            )
                        {
                            var vNormExp = NormalizedExpression <BoxedVariable <Variable> > .For(new BoxedVariable <Variable>(v1));

                            var sumNormExp = NormalizedExpression <BoxedVariable <Variable> > .For(new BoxedVariable <Variable>(v2), k);

                            var mySubState = Select(data);
                            mySubState = mySubState.TestTrueEqualAsymmetric(vNormExp, sumNormExp);
                            mySubState = mySubState.TestTrueEqualAsymmetric(sumNormExp, vNormExp);

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

                    return(data.UpdatePluginAt(this.Id, Select(data).ReduceWith(data.Numerical)));
                }
                public override ArrayState HelperForAssignInParallel(
                    ArrayState state,
                    Pair <APC, APC> edge, Dictionary <BoxedVariable <Variable>, FList <BoxedVariable <Variable> > > refinedMap,
                    Converter <BoxedVariable <Variable>, BoxedExpression> convert)
                {
                    Contract.Assume(state != null);

                    var mySubState = Select(state);

                    mySubState.AssignInParallel(refinedMap, convert);

                    return(state.UpdatePluginAt(this.Id, mySubState));
                }
                public override ArrayState Stelem(APC pc, Type type, Variable array, Variable index, Variable value, ArrayState data)
                {
                    var mySubState = Select(data);
                    var bArray     = new BoxedVariable <Variable>(array);

                    if (mySubState.ContainsKey(bArray))
                    {
                        mySubState.RemoveElement(bArray);

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

                    return(data);
                }
                public override ArrayState Assume(APC pc, string tag, Variable source, object provenance, ArrayState data)
                {
                    Contract.Assume(data != null, "Assume for inheritance");

                    #region Assume the existential, if any

                    if (tag != "false")
                    {
                        var exist = this.MethodDriver.AsExistsIndexed(pc, source);
                        if (exist != null)
                        {
                            var updated = AssumeExistsAll(pc, exist, data);

                            if (updated.IsBottom)
                            {
                                return(data.Bottom);
                            }

                            data = data.UpdatePluginAt(this.Id, updated);
                        }
                    }

                    #endregion

                    #region Look for contraddictions forall/exists
                    var bottom = NonRelationalValueAbstraction <BoxedVariable <Variable>, BoxedExpression> .Unreached;

                    foreach (var pair in Select(data).Elements)
                    {
                        if (pair.Value.IsNormal)
                        {
                            ArraySegmentation <NonRelationalValueAbstraction <BoxedVariable <Variable>, BoxedExpression>, BoxedVariable <Variable>, BoxedExpression> universal;
                            if (data.Array.TryGetValue(pair.Key, out universal))
                            {
                                if (pair.Value.JoinAll(bottom).AreInContraddiction(universal.JoinAll(bottom)))
                                {
                                    // Found a contraddiction!!!
                                    return(data.Bottom);
                                }
                            }
                        }
                    }
                    #endregion

                    return(data);
                }
                private ArrayState MaterializeUnmodifiedIfArray(APC postPC, Variable dest, ArrayState data)
                {
                    Contract.Requires(data != null);

                    var destType = this.Context.ValueContext.GetType(postPC, dest);

                    if (destType.IsNormal && this.DecoderForMetaData.IsArray(destType.Value))
                    {
                        var mySubState = Select(data);
                        if (this.MaterializeArray(
                                postPC, mySubState, data.Numerical.CheckIfNonZero, dest, UNMODIFIED, UNMODIFIED) != null)
                        {
                            data = data.UpdatePluginAt(this.Id, mySubState);
                        }
                    }

                    return(data);
                }
                private ArrayState AssumeCheckOfAnArrayElement(APC pc, Variable var, ArrayState data)
                {
                    Contract.Requires(data != null);
                    Contract.Ensures(Contract.Result <ArrayState>() != null);

                    Pair <BoxedVariable <Variable>, BoxedVariable <Variable> > refined;

                    if (data.CanRefineToArrayLoad(new BoxedVariable <Variable>(var), out refined))
                    {
                        var mySubState = Select(data);
                        ArraySegmentation <
                            FlatAbstractDomainOfBoolsWithRenaming <BoxedVariable <Variable> >, BoxedVariable <Variable>, BoxedExpression> segmentation;

                        Contract.Assume(refined.One != null);
                        Contract.Assume(refined.Two != null);

                        // Do we have a segmentation?
                        foreach (var arr in GetEquals(pc, refined.One, data))
                        {
                            if (mySubState.TryGetValue(arr, out segmentation))
                            {
                                // Is it unmodified?
                                if (data.IsUnmodifiedArrayElementFromEntry(arr, ToBoxedExpression(pc, refined.Two)))
                                {
                                    var norm = ToBoxedExpression(pc, refined.Two).ToNormalizedExpression <Variable>();
                                    if (norm != null && segmentation.TrySetAbstractValue(norm, CHECKED, data.Numerical, out segmentation))
                                    {
                                        mySubState.Update(arr, segmentation);
                                    }
                                    else
                                    {
                                        mySubState.RemoveElement(arr);
                                    }

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

                    return(data);
                }
                public override ArrayState Call <TypeList, ArgList>(APC pc, Method method, bool tail, bool virt, TypeList extraVarargs, Variable dest, ArgList args, ArrayState data)
                {
                    if (!this.MethodDriver.ExpressionLayer.ContractDecoder.IsPure(method))
                    {
                        var mySubState = Select(data);

                        if (mySubState.IsNormal())
                        {
                            var result             = mySubState.Top;
                            var atLeastOneExcluded = false;

                            var argsAsBoxedVariables = new List <BoxedVariable <Variable> >();
                            foreach (var arg in args.Enumerate())
                            {
                                argsAsBoxedVariables.Add(new BoxedVariable <Variable>(arg));
                            }

                            foreach (var el in mySubState.Elements)
                            {
                                var arrays = el.Value.Left;
                                if (arrays.IsNormal() && !arrays.Values.Intersect(argsAsBoxedVariables).Any())
                                {
                                    result.AddElement(el.Key, el.Value);
                                }
                                else
                                {
                                    atLeastOneExcluded = true;
                                }
                            }

                            if (atLeastOneExcluded)
                            {
                                return(data.UpdatePluginAt(this.Id, result));
                            }
                        }
                    }
                    return(data);
                }
                public override ArrayState Entry(APC pc, Method method, ArrayState data)
                {
                    Contract.Assume(data != null);

                    var mySubState = Select(data);

                    // We materialize all the arrays in the parameters...
                    foreach (var param in this.DecoderForMetaData.Parameters(method).Enumerate())
                    {
                        Variable symb;
                        var      postPC = Context.MethodContext.CFG.Post(pc);
                        if (
                            this.Context.ValueContext.TryParameterValue(postPC, param, out symb))
                        {
                            if (this.DecoderForMetaData.IsArray(DecoderForMetaData.ParameterType(param)))
                            {
                                var dummy = MaterializeArray(
                                    postPC, mySubState,
                                    data.Numerical.CheckIfNonZero, symb, UNCHECKED,
                                    new FlatAbstractDomainOfBoolsWithRenaming <BoxedVariable <Variable> >(FlatAbstractDomain <bool> .State.Bottom));
                            }
                            else
                            {
                                var paramType = this.DecoderForMetaData.ParameterType(param);
                                foreach (var intf in this.DecoderForMetaData.Interfaces(paramType))
                                {
                                    if (this.DecoderForMetaData.Name(intf).AssumeNotNull().Contains("IEnumerable"))
                                    {
                                        var dummy = MaterializeEnumerable(postPC, mySubState, symb, UNCHECKED);
                                    }
                                }
                            }
                        }
                    }

                    return(data.UpdatePluginAt(this.Id, mySubState));
                }
                public override ArrayState Call <TypeList, ArgList>(APC pc, Method method, bool tail, bool virt, TypeList extraVarargs, Variable dest, ArgList args, ArrayState data)
                {
                    Contract.Assume(data != null);

                    if (!this.DecoderForContracts.IsPure(method))
                    {
                        var mySubState = Select(data);
                        // Havoc all the arrays in the arguments that are not marked as pure
                        for (var pos = this.DecoderForMetaData.IsStatic(method) ? 0 : 1; pos < args.Count; pos++)
                        {
                            Variable arrayValue, index;
                            // An array is passed. Havoc the content
                            if (mySubState.ContainsKey(new BoxedVariable <Variable>(args[pos])) && !this.DecoderForMetaData.IsPure(method, pos))
                            {
                                mySubState.RemoveVariable(new BoxedVariable <Variable>(args[pos]));
                            }
                            // an array is passed by ref: Havoc the array
                            else if (this.Context.ValueContext.TryGetArrayFromElementAddress(pc, args[pos], out arrayValue, out index))
                            {
                                mySubState.RemoveVariable(new BoxedVariable <Variable>(arrayValue));
                            }
                        }

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

                    if (!this.DecoderForMetaData.IsStatic(method))
                    {
                        Contract.Assume(args.Count > 0);
                        return(AssumeCheckOfAnArrayElement(pc, args[0], data));
                    }
                    else
                    {
                        return(data);
                    }
                }
                public override ArrayState Binary(APC pc, BinaryOperator op, Variable dest, Variable s1, Variable s2, ArrayState data)
                {
                    Variable var;
                    int      k;

                    if (TryMatchVariableConstant(pc, op, Strip(pc, s1), Strip(pc, s2), data.Numerical, out var, out k) && k != Int32.MinValue)
                    {
                        var mySubState = Select(data);

                        var normExpression = NormalizedExpression <BoxedVariable <Variable> > .For(new BoxedVariable <Variable>(var), k);

                        var normVariable = NormalizedExpression <BoxedVariable <Variable> > .For(new BoxedVariable <Variable>(dest));

                        var array = mySubState.TestTrueEqualAsymmetric(normVariable, normExpression);

                        normExpression = NormalizedExpression <BoxedVariable <Variable> > .For(new BoxedVariable <Variable>(dest), -k);

                        normVariable = NormalizedExpression <BoxedVariable <Variable> > .For(new BoxedVariable <Variable>(var));

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

                    return(data);
                }
                public override ArrayState Stelem(APC pc, Type type, Variable array, Variable index, Variable value, ArrayState data)
                {
                    Contract.Assume(data != null);

                    var mySubState = Select(data);

                    var boxedArray = new BoxedVariable <Variable>(array);
                    var boxedIndex = new BoxedVariable <Variable>(index);


                    if (mySubState.IsNormal())
                    {
                        var toRemove = new List <BoxedVariable <Variable> >();
                        foreach (var pair in mySubState.Elements)
                        {
                            var el = pair.Value;
                            if (el.IsNormal() && el.Left.IsNormal() && el.Left.Contains(boxedArray) && el.Right.IsNormal() && el.Right.Contains(boxedIndex))
                            {
                                toRemove.Add(pair.Key);
                            }
                        }

                        foreach (var k in toRemove)
                        {
                            mySubState.RemoveElement(k);
                        }
                    }

                    var isUnModifiedArrayElement = data.IsUnmodifiedArrayElementFromEntry(boxedArray, ToBoxedExpression(pc, index));

                    var newRelation = new ScalarFromArrayTracking(boxedArray, boxedIndex, isUnModifiedArrayElement, SymbolicExpressionTracker <BoxedVariable <Variable>, BoxedExpression> .Unknown);

                    mySubState[new BoxedVariable <Variable>(value)] = newRelation;

                    return(data.UpdatePluginAt(this.Id, mySubState));
                }
 public ArrayState MakeState(EnumDefined <BoxedVariable <Variable>, Type, BoxedExpression> newSubState, ArrayState oldState)
 {
     return(oldState.UpdatePluginAt(this.Id, newSubState));
 }
                public override ArrayState Call <TypeList, ArgList>(APC pc, Method method, bool tail, bool virt,
                                                                    TypeList extraVarargs, Variable dest, ArgList args, ArrayState data)
                {
                    Contract.Assume(data != null);

                    var mdd = this.DecoderForMetaData;

                    var methodname = mdd.Name(method);

                    Contract.Assert(methodname != null);
                    var containingType     = mdd.DeclaringType(method);
                    var containingTypeName = mdd.Name(containingType);
                    var nsName             = mdd.Namespace(containingType);

                    if (nsName != null && /* && methodname != null */
                        nsName.Equals("System") && methodname.Equals("GetTypeFromHandle"))
                    {
                        Type runtimeType;
                        if (Context.ValueContext.IsRuntimeType(this.Context.MethodContext.CFG.Post(pc), dest, out runtimeType)) // Get the type
                        {
                            return(data.UpdatePluginAt(this.Id, Select(data).Update(dest, runtimeType)));
                        }

                        return(data);
                    }

                    if (nsName != null && nsName.Equals("System") && methodname.Equals("get_GenericTypeArguments"))
                    {
                        var runtimeTypes = Select(data);
                        Contract.Assume(args.Count > 0);
                        var key = args[0];

                        Type t;
                        if (runtimeTypes.TryGetValue(key, out t))
                        {
                            IIndexable <Type> typeList; Variable len;
                            if (this.DecoderForMetaData.IsGeneric(t, out typeList, false) && this.MethodDriver.Context.ValueContext.TryGetArrayLength(pc.Post(), dest, out len))
                            {
                                // assume lenght == typeList.Count + 1
                                var range = DisInterval.For(typeList.Count + 1);
                                data.Numerical.AssumeInDisInterval(new BoxedVariable <Variable>(len), range); // unfortunately with side-effects ...
                            }
                        }

                        return(data);
                    }

                    if (nsName != null && containingTypeName != null &&
                        nsName.Equals("System") && containingTypeName.Equals("Enum"))
                    {
                        Type type;
                        if (args.Count == 2 && methodname == "IsDefined" && Select(data).TryGetValue(args[0], out type))
                        {
                            var enumvalues = new List <int>();
                            if (mdd.TryGetEnumValues(type, out enumvalues))
                            {
                                Variable unboxed;

                                // We check if it is the right integer
                                if (this.Context.ValueContext.TryUnbox(pc, args[1], out unboxed))
                                {
                                    var bounds     = data.Numerical.BoundsFor(ToBoxedExpression(pc, unboxed));
                                    var enumValues = DisInterval.For(enumvalues.ConvertAll(y => Interval.For(y)));

                                    if (bounds.LessEqual(enumValues))
                                    {
                                        var guard = ToBoxedExpression(pc, dest);
                                        if (guard == null)
                                        {
                                            return(data);
                                        }
                                        var newNumerical = data.Numerical.TestTrue(guard) as INumericalAbstractDomain <BoxedVariable <Variable>, BoxedExpression>;

                                        Contract.Assume(newNumerical != null);

                                        return(data.UpdateNumerical(newNumerical));
                                    }
                                    else if (bounds.Meet(enumValues).IsBottom)
                                    {
                                        var exp = ToBoxedExpression(pc, dest);
                                        if (exp == null)
                                        {
                                            return(data);
                                        }

                                        var newNumerical = data.Numerical.TestFalse(exp) as INumericalAbstractDomain <BoxedVariable <Variable>, BoxedExpression>;

                                        Contract.Assume(newNumerical != null);

                                        return(data.UpdateNumerical(newNumerical));
                                    }
                                }
                                // Otherwise we check if it is used by name
                                object value;
                                Type   typeValue;
                                if (this.Context.ValueContext.IsConstant(pc, args[1], out typeValue, out value) && this.DecoderForMetaData.System_String.Equals(typeValue))
                                {
                                    List <string> enumFields;
                                    if (this.DecoderForMetaData.TryGetEnumFields(type, out enumFields))
                                    {
                                        var enumFieldName = value as string;
                                        Contract.Assume(enumFieldName != null);
                                        if (enumFields.Contains(enumFieldName))
                                        {
                                            var exp = ToBoxedExpression(pc, dest);
                                            if (exp == null)
                                            {
                                                return(data);
                                            }
                                            var newNumerical = data.Numerical.TestTrue(exp) as INumericalAbstractDomain <BoxedVariable <Variable>, BoxedExpression>;

                                            Contract.Assume(newNumerical != null);

                                            return(data.UpdateNumerical(newNumerical));
                                        }
                                        else
                                        {
                                            var exp = ToBoxedExpression(pc, dest);
                                            if (exp == null)
                                            {
                                                return(data);
                                            }
                                            var newNumerical = data.Numerical.TestFalse(exp) as INumericalAbstractDomain <BoxedVariable <Variable>, BoxedExpression>;

                                            Contract.Assume(newNumerical != null);

                                            return(data.UpdateNumerical(newNumerical));
                                        }
                                    }
                                }
                            }
                        }
                    }
                    return(data);
                }
                public override ArrayState Stelem(
                    APC pc, Type type, Variable array, Variable index, Variable value, ArrayState data)
                {
                    Contract.Assume(data != null);

                    var state  = Select(data);
                    var bArray = new BoxedVariable <Variable>(array);

                    ArraySegmentation <TwoValuesLattice <BoxedVariable <Variable> >, BoxedVariable <Variable>, BoxedExpression> segment, newSegment;

                    if (state.TryGetValue(bArray, out segment))
                    {
                        var indexExp     = ToBoxedExpression(pc, index);
                        var indexNormExp = indexExp.ToNormalizedExpression <Variable>();

                        if (indexNormExp == null)
                        {
                            // Try to find a numerical bounds
                            var indexValue = data.Numerical.BoundsFor(indexExp).AsInterval;
                            if (indexValue.IsSingleton && indexValue.LowerBound.IsInteger)
                            {
                                indexNormExp = NormalizedExpression <BoxedVariable <Variable> > .For((Int32)indexValue.LowerBound);

                                Contract.Assert(indexNormExp != null);
                            }
                            else
                            {
                                // We have a range of addresses
                                Int32 low, upp;
                                if (indexValue.IsFiniteAndInt32(out low, out upp))
                                {
                                    var lowExp = NormalizedExpression <BoxedVariable <Variable> > .For(low);

                                    var uppExp = NormalizedExpression <BoxedVariable <Variable> > .For(upp);

                                    if (segment.TrySetAbstractValue(lowExp, uppExp,
                                                                    MAYBEMODIFIED,
                                                                    data.Numerical, out newSegment))
                                    {
                                        state.Update(new BoxedVariable <Variable>(array), newSegment);

                                        return(data.UpdatePluginAt(this.Id, state));
                                    }
                                }
                                state.RemoveElement(new BoxedVariable <Variable>(array));

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

                        if (segment.TrySetAbstractValue(indexNormExp, MAYBEMODIFIED, data.Numerical, out newSegment))
                        {
                            // We explicty add the constant for indexNormExp, if we have one
                            Rational val;
                            if (data.Numerical.BoundsFor(indexExp).TryGetSingletonValue(out val) && val.IsInteger)
                            {
                                var k = (Int32)val;
                                // Add k == indexNormExp
                                newSegment = newSegment.TestTrueEqualAsymmetric(NormalizedExpression <BoxedVariable <Variable> > .For(k), indexNormExp);
                            }

                            // Add the sv = constants informations
                            newSegment = newSegment.TestTrueWithIntConstants(data.Numerical.IntConstants.ToNormalizedExpressions());

                            state.Update(new BoxedVariable <Variable>(array), newSegment);
                        }
                        else // For some reason, we were unable to set the abstract value, so we smash all the array to one
                        {
                            state.RemoveElement(new BoxedVariable <Variable>(array));
                        }
                    }

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