public bool TryPartitionAt(APC pc, out SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> result)
                {
                    if (this.fixpointInfo.PreState(pc, out result))
                    {
                        return(true);
                    }

                    result = default(SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression>);
                    return(false);
                }
                public bool LookupState(IMethodResult <Variable> mr, APC pc, out SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> astate)
                {
                    astate = null;
                    PartitionAnalysis an = mr as PartitionAnalysis;

                    if (an == null)
                    {
                        return(false);
                    }

                    return(an.PreStateLookup(pc, out astate));
                }
                public bool AssignInParallel(IMethodResult <Variable> mr, ref SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> astate, Dictionary <BoxedVariable <Variable>, FList <BoxedVariable <Variable> > > mapping, Converter <BoxedVariable <Variable>, BoxedExpression> convert)
                {
                    PartitionAnalysis an = mr as PartitionAnalysis;

                    if (an == null)
                    {
                        return(false);
                    }

                    astate.AssignInParallel(mapping, convert);
                    return(true);
                }
                public List <BoxedExpression> ExtractAssertions(
                    IMethodResult <Variable> mr,
                    SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> astate,
                    IExpressionContext <APC, Local, Parameter, Method, Field, Type, ExternalExpression, Variable> context,
                    IDecodeMetaData <Local, Parameter, Method, Field, Property, Type, Attribute, Assembly> metaDataDecoder)
                {
                    PartitionAnalysis an = mr as PartitionAnalysis;

                    if (an == null)
                    {
                        return(null);
                    }

                    BoxedExpressionReader <APC, Local, Parameter, Method, Field, Property, Type, Variable, ExternalExpression, Attribute, Assembly> br = new BoxedExpressionReader <APC, Local, Parameter, Method, Field, Property, Type, Variable, ExternalExpression, Attribute, Assembly>(context, metaDataDecoder);

                    return(an.ToListOfBoxedExpressions(astate, br));
                }
                /// <summary>
                ///
                /// </summary>
                private SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> GenericArrayHandling(APC pc, Variable array, SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> data)
                {
                    Variable arrayLengthVar;

                    if (this.Context.TryGetArrayLength(this.Context.Post(pc), array, out arrayLengthVar))
                    {
                        // if a symbolic value is assigned twice, thanks to symbolic values semantics, its equivalent to nop.
                        // So we keep the partition such as it is.
                        if (!data.ContainsKey(ToBoxedVariable(array)))
                        {
                            return(HandleAllocations(pc, array, arrayLengthVar, data));
                        }

                        return(data);
                    }

                    Debug.Assert(false, "ArrayLength of an array must be known");

                    return(data);
                }
                public override SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> Binary(APC pc, BinaryOperator op, Variable dest, Variable s1, Variable s2, SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> data)
                {
                    Log("Binary:{0}", op);
                    if (OperatorExtensions.IsComparisonBinaryOperator(op))
                    {
                        // TODO: if s1 or s2 includes an array term, partitioning must be done.
                        return(data);
                    }
                    else if (OperatorExtensions.IsBooleanBinaryOperator(op))
                    {
                        // TODO: see above
                        return(data);
                    }
                    else
                    {
                        var destAsExp  = ToBoxedExpression(pc, dest);
                        var leftAsExp  = ToBoxedExpressionWithConstantRefinement(pc, s1);
                        var rightAsExp = ToBoxedExpressionWithConstantRefinement(pc, s2);

                        ALog.BeginTransferFunction(StringClosure.For("Assign"),
                                                   StringClosure.For("{0} := {1}({2}, {3})",
                                                                     ExpressionPrinter.ToStringClosure(destAsExp, this.Decoder), StringClosure.For(op),
                                                                     ExpressionPrinter.ToStringClosure(leftAsExp, this.Decoder), ExpressionPrinter.ToStringClosure(rightAsExp, this.Decoder)),
                                                   PrettyPrintPC(pc), StringClosure.For(data));

                        // Hypothesis : if it is a reminder or division operation, we assume that the dividend is not zero
                        var             refinedDomain = data;
                        BoxedExpression rightOfAssignment;

                        Log("REPACK:{1} {0} {2}", op, s1, s2);

                        if (TryRepackAssignment(op, leftAsExp, rightAsExp, out rightOfAssignment))
                        {
                            var arraysToRefine = data.arraysWithPartitionDefinedOnASubsetExpressionOf(rightOfAssignment);

                            if (!arraysToRefine.IsEmpty)
                            {
                                var assignmentKnowledge         = this.Encoder.CompoundExpressionFor(ExpressionType.Bool, ExpressionOperator.Equal, destAsExp, rightOfAssignment);
                                var assignmentStrippedKnowledge = this.Encoder.CompoundExpressionFor(ExpressionType.Bool, ExpressionOperator.Equal, destAsExp, RecursiveStripped(rightOfAssignment));
                                assignmentKnowledge = this.Encoder.CompoundExpressionFor(ExpressionType.Bool, ExpressionOperator.And, assignmentKnowledge, assignmentStrippedKnowledge);

                                //Log("KNOWLEDGEonREPACK:{0}", rightOfAssignment);

                                foreach (var array in arraysToRefine)
                                {
                                    refinedDomain = HandleIndexAssignment("", pc,
                                                                          array,
                                                                          ToBoxedVariable(dest),
                                                                          rightOfAssignment,
                                                                          assignmentKnowledge, refinedDomain);
                                }
                            }
                        }
                        //else
                        //{
                        //  throw new AbstractInterpretationException(); //TODO : leave the else.
                        //}

                        ALog.EndTransferFunction(StringClosure.For(refinedDomain));

                        return(refinedDomain);
                    }
                }
 public override SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> Unary(APC pc, UnaryOperator op, bool overflow, bool unsigned, Variable dest, Variable source, SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> data)
 {
     // TODO: case Neg and Not
     Log("Unary:{0}", op);
     return(data);
 }
                public override SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> Isinst(APC pc, Type type, Variable dest, Variable obj, SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> data)
                {
                    if (isOneDimensionalArray(pc, dest))
                    {
                        return(GenericArrayHandling(pc, dest, data));
                    }

                    return(data);
                }
                public override SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> Call <TypeList, ArgList>(APC pc, Method method, bool tail, bool virt, TypeList extraVarargs, Variable dest, ArgList args, SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> data)
                {
                    if (isOneDimensionalArray(pc, dest))
                    {
                        var      fullNameForMethod = this.DecoderForMetaData.FullName(method);
                        Variable arrayLengthVar;

                        if (fullNameForMethod.StartsWith("System.Runtime.CompilerServices.RuntimeHelpers.InitializeArray"))
                        {
                            if (this.Context.TryGetArrayLength(this.Context.Post(pc), args[0], out arrayLengthVar))
                            {
                                var arrayLengthExp = BoxedExpression.For(this.Context.Refine(pc, arrayLengthVar), this.Decoder.Outdecoder);
                                arrayLengthExp = this.Decoder.Stripped(arrayLengthExp);
                                int n;

                                if (arrayLengthExp.IsConstantInt(out n))
                                {
                                    var refinedDomain = data;
                                    // var arrayAsExp = BoxedExpression.For(this.Context.Refine(pc, args[0]), this.Decoder.Outdecoder);

                                    var array = ToBoxedVariable(args[0]);

                                    var knowledge = this.Encoder.ConstantFor(true);

                                    for (int i = 0; i < n; i++)
                                    {
                                        //refinedDomain = HandleArrayAssignment("InitializeArray", pc, args[0], i, refinedDomain);
                                        refinedDomain = refinedDomain.ArrayAssignment(array, this.Encoder.ConstantFor(i), knowledge, new Set <BoxedVariable <Variable> >());
                                    }

                                    return(refinedDomain);
                                }
                                else
                                {
                                    // TODO: probably nothing
                                }
                            }

                            Debug.Assert(false, "ArrayLength of an array must be known");
                        }

                        //if (isArray(pc, dest))
                        //{
                        return(GenericArrayHandling(pc, dest, data));
                        //}
                    }

                    return(data);
                }
                public override SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> Ldarg(APC pc, Parameter argument, bool isOld, Variable dest, SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> data)
                {
                    // TODO: what is isOld for ?
                    if (isOneDimensionalArray(pc, dest))
                    {
                        return(GenericArrayHandling(pc, dest, data));
                    }

                    return(data);
                }
                private SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> HandleIndexAssignment(string name, APC pc,
                                                                                                                        BoxedVariable <Variable> array, BoxedVariable <Variable> index,
                                                                                                                        BoxedExpression assignedAsExp, BoxedExpression assignmentKnowledge,
                                                                                                                        SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> data)
                {
                    ALog.BeginTransferFunction(StringClosure.For("[P]IndexAssignement"),
                                               StringClosure.For(""), PrettyPrintPC(pc), StringClosure.For(data));

                    //var baseVariables = this.Decoder.VariablesIn(indexAsExp);
                    var baseVariables = this.Decoder.VariablesIn(assignedAsExp);

                    Log("VARIABLESIN={0}", baseVariables);

                    var indexAsExp = ToBoxedExpression(pc, index);

                    var indexKnowledge = gatherKnowledge(this.Context.Post(pc), indexAsExp); //TODO: post is not useful here

                    var knowledge = this.Encoder.CompoundExpressionFor(ExpressionType.Bool,
                                                                       ExpressionOperator.And,
                                                                       indexKnowledge,
                                                                       assignmentKnowledge);

                    // TODO : useless if indexAsExp is based on variables already in the partition (which space is delimited)
                    //var indexRange = guessRange(pc, indexAsExp);
                    //Log("LB={0}", indexRange.One);
                    //Log("UB={0}", indexRange.Two);

                    IPartitionAbstraction <BoxedVariable <Variable>, BoxedExpression> arrayPartition;
                    var refinedDomain = data;

                    if (data.TryGetValue(array, out arrayPartition))
                    {
                        var singles = arrayPartition.Singles();
                        Log("SINGLES={0}", singles);

                        var b = baseVariables.Remove(index);

                        foreach (var single in singles)
                        {
                            if (!this.Decoder.IsConstant(single))
                            {
                                var variablesInSingle = this.Decoder.VariablesIn(single);

                                if (baseVariables.IsSubset(variablesInSingle))
                                {
                                    // The general case is very complicated. Here we assume that single has the form of an octagon contraint (+/- y + c)
                                    if (baseVariables.Count == 1)
                                    {
                                        var indexSubstitute = this.Encoder.Substitute(single, ToBoxedExpression(pc, baseVariables.PickAnElement()), indexAsExp);

                                        var notWanted = new Set <BoxedVariable <Variable> >(baseVariables);

                                        if (!indexSubstitute.IsVariable) // HACK due to handling of expression
                                        {
                                            notWanted.Add(this.Decoder.UnderlyingVariable(indexSubstitute));
                                        }

                                        refinedDomain = refinedDomain.ArrayAssignment(array, indexSubstitute, knowledge, notWanted);
                                    }
                                    else // Otherwise we try to partition wrt indexAsExp
                                    {
                                        refinedDomain = refinedDomain.ArrayAssignment(array, indexAsExp, knowledge, baseVariables);
                                    }
                                }
                            }
                        }
                    }
                    else
                    {
                        throw new AbstractInterpretationException();
                    }

                    ALog.EndTransferFunction(StringClosure.For(data));

                    return(refinedDomain);
                }
                /// <summary>
                /// Hypothesis: Bound Analysis assumed.
                /// </summary>
                /// <param name="dest"></param>
                private SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> HandleArrayAssignment(
                    string name, APC pc,
                    Variable array, Variable index,
                    SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> data)
                {
                    var arrayAsExp = BoxedExpression.For(this.Context.Refine(pc, array), this.Decoder.Outdecoder);
                    var indexAsExp = BoxedExpression.For(this.Context.Refine(pc, index), this.Decoder.Outdecoder);

                    ALog.BeginTransferFunction(StringClosure.For("[P]ArrayAssignement"),
                                               ExpressionPrinter.ToStringClosure(arrayAsExp, this.Decoder), PrettyPrintPC(pc), StringClosure.For(data));

                    var baseVariables = this.Decoder.VariablesIn(indexAsExp);

                    Log("VARIABLESIN={0}", baseVariables);
                    // TODO: decide wich variables you want in the partition : probably here a variable inside. You must gatherKnowledge for each variable inside, and reconstruct the bounds of interest.
                    // eg. index: sv1; index is (sv2+1); indexKnowledge is (0,sv3); so (sv2+1) go from 1 to sv3+1 (but could be unnecessary if sv2 is already into the partition ...;
                    var notWanted = new Set <BoxedVariable <Variable> >();

                    if (baseVariables.Count > 1 || !baseVariables.Contains(ToBoxedVariable(index)))
                    {
                        notWanted.Add(ToBoxedVariable(index));
                    }

                    var knowledge         = this.Encoder.ConstantFor(true);
                    var equalityKnowledge = this.Encoder.ConstantFor(true);

                    foreach (var e in baseVariables)
                    {
                        knowledge = this.Encoder.CompoundExpressionFor(ExpressionType.Bool,
                                                                       ExpressionOperator.And,
                                                                       knowledge,
                                                                       gatherKnowledge(this.Context.Post(pc), ToBoxedExpression(this.Context.Post(pc), e)));
                    }

                    if (!notWanted.IsEmpty)
                    {
                        // NOTE : even if notWanted will not be part of the split partition used, it can already be present in the current partition.
                        // This is why we provide the information, to be used in simplify.
                        PolynomialOfInt <BoxedVariable <Variable>, BoxedExpression> indexAsPoly;
                        if (PolynomialOfInt <BoxedVariable <Variable>, BoxedExpression> .TryToPolynomialForm(indexAsExp, this.Decoder, out indexAsPoly))
                        {
                            equalityKnowledge = this.Encoder.CompoundExpressionFor(ExpressionType.Bool,
                                                                                   ExpressionOperator.Equal,
                                                                                   indexAsExp,
                                                                                   PolynomialOfInt <BoxedVariable <Variable>, BoxedExpression> .ToPureExpressionForm(indexAsPoly, this.Encoder));

                            knowledge = this.Encoder.CompoundExpressionFor(ExpressionType.Bool, ExpressionOperator.And, knowledge, equalityKnowledge);
                        }
                    }

                    //var indexKnowledge = gatherKnowledge(pc, indexAsExp);

                    foreach (var e in baseVariables)
                    {
                        var indexRange = guessRange(pc, ToBoxedExpression(pc, e)); // carefull : One or Two can be null.
                        Log("LB({1})={0}", indexRange.One, e);
                        Log("UB({1})={0}", indexRange.Two, e);
                    }
                    var indexRange2 = guessRange(pc, indexAsExp); // carefull : One or Two can be null.

                    Log("LB({1})={0}", indexRange2.One, indexAsExp);
                    Log("UB({1})={0}", indexRange2.Two, indexAsExp);

                    var refinedDomain = data.ArrayAssignment(ToBoxedVariable(array), indexAsExp, knowledge, notWanted); //,notWanted

                    ALog.EndTransferFunction(StringClosure.For(data));

                    return(refinedDomain);
                }
                /// <summary>
                /// Hypothesis: Bound Analysis assumed that <code>0 &le; len </code> and
                /// </summary>
                /// <param name="dest"></param>
                private SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> HandleAllocations(APC pc, Variable dest, Variable len, SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> data)
                {
                    var lenAsExp = BoxedExpression.For(this.Context.Refine(pc, len), this.Decoder.Outdecoder);

                    lenAsExp = this.Decoder.Stripped(lenAsExp);
                    var destAsExp = BoxedExpression.For(this.Context.Refine(pc, dest), this.Decoder.Outdecoder);

                    ALog.BeginTransferFunction(StringClosure.For("[P]Allocation"),
                                               ExpressionPrinter.ToStringClosure(lenAsExp, this.Decoder), PrettyPrintPC(pc), StringClosure.For(data));

                    var refinedDomain = data.Allocation(new BoxedVariable <Variable>(dest), lenAsExp);

                    ALog.EndTransferFunction(StringClosure.For(data));

                    return(refinedDomain);
                }
                protected override SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> HelperForJoin(SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> newState, SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> prevState, Pair <APC, APC> edge)
                {
                    /// - that an array can be null, and in his case not appearing into the environment

                    var keep = new Set <BoxedVariable <Variable> >();

                    foreach (var bv in prevState.Variables)
                    {
                        Variable v;
                        if (bv.TryUnpackVariable(out v))
                        {
                            var atJoinPoint   = this.factQuery.IsNull(edge.Two, v);
                            var atJoinedPoint = this.factQuery.IsNull(edge.One, v);

                            if (atJoinPoint == ProofOutcome.Top)
                            {
                                //if (atJoinedPoint == ProofOutcome.True)
                                //{
                                //  // do nothing
                                //}
                                //else if (atJoinedPoint == ProofOutcome.False)
                                {
                                    // for some paths exp is null : we want to keep it in the environment
                                    keep.Add(bv);
                                }

                                // TODO: could be also TOP if in every branch a (non-identity) rebinding appeared
                            }
                        }
                    }

                    var result = newState.Join(prevState, keep);

                    //return base.HelperForJoin(newState, prevState, edge);
                    return(result);
                }
 /// <summary>
 /// We allocate a new partition to the array
 /// </summary>
 public override SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> Newarray <ArgList>(APC pc, Type type, Variable dest, ArgList lengths, SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> data)
 {
     if (lengths.Count == 1)
     {
         return(HandleAllocations(pc, dest, lengths[0], data));
     }
     else
     {
         return(data); // TODO multidimensional array
     }
 }
                public override SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> Ldfld(APC pc, Field field, bool @volatile, Variable dest, Variable obj, SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> data)
                {
                    if (isOneDimensionalArray(pc, dest))
                    {
                        return(GenericArrayHandling(pc, dest, data));
                    }

                    return(data);
                }
                public override SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> Stelem(APC pc, Type type, Variable array, Variable index, Variable value, SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> data)
                {
                    if (isOneDimensionalArray(pc, array))
                    {
                        bool wasTop = data.IsTop;

                        Log("STELEM={0}[{1}]", array, index);
                        var result = HandleArrayAssignment("Stelem", pc, array, index, data);

                        Debug.Assert(wasTop || !result.IsTop);

                        return(result);
                    }

                    return(data);
                }
                public SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> Join(IMethodResult <Variable> mr, SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> astate1, SimplePartitionAbstractDomain <BoxedVariable <Variable>, BoxedExpression> astate2)
                {
                    PartitionAnalysis an = mr as PartitionAnalysis;

                    if (an == null)
                    {
                        return(null);
                    }

                    bool bWeaker;

                    return(an.Join(new Pair <APC, APC>(), astate1, astate2, out bWeaker, false));
                }