////////////////////////////////////////////////////////////////////////////

        private VCExpr AssembleOpExpression(OpTypesPair opTypes, IEnumerable <VCExpr /*!*/> /*!*/ oldArgs, VariableBindings bindings)
        {
            Contract.Requires(bindings != null);
            Contract.Requires(cce.NonNullElements(oldArgs));
            Contract.Ensures(Contract.Result <VCExpr>() != null);
            // UGLY: the code for tracking polarities should be factored out
            int oldPolarity = Eraser.Polarity;

            Eraser.Polarity = 0;

            List <VCExpr /*!*/> /*!*/ newArgs = new List <VCExpr /*!*/> ();

            // explicit type parameters
            foreach (Type /*!*/ t in opTypes.Types)
            {
                Contract.Assert(newArgs != null);
                newArgs.Add(AxBuilder.Type2Term(t, bindings.TypeVariableBindings));
            }

            // and the actual value parameters
            Function /*!*/ newFun = ((VCExprBoogieFunctionOp)opTypes.Op).Func;
            // ^ we only allow this operator at this point
            int i = opTypes.Types.Count;

            foreach (VCExpr /*!*/ arg in oldArgs)
            {
                Contract.Assert(arg != null);
                newArgs.Add(AxBuilder.Cast(Eraser.Mutate(arg, bindings),
                                           cce.NonNull(newFun.InParams[i]).TypedIdent.Type));
                i = i + 1;
            }

            Eraser.Polarity = oldPolarity;
            return(Gen.Function(opTypes.Op, newArgs));
        }
        private VCExpr EqualTypes(Type t0, Type t1, VariableBindings bindings)
        {
            Contract.Requires(bindings != null);
            Contract.Requires(t1 != null);
            Contract.Requires(t0 != null);
            Contract.Ensures(Contract.Result <VCExpr>() != null);
            if (t0.Equals(t1))
            {
                return(VCExpressionGenerator.True);
            }
            VCExpr /*!*/ t0Expr = AxBuilder.Type2Term(t0, bindings.TypeVariableBindings);

            Contract.Assert(t0Expr != null);
            VCExpr /*!*/ t1Expr = AxBuilder.Type2Term(t1, bindings.TypeVariableBindings);

            Contract.Assert(t1Expr != null);
            return(Gen.Eq(t0Expr, t1Expr));
        }
        private VCExpr HandleQuantifier(VCExprQuantifier node, List <VCExprVar /*!*/> /*!*/ newBoundVars, VariableBindings bindings)
        {
            Contract.Requires(bindings != null);
            Contract.Requires(node != null);
            Contract.Requires(cce.NonNullElements(newBoundVars));
            Contract.Ensures(Contract.Result <VCExpr>() != null);
            List <VCTrigger /*!*/> /*!*/ newTriggers = MutateTriggers(node.Triggers, bindings);

            Contract.Assert(cce.NonNullElements(newTriggers));
            VCExpr /*!*/ newBody = Mutate(node.Body, bindings);

            Contract.Assert(newBody != null);
            newBody = AxBuilder.Cast(newBody, Type.Bool);

            if (newBoundVars.Count == 0) // might happen that no bound variables are left
            {
                return(newBody);
            }
            return(Gen.Quantify(node.Quan, new List <TypeVariable /*!*/>(), newBoundVars,
                                newTriggers, node.Infos, newBody));
        }
        public override VCExpr VisitSubtypeOp(VCExprNAry node, VariableBindings bindings)
        {
            Contract.Requires((bindings != null));
            Contract.Requires((node != null));
            Contract.Ensures(Contract.Result <VCExpr>() != null);
            // UGLY: the code for tracking polarities should be factored out
            int oldPolarity = Eraser.Polarity;

            Eraser.Polarity = 0;

            VCExpr /*!*/ res =
                Gen.Function(VCExpressionGenerator.Subtype3Op,
                             AxBuilder.Type2Term(node[0].Type,
                                                 bindings.TypeVariableBindings),
                             AxBuilder.Cast(Eraser.Mutate(node[0], bindings),
                                            AxBuilder.U),
                             AxBuilder.Cast(Eraser.Mutate(node[1], bindings),
                                            AxBuilder.U));

            Eraser.Polarity = oldPolarity;
            return(res);
        }
        ////////////////////////////////////////////////////////////////////////////

        protected override void GenSelectStoreFunctions(MapType abstractedType, TypeCtorDecl synonym,
                                                        out Function /*!*/ select, out Function /*!*/ store)
        {
            //Contract.Requires(synonym != null);
//Contract.Requires(abstractedType != null);
            Contract.Ensures(Contract.ValueAtReturn(out select) != null);
            Contract.Ensures(Contract.ValueAtReturn(out store) != null);
            Contract.Assert(synonym.Name != null);
            string /*!*/
                baseName     = synonym.Name;
            int typeParamNum = abstractedType.FreeVariables.Count +
                               abstractedType.TypeParameters.Count;

            int arity = typeParamNum + abstractedType.Arguments.Count;

            Type /*!*/[] /*!*/
            selectTypes = new Type /*!*/ [arity + 2];
            Type /*!*/[] /*!*/
            storeTypes = new Type /*!*/ [arity + 3];

            int i = 0;

            // Fill in the free variables and type parameters
            for (; i < typeParamNum; i++)
            {
                selectTypes[i] = AxBuilder.T;
                storeTypes[i]  = AxBuilder.T;
            }

            // Fill in the map type
            selectTypes[i] = AxBuilder.U;
            storeTypes[i]  = AxBuilder.U;
            i++;
            // Fill in the index types
            foreach (Type /*!*/ type in abstractedType.Arguments)
            {
                Contract.Assert(type != null);
                selectTypes[i] = AxBuilder.U;
                storeTypes[i]  = AxBuilder.U;
                i++;
            }

            // Fill in the output type for select function which also happens
            // to be the type of the last argument to the store function
            selectTypes[i] = AxBuilder.U;
            storeTypes[i]  = AxBuilder.U;
            i++;
            // Fill in the map type which is the output of the store function
            storeTypes[i] = AxBuilder.U;
            Contract.Assert(cce.NonNullElements <Type>(selectTypes));
            Contract.Assert(cce.NonNullElements <Type>(storeTypes));

            select = HelperFuns.BoogieFunction(baseName + "Select", selectTypes);
            store  = HelperFuns.BoogieFunction(baseName + "Store", storeTypes);

            if (CommandLineOptions.Clo.UseArrayTheory)
            {
                select.AddAttribute("builtin", "select");
                store.AddAttribute("builtin", "store");
            }
            else
            {
                AxBuilder.AddTypeAxiom(GenMapAxiom0(select, store,
                                                    abstractedType.TypeParameters.Count, abstractedType.FreeVariables.Count));
                AxBuilder.AddTypeAxiom(GenMapAxiom1(select, store,
                                                    abstractedType.TypeParameters.Count, abstractedType.FreeVariables.Count));
            }
        }