Exemplo n.º 1
0
 private static void BuildAssignment(Sink sink, Bpl.StmtListBuilder stmtBuilder, List <Bpl.Variable> lvars, List <Bpl.Variable> rvars)
 {
     for (int i = 0; i < lvars.Count; i++)
     {
         Bpl.Variable       lvar  = lvars[i];
         Bpl.Type           ltype = lvar.TypedIdent.Type;
         Bpl.Variable       rvar  = rvars[i];
         Bpl.Type           rtype = rvar.TypedIdent.Type;
         Bpl.IdentifierExpr lexpr = Bpl.Expr.Ident(lvar);
         Bpl.Expr           rexpr = Bpl.Expr.Ident(rvar);
         if (rtype == ltype)
         {
             // do nothing
         }
         else if (ltype == sink.Heap.UnionType)
         {
             rexpr = sink.Heap.ToUnion(Bpl.Token.NoToken, rtype, rexpr, false, stmtBuilder);
         }
         else if (rtype == sink.Heap.UnionType)
         {
             rexpr = sink.Heap.FromUnion(Bpl.Token.NoToken, ltype, rexpr, false);
         }
         else
         {
             System.Diagnostics.Debug.Assert(false);
         }
         stmtBuilder.Add(TranslationHelper.BuildAssignCmd(lexpr, rexpr));
     }
 }
Exemplo n.º 2
0
 /// <summary>
 /// lhs should be a Bpl.IdentifierExpr.
 /// Creates lhs := rhs;
 /// </summary>
 static Bpl.Cmd BplSimplestAssign(Bpl.Expr lhs, Bpl.Expr rhs)
 {
     Contract.Requires(lhs is Bpl.IdentifierExpr);
     return(new Bpl.AssignCmd(rhs.tok,
                              Singleton((Bpl.AssignLhs) new Bpl.SimpleAssignLhs(rhs.tok, (Bpl.IdentifierExpr)lhs)),
                              Singleton(rhs)));
 }
Exemplo n.º 3
0
        public bpl.Expr guardWithExistConst(bpl.Expr expr)
        {
            var existsConst = new bpl.Constant(bpl.Token.NoToken, new bpl.TypedIdent(bpl.Token.NoToken, existsConstName + (numExistsConst++), bpl.Type.Bool));

            existsConsts.Add(existsConst);
            return(bpl.NAryExpr.Imp(new bpl.IdentifierExpr(bpl.Token.NoToken, existsConst), expr));
        }
        public Bpl.Expr FromUnion(Bpl.IToken tok, Bpl.Type boogieType, Bpl.Expr expr, bool isStruct)
        {
            if (boogieType == UnionType || boogieType == RefType)
            {
                return(expr);
            }

            Bpl.Function conversion = null;
            if (boogieType == Bpl.Type.Bool)
            {
                conversion = this.Union2Bool;
            }
            else if (boogieType == Bpl.Type.Int)
            {
                conversion = this.Union2Int;
            }
            else if (boogieType == RealType)
            {
                conversion = this.Union2Real;
            }
            else
            {
                throw new InvalidOperationException(String.Format("Unknown Boogie type: '{0}'", boogieType.ToString()));
            }

            var callExpr = new Bpl.NAryExpr(
                tok,
                new Bpl.FunctionCall(conversion),
                new List <Bpl.Expr>(new Bpl.Expr[] { expr })
                );

            callExpr.Type = boogieType;
            return(callExpr);
        }
 public override void TraverseChildren(IAssertStatement assertStatement)
 {
     Bpl.Expr conditionExpr = ExpressionFor(assertStatement.Condition);
     Bpl.Type conditionType = this.sink.CciTypeToBoogie(assertStatement.Condition.Type);
     if (conditionType == this.sink.Heap.RefType)
     {
         conditionExpr = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Neq, conditionExpr, Bpl.Expr.Ident(this.sink.Heap.NullRef));
     }
     else if (conditionType == Bpl.Type.Int)
     {
         conditionExpr = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Neq, conditionExpr, Bpl.Expr.Literal(0));
     }
     else
     {
         System.Diagnostics.Debug.Assert(conditionType == Bpl.Type.Bool);
     }
     if (this.sink.Options.getMeHere)
     {
         StmtBuilder.Add(new Bpl.AssumeCmd(assertStatement.Token(), conditionExpr));
     }
     else
     {
         StmtBuilder.Add(new Bpl.AssertCmd(assertStatement.Token(), conditionExpr));
     }
 }
 public void RaiseException(Bpl.Expr e)
 {
     Bpl.StmtListBuilder builder = new Bpl.StmtListBuilder();
     RaiseExceptionHelper(builder);
     Bpl.IfCmd ifCmd = new Bpl.IfCmd(Bpl.Token.NoToken, e, builder.Collect(Bpl.Token.NoToken), null, null);
     StmtBuilder.Add(ifCmd);
 }
Exemplo n.º 7
0
 bool IsLit(Bpl.Expr expr)
 {
     if (expr is Bpl.IdentifierExpr ie)
     {
         return(letBoundVariablesWithLitRHS.Contains(ie.Name));
     }
     return(GetLit(expr) != null);
 }
Exemplo n.º 8
0
        /* This function allows you to replace, for example:
         *
         *     Bpl.BoundVariable iVar = new Bpl.BoundVariable(e.tok, new Bpl.TypedIdent(e.tok, "$i", Bpl.Type.Int));
         *     Bpl.IdentifierExpr i = new Bpl.IdentifierExpr(e.tok, iVar);
         *
         * with:
         *
         *     Bpl.Expr i; var iVar = BplBoundVar("$i", Bpl.Type.Int, out i);
         */
        static Bpl.BoundVariable BplBoundVar(string name, Bpl.Type ty, out Bpl.Expr e)
        {
            Contract.Requires(ty != null);
            var v = new Bpl.BoundVariable(ty.tok, new Bpl.TypedIdent(ty.tok, name, ty));

            e = new Bpl.IdentifierExpr(ty.tok, name, ty);
            return(v);
        }
Exemplo n.º 9
0
 public void AddRecordCall(string label, IExpression value, Bpl.Expr valueBpl)
 {
     // valueBpl.Type only gets set in a few simple cases, while
     // sink.CciTypeToBoogie(value.Type.ResolvedType) should always be correct
     // if BCT is working properly. *cross fingers*
     // ~ REDACTED 2016-06-21
     AddRecordCall(label, sink.CciTypeToBoogie(value.Type.ResolvedType), valueBpl);
 }
Exemplo n.º 10
0
 public Bpl.Expr ProperMultiset(Bpl.IToken tok, Bpl.Expr e0, Bpl.Expr e1)
 {
     Contract.Requires(tok != null);
     Contract.Requires(e0 != null);
     Contract.Requires(e1 != null);
     return(Bpl.Expr.Binary(tok, Bpl.BinaryOperator.Opcode.And,
                            FunctionCall(tok, BuiltinFunction.MultiSetSubset, null, e0, e1),
                            Bpl.Expr.Not(FunctionCall(tok, BuiltinFunction.MultiSetEqual, null, e0, e1))));
 }
        public static Bpl.AssignCmd BuildAssignCmd(Bpl.IdentifierExpr lhs, Bpl.Expr rhs)
        {
            List <Bpl.AssignLhs> lhss = new List <Bpl.AssignLhs>();

            lhss.Add(new Bpl.SimpleAssignLhs(lhs.tok, lhs));
            List <Bpl.Expr> rhss = new List <Bpl.Expr>();

            rhss.Add(rhs);
            return(new Bpl.AssignCmd(lhs.tok, lhss, rhss));
        }
Exemplo n.º 12
0
 static Bpl.Expr BplOr(IEnumerable <Bpl.Expr> disjuncts)
 {
     Contract.Requires(disjuncts != null);
     Bpl.Expr eq = Bpl.Expr.False;
     foreach (var d in disjuncts)
     {
         eq = BplOr(eq, d);
     }
     return(eq);
 }
Exemplo n.º 13
0
 static Bpl.Expr BplAnd(IEnumerable <Bpl.Expr> conjuncts)
 {
     Contract.Requires(conjuncts != null);
     Bpl.Expr eq = Bpl.Expr.True;
     foreach (var c in conjuncts)
     {
         eq = BplAnd(eq, c);
     }
     return(eq);
 }
Exemplo n.º 14
0
        public Bpl.Expr ProperSubset(Bpl.IToken tok, Bpl.Expr e0, Bpl.Expr e1)
        {
            Contract.Requires(tok != null);
            Contract.Requires(e0 != null);
            Contract.Requires(e1 != null);
            Contract.Ensures(Contract.Result <Bpl.Expr>() != null);

            return(Bpl.Expr.Binary(tok, Bpl.BinaryOperator.Opcode.And,
                                   FunctionCall(tok, BuiltinFunction.SetSubset, null, e0, e1),
                                   Bpl.Expr.Not(FunctionCall(tok, BuiltinFunction.SetSubset, null, e1, e0))));
        }
Exemplo n.º 15
0
        /// <summary>
        /// Returns the BPL expression that corresponds to the value of the dynamic type
        /// of the object represented by the expression <paramref name="o"/>.
        /// </summary>
        public Bpl.Expr DynamicType(Bpl.Expr o)
        {
            // $DymamicType(o)
            var callDynamicType = new Bpl.NAryExpr(
                o.tok,
                new Bpl.FunctionCall(this.DynamicTypeFunction),
                new List <Bpl.Expr>(new Bpl.Expr[] { o })
                );

            return(callDynamicType);
        }
Exemplo n.º 16
0
 public Bpl.Expr ProperPrefix(Bpl.IToken tok, Bpl.Expr e0, Bpl.Expr e1)
 {
     Contract.Requires(tok != null);
     Contract.Requires(e0 != null);
     Contract.Requires(e1 != null);
     Contract.Ensures(Contract.Result <Bpl.Expr>() != null);
     Bpl.Expr len0 = FunctionCall(tok, BuiltinFunction.SeqLength, null, e0);
     Bpl.Expr len1 = FunctionCall(tok, BuiltinFunction.SeqLength, null, e1);
     return(Bpl.Expr.And(
                Bpl.Expr.Lt(len0, len1),
                FunctionCall(tok, BuiltinFunction.SeqSameUntil, null, e0, e1, len0)));
 }
Exemplo n.º 17
0
        /// <summary>
        /// If the local declaration has an initial value, then generate the
        /// statement "loc := e" from it.
        /// Special case: if "loc" is a struct, then treat it as a call to
        /// the default ctor.
        /// Otherwise ignore it.
        /// </summary>
        public override void TraverseChildren(ILocalDeclarationStatement localDeclarationStatement)
        {
            var initVal  = localDeclarationStatement.InitialValue;
            var typ      = localDeclarationStatement.LocalVariable.Type;
            var isStruct = TranslationHelper.IsStruct(typ);

            if (initVal == null && !isStruct)
            {
                return;
            }
            var boogieLocal     = this.sink.FindOrCreateLocalVariable(localDeclarationStatement.LocalVariable);
            var boogieLocalExpr = Bpl.Expr.Ident(boogieLocal);
            var tok             = localDeclarationStatement.Token();

            Bpl.Expr e = null;


            var structCopy = isStruct && initVal != null && !(initVal is IDefaultValue);

            // then a struct value of type S is being assigned: "lhs := s"
            // model this as the statement "call lhs := S..#copy_ctor(s)" that does the bit-wise copying
            if (isStruct)
            {
                if (!structCopy)
                {
                    var defaultValue = new DefaultValue()
                    {
                        DefaultValueType = typ,
                        Locations        = new List <ILocation>(localDeclarationStatement.Locations),
                        Type             = typ,
                    };
                    var e2 = ExpressionFor(defaultValue);
                    StmtBuilder.Add(Bpl.Cmd.SimpleAssign(tok, boogieLocalExpr, e2));
                }
                else
                /*if (structCopy) */ {
                    var proc = this.sink.FindOrCreateProcedureForStructCopy(typ);
                    e = ExpressionFor(initVal);
                    StmtBuilder.Add(new Bpl.CallCmd(tok, proc.Name, new List <Bpl.Expr> {
                        e,
                    }, new List <Bpl.IdentifierExpr> {
                        boogieLocalExpr,
                    }));
                }
            }
            else
            {
                e = ExpressionFor(initVal);
                AddRecordCall(localDeclarationStatement.LocalVariable.Name.Value, initVal, e);
                StmtBuilder.Add(Bpl.Cmd.SimpleAssign(tok, boogieLocalExpr, e));
            }
            return;
        }
Exemplo n.º 18
0
 private static void BplIfIf(Bpl.IToken tk, bool yes, Bpl.Expr guard, BoogieStmtListBuilder builder, Action <BoogieStmtListBuilder> k)
 {
     if (yes)
     {
         var newBuilder = new BoogieStmtListBuilder(builder.tran);
         k(newBuilder);
         builder.Add(new Bpl.IfCmd(tk, guard, newBuilder.Collect(tk), null, null));
     }
     else
     {
         k(builder);
     }
 }
Exemplo n.º 19
0
 /// <summary>
 /// Returns the (typed) BPL expression that corresponds to the value of the field
 /// <paramref name="f"/> belonging to the object <paramref name="o"/> (which must be non-null).
 /// </summary>
 /// <param name="o">The expression that represents the object to be dereferenced.
 /// </param>
 /// <param name="f">The field that is used to dereference the object <paramref name="o"/>.
 /// </param>
 public override Bpl.Expr ReadHeap(Bpl.Expr /*?*/ o, Bpl.Expr f, AccessType accessType, Bpl.Type unboxType)
 {
     if (accessType == AccessType.Struct || accessType == AccessType.Heap)
     {
         Bpl.IdentifierExpr field = f as Bpl.IdentifierExpr;
         Debug.Assert(field != null);
         return(Bpl.Expr.Select(field, o));
     }
     else
     {
         return(FromUnion(f.tok, unboxType, Bpl.Expr.Select(Bpl.Expr.Select(Bpl.Expr.Ident(ArrayContentsVariable), o), f), false));
     }
 }
Exemplo n.º 20
0
        public static Bpl.AssumeCmd TrAssumeCmd(Bpl.IToken tok, Bpl.Expr expr, Bpl.QKeyValue attributes = null)
        {
            var litArgument = GetLit(expr);

            if (litArgument is Bpl.LiteralExpr literalExpr && literalExpr.asBool)
            {
                // In most cases, we leave any Lit brackets that "expr" may have. In the past, these brackets
                // had always been removed here. Alas, some brittle test cases stopped verifying if we
                // keep "assume Lit(true)" instead of simplifying it to "assume true". Therefore, as a
                // special case, we remove the Lit brackets from the literal "true".
                expr = litArgument;
            }
            return(attributes == null ? new Bpl.AssumeCmd(tok, expr) : new Bpl.AssumeCmd(tok, expr, attributes));
        }
        /// <summary>
        ///
        /// </summary>
        /// <remarks>(mschaef) Works, but still a stub</remarks>
        /// <param name="conditionalStatement"></param>
        public override void TraverseChildren(IConditionalStatement conditionalStatement)
        {
            StatementTraverser  thenTraverser = this.factory.MakeStatementTraverser(this.sink, this.PdbReader, this.contractContext);
            StatementTraverser  elseTraverser = this.factory.MakeStatementTraverser(this.sink, this.PdbReader, this.contractContext);
            ExpressionTraverser condTraverser = this.factory.MakeExpressionTraverser(this.sink, this, this.contractContext);

            if (this.sink.Options.instrumentBranches)
            {
                var tok = conditionalStatement.Token();
                thenTraverser.StmtBuilder.Add(
                    new Bpl.AssumeCmd(tok, Bpl.Expr.True, new Bpl.QKeyValue(Bpl.Token.NoToken, "breadcrumb", new List <object> {
                    Bpl.Expr.Literal(this.sink.UniqueNumberAcrossAllAssemblies)
                }, null))
                    );
                elseTraverser.StmtBuilder.Add(
                    new Bpl.AssumeCmd(tok, Bpl.Expr.True, new Bpl.QKeyValue(Bpl.Token.NoToken, "breadcrumb", new List <object> {
                    Bpl.Expr.Literal(this.sink.UniqueNumberAcrossAllAssemblies)
                }, null))
                    );
            }

            condTraverser.Traverse(conditionalStatement.Condition);
            thenTraverser.Traverse(conditionalStatement.TrueBranch);
            elseTraverser.Traverse(conditionalStatement.FalseBranch);

            Bpl.Expr conditionExpr = condTraverser.TranslatedExpressions.Pop();
            Bpl.Type conditionType = this.sink.CciTypeToBoogie(conditionalStatement.Condition.Type);
            if (conditionType == this.sink.Heap.RefType)
            {
                conditionExpr = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Neq, conditionExpr, Bpl.Expr.Ident(this.sink.Heap.NullRef));
            }
            else if (conditionType == Bpl.Type.Int)
            {
                conditionExpr = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Neq, conditionExpr, Bpl.Expr.Literal(0));
            }
            else
            {
                System.Diagnostics.Debug.Assert(conditionType == Bpl.Type.Bool);
            }

            Bpl.IfCmd ifcmd = new Bpl.IfCmd(conditionalStatement.Token(),
                                            conditionExpr,
                                            thenTraverser.StmtBuilder.Collect(conditionalStatement.TrueBranch.Token()),
                                            null,
                                            elseTraverser.StmtBuilder.Collect(conditionalStatement.FalseBranch.Token())
                                            );

            StmtBuilder.Add(ifcmd);
        }
Exemplo n.º 22
0
 private static void GenerateInAndOutExprs(Bpl.Expr e, List <Bpl.Variable> invars, List <Bpl.Variable> outvars, out List <Bpl.Expr> inExprs, out List <Bpl.IdentifierExpr> outExprs)
 {
     inExprs = new List <Bpl.Expr>();
     inExprs.Add(e);
     for (int i = 1; i < invars.Count; i++)
     {
         Bpl.Variable f = invars[i];
         inExprs.Add(Bpl.Expr.Ident(f));
     }
     outExprs = new List <Bpl.IdentifierExpr>();
     foreach (Bpl.Formal f in outvars)
     {
         outExprs.Add(Bpl.Expr.Ident(f));
     }
 }
Exemplo n.º 23
0
        static Bpl.Expr BplForall(IEnumerable <Bpl.Variable> args_in, Bpl.Expr body)
        {
            Contract.Requires(args_in != null);
            Contract.Requires(body != null);
            Contract.Ensures(Contract.Result <Bpl.Expr>() != null);
            var args = new List <Bpl.Variable>(args_in);

            if (args.Count == 0)
            {
                return(body);
            }
            else
            {
                return(new Bpl.ForallExpr(body.tok, args, body)); // NO_TRIGGER
            }
        }
Exemplo n.º 24
0
 /// <summary>
 /// Returns the BPL command that corresponds to assigning the value <paramref name="value"/>
 /// to the field <paramref name="f"/> of the object <paramref name="o"/> (which should be non-null).
 /// </summary>
 public override void WriteHeap(Bpl.IToken tok, Bpl.Expr /*?*/ o, Bpl.Expr f, Bpl.Expr value, AccessType accessType, Bpl.Type boxType, Bpl.StmtListBuilder builder)
 {
     Debug.Assert(o != null);
     Bpl.Cmd cmd;
     if (accessType == AccessType.Struct || accessType == AccessType.Heap)
     {
         Bpl.IdentifierExpr field = f as Bpl.IdentifierExpr;
         Debug.Assert(field != null);
         cmd = Bpl.Cmd.MapAssign(tok, field, o, value);
     }
     else
     {
         cmd = TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(ArrayContentsVariable), Bpl.Expr.Store(Bpl.Expr.Ident(ArrayContentsVariable), o, Bpl.Expr.Store(Bpl.Expr.Select(Bpl.Expr.Ident(ArrayContentsVariable), o), f, ToUnion(f.tok, boxType, value, false, builder))));
     }
     builder.Add(cmd);
 }
Exemplo n.º 25
0
        Bpl.Expr ArrayLength(Bpl.IToken tok, Bpl.Expr arr, int totalDims, int dim)
        {
            Contract.Requires(tok != null);
            Contract.Requires(arr != null);
            Contract.Requires(1 <= totalDims);
            Contract.Requires(0 <= dim && dim < totalDims);

            string name = "_System." + BuiltIns.ArrayClassName(totalDims) + ".Length";

            if (totalDims != 1)
            {
                name += dim;
            }
            return(new Bpl.NAryExpr(tok, new Bpl.FunctionCall(new Bpl.IdentifierExpr(tok, name, Bpl.Type.Int)), new List <Bpl.Expr> {
                arr
            }));
        }
Exemplo n.º 26
0
        public bool isTidFunc(bpl.Expr expr)
        {
            if (!(expr is bpl.NAryExpr))
            {
                return(false);
            }
            var naryExpr = expr as bpl.NAryExpr;

            if (naryExpr.Fun is bpl.FunctionCall && (naryExpr.Fun as bpl.FunctionCall).Func.Name == tidFunc)
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
Exemplo n.º 27
0
        private static Bpl.Expr GetLit(Bpl.Expr expr)
        {
            if (expr is Bpl.NAryExpr)
            {
                Bpl.NAryExpr app = (Bpl.NAryExpr)expr;
                switch (app.Fun.FunctionName)
                {
                case "LitInt":
                case "LitReal":
                case "Lit":
                    return(app.Args[0]);

                default:
                    break;
                }
            }
            return(null);
        }
        public void GenerateDispatchContinuation(ITryCatchFinallyStatement tryCatchFinallyStatement)
        {
            string continuationLabel = this.sink.FindOrCreateContinuationLabel(tryCatchFinallyStatement);

            Bpl.IfCmd elseIfCmd = new Bpl.IfCmd(Bpl.Token.NoToken, Bpl.Expr.Literal(true),
                                                TranslationHelper.BuildStmtList(new Bpl.GotoCmd(Bpl.Token.NoToken, new List <string>(new string[] { continuationLabel }))), null, null);
            List <string> edges = sink.EscapingEdges(tryCatchFinallyStatement);

            Bpl.IdentifierExpr labelExpr = Bpl.Expr.Ident(this.sink.LabelVariable);
            for (int i = 0; i < edges.Count; i++)
            {
                string      label      = edges[i];
                Bpl.GotoCmd gotoCmd    = new Bpl.GotoCmd(Bpl.Token.NoToken, new List <string>(new string[] { label }));
                Bpl.Expr    targetExpr = Bpl.Expr.Literal(i);
                elseIfCmd = new Bpl.IfCmd(Bpl.Token.NoToken, Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Eq, labelExpr, targetExpr),
                                          TranslationHelper.BuildStmtList(gotoCmd), elseIfCmd, null);
            }
            this.StmtBuilder.Add(elseIfCmd);
        }
Exemplo n.º 29
0
        Bpl.Expr BplIff(Bpl.Expr a, Bpl.Expr b)
        {
            Contract.Requires(a != null);
            Contract.Requires(b != null);
            Contract.Ensures(Contract.Result <Bpl.Expr>() != null);

            if (a == Bpl.Expr.True)
            {
                return(b);
            }
            else if (b == Bpl.Expr.True)
            {
                return(a);
            }
            else
            {
                return(Bpl.Expr.Iff(a, b));
            }
        }
Exemplo n.º 30
0
        static Bpl.Expr BplImp(Bpl.Expr a, Bpl.Expr b)
        {
            Contract.Requires(a != null);
            Contract.Requires(b != null);
            Contract.Ensures(Contract.Result <Bpl.Expr>() != null);

            if (a == Bpl.Expr.True || b == Bpl.Expr.True)
            {
                return(b);
            }
            else if (a == Bpl.Expr.False)
            {
                return(Bpl.Expr.True);
            }
            else
            {
                return(Bpl.Expr.Imp(a, b));
            }
        }
    public override void TraverseChildren(IArrayIndexer arrayIndexer) {

      //if (!IsAtomicInstance(arrayIndexer.IndexedObject)) {
      //  // Simplify the BE so that all nested dereferences and method calls are broken up into separate assignments to locals.
      //  var se = ExpressionSimplifier.Simplify(this.sink, arrayIndexer);
      //  this.Traverse(se);
      //  return;
      //}

      this.Traverse(arrayIndexer.IndexedObject);
      Bpl.Expr arrayExpr = TranslatedExpressions.Pop();

      var be = arrayIndexer.IndexedObject as IBoundExpression;
      if (be != null && be.Instance != null) {
        var l = this.sink.CreateFreshLocal(be.Type);
        var lhs = Bpl.Expr.Ident(l);
        var cmd = Bpl.Cmd.SimpleAssign(arrayIndexer.Token(), lhs, arrayExpr);
        this.StmtTraverser.StmtBuilder.Add(cmd);
        arrayExpr = lhs;
      }

      this.Traverse(arrayIndexer.Indices);
      int count = arrayIndexer.Indices.Count();
      Bpl.Expr[] indexExprs = new Bpl.Expr[count];
      for (int i = count; i > 0; i--) {
        indexExprs[i - 1] = TranslatedExpressions.Pop();
      }
      Bpl.Expr indexExpr;
      if (indexExprs.Length == 1) {
        indexExpr = indexExprs[0];
      }
      else {
        Bpl.Function f = this.sink.FindOrCreateNaryIntFunction(indexExprs.Length);
        indexExpr = new Bpl.NAryExpr(arrayIndexer.Token(), new Bpl.FunctionCall(f), new List<Bpl.Expr>(indexExprs));
      }

      AssertOrAssumeNonNull(arrayIndexer.Token(), arrayExpr);
      this.TranslatedExpressions.Push(this.sink.Heap.ReadHeap(arrayExpr, indexExpr, AccessType.Array, this.sink.CciTypeToBoogie(arrayIndexer.Type)));
    }