Esempio n. 1
0
        private void DirectWrite(IList <Expr> indices, Expr value)
        {
            var groupedIndices = GroupIndices(indices);

            // Build the MapStores bottom up

            /* Example
             * var m:[int][int][int]bool;
             *
             * Assignment m[1][2][3] := false
             * has the following form as mapstore/mapselect expressions
             * m[ 1:= m[1][ 2:= m[1][2][3 := false]]]
             *
             * As a tree this looks like.
             * NOTE:
             * (mapstore <map to base store on> <index>... <value to store>)
             * (mapselect <map to read> <index>...)
             * <index> may repreat several times (this is why groupedIndices was computed)
             *
             *      mapstore
             *     /    |    \
             *   m      1     \
             *                 \
             *                  \
             *                 mapstore
             *                /    |     \
             *               /     2      \
             *           mapselect         \
             *          /     |             \
             *         m      1              \
             *                               mapstore
             *                             /     |   \
             *                     mapselect     3   false
             *                    /    |
             *             mapselect   2
             *            /   |
             *           m    1
             */
            Expr result = value;

            for (int groupIndex = groupedIndices.Count - 1; groupIndex >= 0; --groupIndex)
            {
                // Build the Mapselects necessary for map variables with nested maps
                Expr readFromMap = ExpressionRepresentation;
                for (int mapSelectIndex = 0; mapSelectIndex < groupIndex; ++mapSelectIndex)
                {
                    readFromMap = Builder.MapSelect(readFromMap, groupedIndices[mapSelectIndex].ToArray());
                }
                result = Builder.MapStore(readFromMap, result, groupedIndices[groupIndex].ToArray());
            }

            ExpressionRepresentation = result;
        }
Esempio n. 2
0
 public virtual Expr MapStore(Expr map, Expr value, params Expr[] indices)
 {
     return(UB.MapStore(map, value, indices));
 }
Esempio n. 3
0
        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");
        }