Exemple #1
0
        // Might avoid map store flushing
        public Expr ReadMapAt(IList <Expr> indices)
        {
            TypeCheckIndices(indices);

            if (AreConcrete(indices))
            {
                Expr storedValue = null;
                var  mapKey      = new MapKey(indices);
                StoresAtConcreteIndices.TryGetValue(mapKey, out storedValue);

                if (storedValue != null)
                {
                    // We have a hit! Return the stored value
                    return(storedValue);
                }
            }
            else if (AreKnownSymbolicNonAliasingIndices(indices))
            {
                // We have this symbolic location already stored
                var mapKey = new MapKey(indices);
                return(StoresAtSymbolicNonAliasingIndices[mapKey]);
            }

            // Reading from a location in the map we don't have stored
            // so we need to flush all stores and return the full expression.
            // Note we aren't doing a write so we can keep the stores in
            // StoresAtConcreteIndices and StoresAtSymbolicNonAliasingIndices
            // for future look up.
            // (by not calling DropConcreteStores() and DropSymbolicNonAliasingStores())
            FlushUnflushedStores();

            // Build map selects to access the location symbolically
            var groupedIndices = GroupIndices(indices);
            var result         = ExpressionRepresentation;

            for (int index = 0; index < groupedIndices.Count; ++index)
            {
                result = Builder.MapSelect(result, groupedIndices[index].ToArray());
            }
            return(result);
        }
 public virtual Expr MapSelect(Expr map, params Expr[] indices)
 {
     return(UB.MapSelect(map, indices));
 }
        public override Expr VisitNAryExpr(NAryExpr node)
        {
            // Need to duplicate arguments first (doing post order traversal)
            var newArgs = new List <Expr>();

            foreach (var oldExpr in node.Args)
            {
                var newExpr = (Expr)this.Visit(oldExpr);
                newArgs.Add(newExpr);
            }

            // Now can finally duplicate this node now we've done our children

            if (node.Fun is FunctionCall)
            {
                var    FC        = (FunctionCall)node.Fun;
                string bvbuiltin = QKeyValue.FindStringAttribute(FC.Func.Attributes, "bvbuiltin");
                if (bvbuiltin != null)
                {
                    return(HandleBvBuiltIns(FC, bvbuiltin, newArgs));
                }
                else
                {
                    string builtin = QKeyValue.FindStringAttribute(FC.Func.Attributes, "builtin");
                    if (builtin != null)
                    {
                        return(HandleBuiltIns(FC, builtin, newArgs));
                    }
                }
                // Not a builtin so treat as uninterpreted function call
                return(Builder.UFC(FC, newArgs.ToArray()));
            }
            else if (node.Fun is UnaryOperator)
            {
                var U = (UnaryOperator)node.Fun;
                Debug.Assert(newArgs.Count == 1);
                switch (U.Op)
                {
                case UnaryOperator.Opcode.Neg:
                    return(Builder.Neg(newArgs[0]));

                case UnaryOperator.Opcode.Not:
                    return(Builder.Not(newArgs[0]));

                default:
                    throw new NotImplementedException("Unary operator not supported");
                }
            }
            else if (node.Fun is BinaryOperator)
            {
                var B = (BinaryOperator)node.Fun;
                Debug.Assert(newArgs.Count == 2);
                switch (B.Op)
                {
                // Integer or Real number operators
                case BinaryOperator.Opcode.Add:
                    return(Builder.Add(newArgs[0], newArgs[1]));

                case BinaryOperator.Opcode.Sub:
                    return(Builder.Sub(newArgs[0], newArgs[1]));

                case BinaryOperator.Opcode.Mul:
                    return(Builder.Mul(newArgs[0], newArgs[1]));

                case BinaryOperator.Opcode.Div:
                    return(Builder.Div(newArgs[0], newArgs[1]));

                case BinaryOperator.Opcode.Mod:
                    return(Builder.Mod(newArgs[0], newArgs[1]));

                case BinaryOperator.Opcode.RealDiv:
                    return(Builder.RealDiv(newArgs[0], newArgs[1]));

                case BinaryOperator.Opcode.Pow:
                    return(Builder.Pow(newArgs[0], newArgs[1]));

                // Comparision operators
                case BinaryOperator.Opcode.Eq:
                    return(Builder.Eq(newArgs[0], newArgs[1]));

                case BinaryOperator.Opcode.Neq:
                    return(Builder.NotEq(newArgs[0], newArgs[1]));

                case BinaryOperator.Opcode.Gt:
                    return(Builder.Gt(newArgs[0], newArgs[1]));

                case BinaryOperator.Opcode.Ge:
                    return(Builder.Ge(newArgs[0], newArgs[1]));

                case BinaryOperator.Opcode.Lt:
                    return(Builder.Lt(newArgs[0], newArgs[1]));

                case BinaryOperator.Opcode.Le:
                    return(Builder.Le(newArgs[0], newArgs[1]));

                // Bool operators
                case BinaryOperator.Opcode.And:
                    return(Builder.And(newArgs[0], newArgs[1]));

                case BinaryOperator.Opcode.Or:
                    return(Builder.Or(newArgs[0], newArgs[1]));

                case BinaryOperator.Opcode.Imp:
                    return(Builder.Imp(newArgs[0], newArgs[1]));

                case BinaryOperator.Opcode.Iff:
                    return(Builder.Iff(newArgs[0], newArgs[1]));

                case BinaryOperator.Opcode.Subtype:
                    throw new NotImplementedException("SubType binary operator support not implemented");

                default:
                    throw new NotSupportedException("Binary operator" + B.Op.ToString() + "not supported!");
                }
            }
            else if (node.Fun is MapStore)
            {
                Debug.Assert(newArgs.Count >= 3);
                // FIXME: We're probably making too many lists/arrays here
                var map     = newArgs[0];
                var value   = newArgs[newArgs.Count - 1]; // Last argument is value to store
                var indices = new List <Expr>();
                for (int index = 1; index < newArgs.Count - 1; ++index)
                {
                    indices.Add(newArgs[index]);
                }
                Debug.Assert(indices.Count + 2 == newArgs.Count);
                return(Builder.MapStore(map, value, indices.ToArray()));
            }
            else if (node.Fun is MapSelect)
            {
                // FIXME: We're probably making too many lists/arrays here
                Debug.Assert(newArgs.Count >= 2);
                var map     = newArgs[0];
                var indices = new List <Expr>();
                for (int index = 1; index < newArgs.Count; ++index)
                {
                    indices.Add(newArgs[index]);
                }
                Debug.Assert(indices.Count + 1 == newArgs.Count);
                return(Builder.MapSelect(map, indices.ToArray()));
            }
            else if (node.Fun is IfThenElse)
            {
                Debug.Assert(newArgs.Count == 3);
                return(Builder.IfThenElse(newArgs[0], newArgs[1], newArgs[2]));
            }
            else if (node.Fun is TypeCoercion)
            {
                // FIXME: Add support for this in the builder
                // I don't want to put this into the IExprBuilder until I know
                // exactly how this operator works and how it should be type checked
                var immutableTC = new NAryExpr(Token.NoToken, node.Fun, newArgs, /*immutable=*/ true);
                immutableTC.Type = node.Type;
                return(immutableTC);
            }
            else if (node.Fun is ArithmeticCoercion)
            {
                Debug.Assert(newArgs.Count == 1);
                var ac = node.Fun as ArithmeticCoercion;
                return(Builder.ArithmeticCoercion(ac.Coercion, newArgs[0]));
            }

            throw new NotSupportedException("Unsupported NAryExpr");
        }