public void ValueAtReturn <Type>(Type type, BoxedExpression expression, BoxedExpression original)
 {
     original.Dispatch(this);
     if (this.PartialResult != null)
     {
         NotifyOkAndSetResult(ClousotExpression <Type> .ValueAtReturn(this.PartialResult, type));
     }
     else
     {
         NotifyNotOk(original);
     }
 }
 public void IsInst <Type>(Type type, BoxedExpression argument, BoxedExpression original)
 {
     argument.Dispatch(this);
     if (this.PartialResult != null)
     {
         NotifyOkAndSetResult(ClousotExpression <Type> .MakeIsInst(type, this.PartialResult));
     }
     else
     {
         NotifyNotOk(original);
     }
 }
        /// <summary>
        /// If failIfCannotReplaceVarsWithAccessPaths is true, whenever we cannot convert a variable into an expression, we return null.
        /// Otherwise (when failIfCannotReplaceVarsWithAccessPaths is false), then we return the same expression
        /// </summary>
        public BoxedExpression ReadAt(APC pc, BoxedExpression exp, bool failIfCannotReplaceVarsWithAccessPaths = true, Typ allowReturnValue = default(Typ))
        {
            Contract.Requires(exp != null);

            if (this.boundVariables.Contains(exp))
            {
                return(exp);
            }

            if (exp.IsVariable)
            {
                Variable var;
                if (exp.TryGetFrameworkVariable(out var))
                {
                    var accessPath = context.ValueContext.AccessPathList(pc, var, true, true, allowReturnValue);

                    if (accessPath != null)
                    {
                        return(BoxedExpression.Var(var, accessPath));
                    }

                    Contract.Assert(accessPath == null, "Just for readibility: we are here if we do not have an access path for the variable");

                    return(failIfCannotReplaceVarsWithAccessPaths ? null : exp);
                }

                return(null);
            }

            BinaryOperator  bop;
            BoxedExpression left, right;

            if (exp.IsBinaryExpression(out bop, out left, out right))
            {
                Variable leftVar, rightVar;
                if (left.TryGetFrameworkVariable(out leftVar) && right.IsConstant)
                {
                    var typeLeft = this.context.ValueContext.GetType(pc, leftVar);
                    if (typeLeft.IsNormal && IsInterestingBoundFromTheTypeRange(right, typeLeft.Value))
                    {
                        var recurse = ReadAt(pc, left, failIfCannotReplaceVarsWithAccessPaths, allowReturnValue);
                        if (recurse != null)
                        {
                            return(BoxedExpression.Binary(bop, recurse, right));
                        }
                    }

                    return(null);
                }

                if (left.IsConstant && right.TryGetFrameworkVariable(out rightVar))
                {
                    var typeRight = this.context.ValueContext.GetType(pc, rightVar);
                    if (typeRight.IsNormal && IsInterestingBoundFromTheTypeRange(left, typeRight.Value))
                    {
                        var recurse = ReadAt(pc, right, failIfCannotReplaceVarsWithAccessPaths, allowReturnValue);
                        if (recurse != null)
                        {
                            return(BoxedExpression.Binary(bop, left, recurse));
                        }
                    }

                    return(null);
                }

                var recurseLeft  = ReadAt(pc, left, failIfCannotReplaceVarsWithAccessPaths, allowReturnValue);
                var recurseRight = ReadAt(pc, right, failIfCannotReplaceVarsWithAccessPaths, allowReturnValue);

                if (recurseLeft != null && recurseRight != null)
                {
                    return(BoxedExpression.Binary(bop, recurseLeft, recurseRight));
                }
                else
                {
                    return(null);
                }
            }

            UnaryOperator uop;

            if (exp.IsUnaryExpression(out uop, out left))
            {
                var recurse = ReadAt(pc, left, failIfCannotReplaceVarsWithAccessPaths, allowReturnValue);
                if (recurse != null)
                {
                    return(BoxedExpression.Unary(uop, recurse));
                }
                return(null);
            }

            object type;

            if (exp.IsIsInstExpression(out left, out type))
            {
                var recurse = ReadAt(pc, left, failIfCannotReplaceVarsWithAccessPaths, allowReturnValue);
                if (recurse != null)
                {
                    return(ClousotExpression <Type> .MakeIsInst((Type)type, recurse));
                }
                return(null);
            }
            bool            isForAll;
            BoxedExpression boundVar, inf, sup, body;

            if (exp.IsQuantifiedExpression(out isForAll, out boundVar, out inf, out sup, out body))
            {
                Contract.Assert(boundVar != null);
                Contract.Assert(inf != null);
                Contract.Assert(sup != null);
                Contract.Assert(body != null);

                this.boundVariables.Add(boundVar);

                var infRec = ReadAt(pc, inf, failIfCannotReplaceVarsWithAccessPaths, allowReturnValue);
                if (infRec != null)
                {
                    var supRec = ReadAt(pc, sup, failIfCannotReplaceVarsWithAccessPaths, allowReturnValue);
                    if (supRec != null)
                    {
                        var bodyRec = ReadAt(pc, body, failIfCannotReplaceVarsWithAccessPaths, allowReturnValue);
                        if (bodyRec != null)
                        {
                            this.boundVariables.Remove(boundVar);

                            if (isForAll)
                            {
                                return(new ForAllIndexedExpression(null, boundVar, infRec, supRec, bodyRec));
                            }
                            else
                            {
                                return(new ExistsIndexedExpression(null, boundVar, infRec, supRec, bodyRec));
                            }
                        }
                    }
                }

                return(null);
            }

            object          t;
            BoxedExpression array, index;

            if (exp.IsArrayIndexExpression(out array, out index, out t) && t is Typ)
            {
                var arrayRec = ReadAt(pc, array, failIfCannotReplaceVarsWithAccessPaths, allowReturnValue);
                if (arrayRec != null)
                {
                    var indexRec = ReadAt(pc, index, failIfCannotReplaceVarsWithAccessPaths, allowReturnValue);
                    if (indexRec != null)
                    {
                        return(new BoxedExpression.ArrayIndexExpression <Typ>(arrayRec, indexRec, (Typ)t));
                    }
                }
            }

            return(exp);
        }