public ScalarFromArrayTracking Meet(ScalarFromArrayTracking a)
                {
                    Contract.Requires(a != null);
                    Contract.Ensures(Contract.Result <ScalarFromArrayTracking>() != null);

                    ScalarFromArrayTracking result;

                    if (AbstractDomainsHelper.TryTrivialMeet(this, a, out result))
                    {
                        return(result);
                    }

                    var meetWrite =
                        this.isUnmodifiedFromEntry.IsTop? a.isUnmodifiedFromEntry :
                        a.isUnmodifiedFromEntry.IsTop ? this.isUnmodifiedFromEntry:
                        a.isUnmodifiedFromEntry.BoxedElement == this.isUnmodifiedFromEntry.BoxedElement? a.isUnmodifiedFromEntry :
                        CheckOutcome.Top;

                    Contract.Assume(meetWrite != null);

                    return(new ScalarFromArrayTracking(
                               (SetOfConstraints <BoxedVariable <Variable> >) this.left.Meet(a.left),
                               (SetOfConstraints <BoxedVariable <Variable> >) this.right.Meet(a.right),
                               meetWrite, this.conditions.Meet(a.conditions)));
                }
                protected override T To <T>(BoxedVariable <Variable> d, ScalarFromArrayTracking c, IFactory <T> factory)
                {
                    var result = factory.IdentityForAnd;

                    if (c.Left.IsNormal())
                    {
                        T name;
                        if (factory.TryGetBoundVariable(out name))
                        {
                            var first = true;

                            foreach (var x in c.Left.Values)
                            {
                                T arrayLength;
                                if (factory.TryArrayLengthName(factory.Variable(x), out arrayLength))
                                {
                                    var body   = factory.EqualTo(factory.Variable(d), factory.ArrayIndex(factory.Variable(x), name));
                                    var exists = factory.Exists(factory.Constant(0), arrayLength, body);

                                    if (first)
                                    {
                                        result = exists;
                                        first  = false;
                                    }
                                    else
                                    {
                                        result = factory.And(result, exists);
                                    }
                                }
                            }
                        }
                    }

                    return(result);
                }
                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 bool LessEqual(ScalarFromArrayTracking a)
                {
                    Contract.Requires(a != null);

                    bool result;

                    if (AbstractDomainsHelper.TryTrivialLessEqual(this, a, out result))
                    {
                        return(result);
                    }

                    return(this.left.LessEqual(a.left) && this.right.LessEqual(a.right) && this.isUnmodifiedFromEntry.LessEqual(a.isUnmodifiedFromEntry) && this.conditions.LessEqual(a.conditions));
                }
                public ScalarFromArrayTracking Widening(ScalarFromArrayTracking prev)
                {
                    Contract.Requires(prev != null);
                    Contract.Ensures(Contract.Result <ScalarFromArrayTracking>() != null);

                    ScalarFromArrayTracking result;

                    if (AbstractDomainsHelper.TryTrivialJoin(this, prev, out result))
                    {
                        return(result);
                    }

                    return(new ScalarFromArrayTracking(
                               (SetOfConstraints <BoxedVariable <Variable> >) this.left.Widening(prev.left),
                               (SetOfConstraints <BoxedVariable <Variable> >) this.right.Widening(prev.right),
                               this.isUnmodifiedFromEntry.Join(prev.isUnmodifiedFromEntry), this.conditions.Join(prev.conditions)));
                }
                public override void AssignInParallel(
                    Dictionary <BoxedVariable <Variable>, FList <BoxedVariable <Variable> > > sourcesToTargets,
                    Converter <BoxedVariable <Variable>, BoxedExpression> convert)
                {
                    if (!this.IsNormal())
                    {
                        return;
                    }

                    var result = new
                                 List <Pair <BoxedVariable <Variable>, ScalarFromArrayTracking> >();

                    foreach (var element in this.Elements)
                    {
                        FList <BoxedVariable <Variable> > newNames;
                        if (sourcesToTargets.TryGetValue(element.Key, out newNames))
                        {
                            var newLeft  = element.Value.Left.Rename(sourcesToTargets);
                            var newRight = element.Value.Right.Rename(sourcesToTargets);


                            if (newLeft.IsNormal() || newRight.IsNormal())
                            {
                                var renamedPair = new ScalarFromArrayTracking(
                                    newLeft, newRight, element.Value.IsUnmodifiedFromEntry, element.Value.Conditions);

                                foreach (var newKey in newNames.GetEnumerable())
                                {
                                    result.Add(newKey, renamedPair);
                                }
                            }
                        }
                    }

                    this.ClearElements();
                    foreach (var el in result)
                    {
                        this[el.One] = el.Two;
                    }
                }
                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));
                }