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);
        }
        /// <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);
        }
Exemple #3
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);
        }
Exemple #4
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)
        {
            Debug.Assert(o != null);

            Bpl.NAryExpr callRead;
            if (accessType == AccessType.Struct || accessType == AccessType.Heap)
            {
                callRead = new Bpl.NAryExpr(f.tok, new Bpl.FunctionCall(this.Read), new List <Bpl.Expr>(new Bpl.Expr[] { new Bpl.IdentifierExpr(f.tok, this.HeapVariable), o, f }));
            }
            else
            {
                callRead = Bpl.Expr.Select(Bpl.Expr.Select(Bpl.Expr.Ident(ArrayContentsVariable), o), f);
            }

            // wrap it in the right conversion function
            var callExpr = FromUnion(f.tok, unboxType, callRead, false);

            return(callExpr);
        }
Exemple #5
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.IdentifierExpr h;
            Bpl.NAryExpr       callWrite;
            var callConversion = ToUnion(f.tok, boxType, value, false, builder);

            if (accessType == AccessType.Struct || accessType == AccessType.Heap)
            {
                h         = Bpl.Expr.Ident(HeapVariable);
                callWrite = new Bpl.NAryExpr(f.tok, new Bpl.FunctionCall(this.Write), new List <Bpl.Expr>(new Bpl.Expr[] { h, o, f, callConversion }));
            }
            else
            {
                h         = Bpl.Expr.Ident(ArrayContentsVariable);
                callWrite = Bpl.Expr.Store(Bpl.Expr.Ident(ArrayContentsVariable), o, Bpl.Expr.Store(Bpl.Expr.Select(Bpl.Expr.Ident(ArrayContentsVariable), o), f, callConversion));
            }
            builder.Add(Bpl.Cmd.SimpleAssign(f.tok, h, callWrite));
        }
        public Bpl.Expr ToUnion(Bpl.IToken tok, Bpl.Type boogieType, Bpl.Expr expr, bool isStruct, Bpl.StmtListBuilder builder)
        {
            if (boogieType == UnionType || boogieType == RefType)
            {
                return(expr);
            }

            Bpl.Expr callConversion;
            if (boogieType == Bpl.Type.Bool)
            {
                callConversion = new Bpl.NAryExpr(tok, new Bpl.FunctionCall(this.Bool2Union), new List <Bpl.Expr>(new Bpl.Expr[] { expr }));
                builder.Add(
                    new Bpl.AssumeCmd(tok,
                                      Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Eq,
                                                      new Bpl.NAryExpr(tok, new Bpl.FunctionCall(this.Union2Bool), new List <Bpl.Expr>(new Bpl.Expr[] { callConversion })),
                                                      expr)));
            }
            else if (boogieType == Bpl.Type.Int)
            {
                callConversion = new Bpl.NAryExpr(tok, new Bpl.FunctionCall(this.Int2Union), new List <Bpl.Expr>(new Bpl.Expr[] { expr }));
                builder.Add(
                    new Bpl.AssumeCmd(tok,
                                      Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Eq,
                                                      new Bpl.NAryExpr(tok, new Bpl.FunctionCall(this.Union2Int), new List <Bpl.Expr>(new Bpl.Expr[] { callConversion })),
                                                      expr)));
            }
            else if (boogieType == RealType)
            {
                callConversion = new Bpl.NAryExpr(tok, new Bpl.FunctionCall(this.Real2Union), new List <Bpl.Expr>(new Bpl.Expr[] { expr }));
                builder.Add(
                    new Bpl.AssumeCmd(tok,
                                      Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Eq,
                                                      new Bpl.NAryExpr(tok, new Bpl.FunctionCall(this.Union2Real), new List <Bpl.Expr>(new Bpl.Expr[] { callConversion })),
                                                      expr)));
            }
            else
            {
                throw new InvalidOperationException(String.Format("Unknown Boogie type: '{0}'", boogieType.ToString()));
            }
            return(callConversion);
        }
    private void TraverseBitwiseAndRightOperandAndDoOperation(IExpression expression) {
      Contract.Assume(expression is IBitwiseAnd);
      var bitwiseAnd = (IBitwiseAnd)expression;

      this.Traverse(bitwiseAnd.RightOperand);

      Bpl.Expr rexp = TranslatedExpressions.Pop();
      Bpl.Expr lexp = TranslatedExpressions.Pop();
      Bpl.Expr e;
      if (bitwiseAnd.Type.TypeCode == PrimitiveTypeCode.Boolean) {
        e = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.And, lexp, rexp);
      }
      else {
        if (lexp.Type != Bpl.Type.Int || rexp.Type != Bpl.Type.Int)
          throw new TranslationException("BitwiseAnd called in a non-boolean context, but at least one argument is not an integer!");
        e = new Bpl.NAryExpr(
          bitwiseAnd.Token(),
          new Bpl.FunctionCall(this.sink.Heap.BitwiseAnd),
          new List<Bpl.Expr>(new Bpl.Expr[] {lexp, rexp})
          );
      }
      TranslatedExpressions.Push(e);
    }
 public override void TraverseChildren(IUnaryNegation unaryNegation)
 {
   base.TraverseChildren(unaryNegation);
   Bpl.Expr exp = TranslatedExpressions.Pop();
   Bpl.Expr e, zero, realZero;
   zero = Bpl.Expr.Literal(0);
   realZero = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(this.sink.Heap.Int2Real), new List<Bpl.Expr>(new Bpl.Expr[] {zero}));
   switch (unaryNegation.Type.TypeCode) {
     case PrimitiveTypeCode.Float32:
     case PrimitiveTypeCode.Float64:
       e = new Bpl.NAryExpr(
         unaryNegation.Token(),
         new Bpl.FunctionCall(this.sink.Heap.RealMinus),
         new List<Bpl.Expr>(new Bpl.Expr[] {realZero, exp})
         );
       break;
     default:
       e = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Sub, Bpl.Expr.Literal(0), exp);
       break;
   }
   TranslatedExpressions.Push(e);
 }
    public override void TraverseChildren(IConversion conversion) {
      var tok = conversion.ValueToConvert.Token();
      this.Traverse(conversion.ValueToConvert);
      var boogieTypeOfValue = this.sink.CciTypeToBoogie(conversion.ValueToConvert.Type);
      var boogieTypeToBeConvertedTo = this.sink.CciTypeToBoogie(conversion.TypeAfterConversion);
      if (boogieTypeOfValue == boogieTypeToBeConvertedTo && !TranslationHelper.IsStruct(conversion.ValueToConvert.Type)
        && !TranslationHelper.IsStruct(conversion.TypeAfterConversion)) {
        // then this conversion is a nop, just ignore it
        return;
      }
      var nameOfTypeToConvert = TypeHelper.GetTypeName(conversion.ValueToConvert.Type);
      var nameOfTypeToBeConvertedTo = TypeHelper.GetTypeName(conversion.TypeAfterConversion);
      var msg = String.Format("Can't convert '{0}' to '{1}'", nameOfTypeToConvert, nameOfTypeToBeConvertedTo);

      var exp = TranslatedExpressions.Pop();

      if (boogieTypeOfValue == this.sink.Heap.UnionType && boogieTypeToBeConvertedTo != this.sink.Heap.RefType) {
        var e = this.sink.Heap.FromUnion(tok, boogieTypeToBeConvertedTo, exp, false);
        TranslatedExpressions.Push(e);
        return;
      }
      if (boogieTypeToBeConvertedTo == this.sink.Heap.UnionType) {
        Bpl.Expr e;
        if (boogieTypeOfValue == this.sink.Heap.RefType)
          e = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(this.sink.Heap.Unbox2Union), new List<Bpl.Expr>(new Bpl.Expr[] {exp}));
        else
          e = this.sink.Heap.ToUnion(tok, boogieTypeOfValue, exp, false, StmtTraverser.StmtBuilder);
        TranslatedExpressions.Push(e);
        return;
      }

      if (boogieTypeToBeConvertedTo == this.sink.Heap.RefType &&
        TranslationHelper.IsStruct(conversion.TypeAfterConversion) &&
        boogieTypeOfValue == this.sink.Heap.RefType) {
        // REVIEW: This also applies to conversions from one struct type to another!
        TranslatedExpressions.Push(exp);
        return;
      }

      if (boogieTypeToBeConvertedTo == Bpl.Type.Bool) {
        Bpl.Expr expr;
        if (boogieTypeOfValue == Bpl.Type.Int) {
          expr = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Neq, exp, Bpl.Expr.Literal(0));
        }
        else if (boogieTypeOfValue == this.sink.Heap.RefType) {
          expr = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(this.sink.Heap.Unbox2Bool), new List<Bpl.Expr>(new Bpl.Expr[] {exp}));
        }
        else if (boogieTypeOfValue == this.sink.Heap.RealType) {
          expr = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(this.sink.Heap.Real2Int), new List<Bpl.Expr>(new Bpl.Expr[] {exp}));
          expr = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Neq, expr, Bpl.Expr.Literal(0));
        }
        else if (boogieTypeOfValue == this.sink.Heap.UnionType) {
          expr = this.sink.Heap.FromUnion(tok, Bpl.Type.Bool, exp, false);
        }
        else {
          throw new NotImplementedException(msg);
        }
        TranslatedExpressions.Push(expr);
        return;
      }

      if (boogieTypeToBeConvertedTo == Bpl.Type.Int) {
        Bpl.Expr expr;
        if (boogieTypeOfValue == Bpl.Type.Bool) {
          expr = new Bpl.NAryExpr(tok, new Bpl.IfThenElse(tok), new List<Bpl.Expr>(new Bpl.Expr[] {exp, Bpl.Expr.Literal(1), Bpl.Expr.Literal(0)}));
        }
        else if (boogieTypeOfValue == this.sink.Heap.RefType) {
          expr = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(this.sink.Heap.Unbox2Int), new List<Bpl.Expr>(new Bpl.Expr[] {exp}));
        }
        else if (boogieTypeOfValue == this.sink.Heap.RealType) {
          expr = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(this.sink.Heap.Real2Int), new List<Bpl.Expr>(new Bpl.Expr[] {exp}));
        }
        else if (boogieTypeOfValue == this.sink.Heap.UnionType) {
          expr = this.sink.Heap.FromUnion(Bpl.Token.NoToken, Bpl.Type.Int, exp, false);
        }
        else {
          throw new NotImplementedException(msg);
        }
        TranslatedExpressions.Push(expr);
        return;
      }

      if (boogieTypeToBeConvertedTo == this.sink.Heap.RefType) {
        // var a = BoxFromXXX(exp);
        Bpl.Variable a = this.sink.CreateFreshLocal(conversion.TypeAfterConversion);
        Bpl.Procedure boxOperator;
        if (boogieTypeOfValue == Bpl.Type.Bool)
          boxOperator = this.sink.Heap.BoxFromBool;
        else if (boogieTypeOfValue == Bpl.Type.Int)
          boxOperator = this.sink.Heap.BoxFromInt;
        else if (boogieTypeOfValue == this.sink.Heap.RealType)
          boxOperator = this.sink.Heap.BoxFromReal;
        else if (TranslationHelper.IsStruct(conversion.ValueToConvert.Type)) {
          // Boxing a struct implicitly makes a copy of the struct
          var typeOfValue = conversion.ValueToConvert.Type;
          var proc = this.sink.FindOrCreateProcedureForStructCopy(typeOfValue);
          var bplLocal = Bpl.Expr.Ident(this.sink.CreateFreshLocal(typeOfValue));
          var cmd = new Bpl.CallCmd(tok, proc.Name, new List<Bpl.Expr> { exp, }, new List<Bpl.IdentifierExpr> { bplLocal, });
          this.StmtTraverser.StmtBuilder.Add(cmd);
          TranslatedExpressions.Push(bplLocal);
          return;
        }  else {
          if (boogieTypeOfValue != this.sink.Heap.UnionType)
            throw new NotImplementedException(msg);
          boxOperator = this.sink.Heap.BoxFromUnion;
        }
        var name = boxOperator.Name;

        this.StmtTraverser.StmtBuilder.Add(new Bpl.CallCmd(Bpl.Token.NoToken, name, new List<Bpl.Expr>(new Bpl.Expr[] {exp}), new List<Bpl.IdentifierExpr>(new Bpl.IdentifierExpr[] {Bpl.Expr.Ident(a)})));
        TranslatedExpressions.Push(Bpl.Expr.Ident(a));
        return;
      }

      if (boogieTypeToBeConvertedTo == this.sink.Heap.RealType) {
        Bpl.Expr expr;
        if (boogieTypeOfValue == Bpl.Type.Bool) {
          expr = new Bpl.NAryExpr(tok, new Bpl.IfThenElse(tok), new List<Bpl.Expr>(new Bpl.Expr[] {exp, Bpl.Expr.Literal(1), Bpl.Expr.Literal(0)}));
          expr = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(this.sink.Heap.Int2Real), new List<Bpl.Expr>(new Bpl.Expr[] {expr}));
        }
        else if (boogieTypeOfValue == Bpl.Type.Int) {
          expr = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(this.sink.Heap.Int2Real), new List<Bpl.Expr>(new Bpl.Expr[] {exp}));
        }
        else if (boogieTypeOfValue == this.sink.Heap.RefType) {
            expr = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(this.sink.Heap.Unbox2Real), new List<Bpl.Expr>(new Bpl.Expr[] { exp }));
        }
        else if (boogieTypeOfValue == this.sink.Heap.UnionType) {
          expr = this.sink.Heap.FromUnion(tok, this.sink.Heap.RealType, exp, false);
        }
        else {
          throw new NotImplementedException(msg);
        }
        TranslatedExpressions.Push(expr);
        return;
      }
      
      //if (boogieTypeToBeConvertedTo == this.sink.Heap.UnionType) {
      //  Bpl.Function func;
      //  if (boogieTypeOfValue == Bpl.Type.Bool) {
      //    func = this.sink.Heap.Bool2Union;
      //  }
      //  else if (boogieTypeOfValue == Bpl.Type.Int) {
      //    func = this.sink.Heap.Int2Union;
      //  }
      //  else if (boogieTypeOfValue == this.sink.Heap.RefType) {
      //    func = this.sink.Heap.Ref2Union;
      //  }
      //  else if (boogieTypeOfValue == this.sink.Heap.RealType) {
      //    func = this.sink.Heap.Real2Union;
      //  }
      //  else {
      //    throw new NotImplementedException(msg);
      //  }
      //  var boxExpr = new Bpl.NAryExpr(conversion.Token(), new Bpl.FunctionCall(func), new List<Bpl.Expr>(exp));
      //  TranslatedExpressions.Push(boxExpr);
      //  return;
      //}
    }
 public override void TraverseChildren(ICastIfPossible castIfPossible) {
   base.Traverse(castIfPossible.ValueToCast);
   var exp = TranslatedExpressions.Pop();
   var e = this.sink.FindOrCreateTypeReferenceInCodeContext(castIfPossible.TargetType);
   var callAs = new Bpl.NAryExpr(
     castIfPossible.Token(),
     new Bpl.FunctionCall(this.sink.Heap.AsFunction),
     new List<Bpl.Expr>(new Bpl.Expr[] {exp, e})
     );
   TranslatedExpressions.Push(callAs);
   return;
 }
    public override void TraverseChildren(ILessThanOrEqual lessEqual)
    {
      base.TraverseChildren(lessEqual);
      Bpl.Expr rexp = TranslatedExpressions.Pop();
      Bpl.Expr lexp = TranslatedExpressions.Pop();

      Bpl.Expr e;
      switch (lessEqual.LeftOperand.Type.TypeCode) {
        case PrimitiveTypeCode.Float32:
        case PrimitiveTypeCode.Float64:
          e = new Bpl.NAryExpr(
            lessEqual.Token(),
            new Bpl.FunctionCall(this.sink.Heap.RealLessThanOrEqual),
            new List<Bpl.Expr>(new Bpl.Expr[] {lexp, rexp})
            );
          break;
        default:
          e = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Le, lexp, rexp);
          break;
      }

      TranslatedExpressions.Push(e);
    }
    private void TraverseExclusiveOrRightOperandAndDoOperation(IExpression expression) {
      Contract.Assume(expression is IExclusiveOr);
      var exclusiveOr = (IExclusiveOr)expression;
      this.Traverse(exclusiveOr.RightOperand);

      Bpl.Expr rexp = TranslatedExpressions.Pop();
      Bpl.Expr lexp = TranslatedExpressions.Pop();
      var e = new Bpl.NAryExpr(
        exclusiveOr.Token(),
        new Bpl.FunctionCall(this.sink.Heap.BitwiseExclusiveOr),
        new List<Bpl.Expr>(new Bpl.Expr[] {lexp, rexp})
        );
      TranslatedExpressions.Push(e);
    }
    /// <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) {
      Debug.Assert(o != null);

      Bpl.NAryExpr callRead;
      if (accessType == AccessType.Struct || accessType == AccessType.Heap)
        callRead = new Bpl.NAryExpr(f.tok, new Bpl.FunctionCall(this.Read), new List<Bpl.Expr>(new Bpl.Expr[] {new Bpl.IdentifierExpr(f.tok, this.HeapVariable), o, f}));
      else
        callRead = Bpl.Expr.Select(Bpl.Expr.Select(Bpl.Expr.Ident(ArrayContentsVariable), o), f);

      // wrap it in the right conversion function
      var callExpr = FromUnion(f.tok, unboxType, callRead, false);
      return callExpr;
    }
    private void TraverseBitwiseOrRightOperandAndDoOperation(IExpression expression) {
      Contract.Assume(expression is IBitwiseOr);
      var bitwiseOr = (IBitwiseOr)expression;
      this.Traverse(bitwiseOr.RightOperand);

      Bpl.Expr rexp = TranslatedExpressions.Pop();
      Bpl.Expr lexp = TranslatedExpressions.Pop();
      Bpl.Expr e;
      if (bitwiseOr.Type.TypeCode == PrimitiveTypeCode.Boolean) {
        e = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Or, lexp, rexp);
      }
      else {
        e = new Bpl.NAryExpr(
          bitwiseOr.Token(),
          new Bpl.FunctionCall(this.sink.Heap.BitwiseOr),
          new List<Bpl.Expr>(new Bpl.Expr[] {lexp, rexp})
          );
      }
      TranslatedExpressions.Push(e);
    }
    /// <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.IdentifierExpr h;
      Bpl.NAryExpr callWrite;
      var callConversion = ToUnion(f.tok, boxType, value, false, builder);

      if (accessType == AccessType.Struct || accessType == AccessType.Heap) {
        h = Bpl.Expr.Ident(HeapVariable);
        callWrite = new Bpl.NAryExpr(f.tok, new Bpl.FunctionCall(this.Write), new List<Bpl.Expr>(new Bpl.Expr[] {h, o, f, callConversion}));
      }
      else {
        h = Bpl.Expr.Ident(ArrayContentsVariable);
        callWrite = Bpl.Expr.Store(Bpl.Expr.Ident(ArrayContentsVariable), o, Bpl.Expr.Store(Bpl.Expr.Select(Bpl.Expr.Ident(ArrayContentsVariable), o), f, callConversion));
      }
      builder.Add(Bpl.Cmd.SimpleAssign(f.tok, h, callWrite));
    }
    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)));
    }
        public override void TraverseChildren(ITryCatchFinallyStatement tryCatchFinallyStatement)
        {
            if (this.sink.Options.modelExceptions == 0)
            {
                this.Traverse(tryCatchFinallyStatement.TryBody);
                if (tryCatchFinallyStatement.FinallyBody != null)
                {
                    this.Traverse(tryCatchFinallyStatement.FinallyBody);
                }
                return;
            }

            this.sink.nestedTryCatchFinallyStatements.Add(new Tuple <ITryCatchFinallyStatement, Sink.TryCatchFinallyContext>(tryCatchFinallyStatement, Sink.TryCatchFinallyContext.InTry));
            this.Traverse(tryCatchFinallyStatement.TryBody);
            StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.LabelVariable), Bpl.Expr.Literal(-1)));
            StmtBuilder.Add(new Bpl.GotoCmd(Bpl.Token.NoToken, new List <string>(new string[] { this.sink.FindOrCreateFinallyLabel(tryCatchFinallyStatement) })));
            this.sink.nestedTryCatchFinallyStatements.RemoveAt(this.sink.nestedTryCatchFinallyStatements.Count - 1);

            StmtBuilder.AddLabelCmd(this.sink.FindOrCreateCatchLabel(tryCatchFinallyStatement));
            StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.LocalExcVariable), Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable)));
            StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable), Bpl.Expr.Ident(this.sink.Heap.NullRef)));
            List <Bpl.StmtList> catchStatements = new List <Bpl.StmtList>();
            List <Bpl.Expr>     typeReferences  = new List <Bpl.Expr>();

            this.sink.nestedTryCatchFinallyStatements.Add(new Tuple <ITryCatchFinallyStatement, Sink.TryCatchFinallyContext>(tryCatchFinallyStatement, Sink.TryCatchFinallyContext.InCatch));
            foreach (ICatchClause catchClause in tryCatchFinallyStatement.CatchClauses)
            {
                typeReferences.Insert(0, this.sink.FindOrCreateTypeReference(catchClause.ExceptionType, true));
                StatementTraverser catchTraverser = this.factory.MakeStatementTraverser(this.sink, this.PdbReader, this.contractContext);
                if (catchClause.ExceptionContainer != Dummy.LocalVariable)
                {
                    Bpl.Variable catchClauseVariable = this.sink.FindOrCreateLocalVariable(catchClause.ExceptionContainer);
                    catchTraverser.StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(catchClauseVariable), Bpl.Expr.Ident(this.sink.LocalExcVariable)));
                }
                catchTraverser.Traverse(catchClause.Body);
                catchTraverser.StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.LabelVariable), Bpl.Expr.Literal(-1)));
                catchTraverser.StmtBuilder.Add(new Bpl.GotoCmd(Bpl.Token.NoToken, new List <string>(new string[] { this.sink.FindOrCreateFinallyLabel(tryCatchFinallyStatement) })));
                catchStatements.Insert(0, catchTraverser.StmtBuilder.Collect(catchClause.Token()));
            }
            Bpl.IfCmd elseIfCmd        = new Bpl.IfCmd(Bpl.Token.NoToken, Bpl.Expr.Literal(false), TranslationHelper.BuildStmtList(new Bpl.ReturnCmd(Bpl.Token.NoToken)), null, null);
            Bpl.Expr  dynTypeOfOperand = this.sink.Heap.DynamicType(Bpl.Expr.Ident(this.sink.LocalExcVariable));
            for (int i = 0; i < catchStatements.Count; i++)
            {
                Bpl.Expr expr = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(this.sink.Heap.Subtype), new List <Bpl.Expr>(new Bpl.Expr[] { dynTypeOfOperand, typeReferences[i] }));
                elseIfCmd = new Bpl.IfCmd(Bpl.Token.NoToken, expr, catchStatements[i], elseIfCmd, null);
            }
            this.StmtBuilder.Add(elseIfCmd);
            this.StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable), Bpl.Expr.Ident(this.sink.LocalExcVariable)));
            RaiseException();
            this.sink.nestedTryCatchFinallyStatements.RemoveAt(this.sink.nestedTryCatchFinallyStatements.Count - 1);

            this.StmtBuilder.AddLabelCmd(this.sink.FindOrCreateFinallyLabel(tryCatchFinallyStatement));
            if (tryCatchFinallyStatement.FinallyBody != null)
            {
                this.sink.nestedTryCatchFinallyStatements.Add(new Tuple <ITryCatchFinallyStatement, Sink.TryCatchFinallyContext>(tryCatchFinallyStatement, Sink.TryCatchFinallyContext.InFinally));
                Bpl.Variable savedExcVariable   = this.sink.CreateFreshLocal(this.sink.Heap.RefType);
                Bpl.Variable savedLabelVariable = this.sink.CreateFreshLocal(Bpl.Type.Int);
                StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(savedExcVariable), Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable)));
                StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(savedLabelVariable), Bpl.Expr.Ident(this.sink.LabelVariable)));
                this.Traverse(tryCatchFinallyStatement.FinallyBody);
                StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable), Bpl.Expr.Ident(savedExcVariable)));
                StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.LabelVariable), Bpl.Expr.Ident(savedLabelVariable)));
                this.sink.nestedTryCatchFinallyStatements.RemoveAt(this.sink.nestedTryCatchFinallyStatements.Count - 1);
            }
            GenerateDispatchContinuation(tryCatchFinallyStatement);
            StmtBuilder.AddLabelCmd(this.sink.FindOrCreateContinuationLabel(tryCatchFinallyStatement));
            Bpl.Expr raiseExpr = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Neq, Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable), Bpl.Expr.Ident(this.sink.Heap.NullRef));
            RaiseException(raiseExpr);
        }
    private void TraverseMultiplicationRightOperandAndDoOperation(IExpression expression) {
      Contract.Assume(expression is IMultiplication);
      var multiplication = (IMultiplication)expression;
      this.Traverse(multiplication.RightOperand);

      Bpl.Expr rexp = TranslatedExpressions.Pop();
      Bpl.Expr lexp = TranslatedExpressions.Pop();
      Bpl.Expr e;
      switch (multiplication.Type.TypeCode) {
        case PrimitiveTypeCode.Float32:
        case PrimitiveTypeCode.Float64:
          e = new Bpl.NAryExpr(
            multiplication.Token(),
            new Bpl.FunctionCall(this.sink.Heap.RealTimes),
            new List<Bpl.Expr>(new Bpl.Expr[] {lexp, rexp})
            );
          break;
        default:
          e = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Mul, lexp, rexp);
          break;
      }
      TranslatedExpressions.Push(e);
    }
    public Bpl.Expr ToUnion(Bpl.IToken tok, Bpl.Type boogieType, Bpl.Expr expr, bool isStruct, Bpl.StmtListBuilder builder)
    {
        if (boogieType == UnionType || boogieType == RefType)
            return expr;

        Bpl.Expr callConversion;
        if (boogieType == Bpl.Type.Bool)
        {
            callConversion = new Bpl.NAryExpr(tok, new Bpl.FunctionCall(this.Bool2Union), new List<Bpl.Expr>(new Bpl.Expr[] {expr}));
            builder.Add(
                new Bpl.AssumeCmd(tok,
                Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Eq,
                                new Bpl.NAryExpr(tok, new Bpl.FunctionCall(this.Union2Bool), new List<Bpl.Expr>(new Bpl.Expr[] { callConversion })),
                                expr)));
        }
        else if (boogieType == Bpl.Type.Int)
        {
            callConversion = new Bpl.NAryExpr(tok, new Bpl.FunctionCall(this.Int2Union), new List<Bpl.Expr>(new Bpl.Expr[] { expr }));
            builder.Add(
                new Bpl.AssumeCmd(tok,
                Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Eq,
                                new Bpl.NAryExpr(tok, new Bpl.FunctionCall(this.Union2Int), new List<Bpl.Expr>(new Bpl.Expr[] {callConversion})),
                                expr)));
        }
        else if (boogieType == RealType)
        {
            callConversion = new Bpl.NAryExpr(tok, new Bpl.FunctionCall(this.Real2Union), new List<Bpl.Expr>(new Bpl.Expr[] { expr }));
            builder.Add(
                new Bpl.AssumeCmd(tok,
                Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Eq,
                                new Bpl.NAryExpr(tok, new Bpl.FunctionCall(this.Union2Real), new List<Bpl.Expr>(new Bpl.Expr[] { callConversion })),
                                expr)));
        }
        else
        {
            throw new InvalidOperationException(String.Format("Unknown Boogie type: '{0}'", boogieType.ToString()));
        }
        return callConversion;
    }
    private void TraverseLeftShiftRightOperandAndDoOperation(IExpression expression) {
      Contract.Assume(expression is ILeftShift);
      var leftShift = (ILeftShift)expression;
      this.Traverse(leftShift.RightOperand);

      Bpl.Expr rexp = TranslatedExpressions.Pop();
      Bpl.Expr lexp = TranslatedExpressions.Pop();
      Bpl.Expr e = new Bpl.NAryExpr(
            leftShift.Token(),
            new Bpl.FunctionCall(this.sink.Heap.LeftShift),
            new List<Bpl.Expr>(new Bpl.Expr[] {lexp, rexp})
            );
      TranslatedExpressions.Push(e);
    }
    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(ICheckIfInstance checkIfInstance) {
   var e = this.sink.FindOrCreateTypeReferenceInCodeContext(checkIfInstance.TypeToCheck);
   //var callTypeOf = new Bpl.NAryExpr(
   //  checkIfInstance.Token(),
   //  new Bpl.FunctionCall(this.sink.Heap.TypeOfFunction),
   //  new List<Bpl.Expr>(new Bpl.IdentifierExpr(checkIfInstance.Token(), v))
   //  );
   base.Traverse(checkIfInstance.Operand);
   var exp = TranslatedExpressions.Pop();
   var dynTypeOfOperand = this.sink.Heap.DynamicType(exp);
   //var subtype = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Subtype, dynTypeOfOperand, e);
   var subtype = new Bpl.NAryExpr(
     Bpl.Token.NoToken,
     new Bpl.FunctionCall(this.sink.Heap.Subtype),
     new List<Bpl.Expr>(new Bpl.Expr[] {dynTypeOfOperand, e})
     );
   var notnull = Bpl.Expr.Neq(exp, Bpl.Expr.Ident(this.sink.Heap.NullRef));
   var and = Bpl.Expr.And(notnull, subtype);
   TranslatedExpressions.Push(and);
   return;
 }
 /// <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;
 }
 public override void TraverseChildren(IOnesComplement onesComplement) {
   base.TraverseChildren(onesComplement);
   var exp = TranslatedExpressions.Pop();
   var e = new Bpl.NAryExpr(
     onesComplement.Token(),
     new Bpl.FunctionCall(this.sink.Heap.BitwiseNegation),
     new List<Bpl.Expr>(new Bpl.Expr[] {exp})
     );
   TranslatedExpressions.Push(e);
 }
    private void TranslateDelegateCreation(IMethodReference methodToCall, ITypeReference type, IExpression creationAST)
    {
      Bpl.IToken cloc = creationAST.Token();
      var a = this.sink.CreateFreshLocal(creationAST.Type);

      ITypeDefinition unspecializedType = Microsoft.Cci.MutableContracts.ContractHelper.Unspecialized(type.ResolvedType).ResolvedType;
      IMethodDefinition unspecializedMethod = ResolveUnspecializedMethodOrThrow(methodToCall);
      sink.AddDelegate(unspecializedType, unspecializedMethod);
      Bpl.Constant constant = sink.FindOrCreateDelegateMethodConstant(unspecializedMethod);
      Bpl.Expr methodExpr = Bpl.Expr.Ident(constant);
      Bpl.Expr instanceExpr = TranslatedExpressions.Pop();

      List<Bpl.Expr> typeParameterExprs = new List<Bpl.Expr>();

      if (unspecializedMethod.IsStatic) {
        List<ITypeReference> consolidatedTypeArguments = new List<ITypeReference>();
        Sink.GetConsolidatedTypeArguments(consolidatedTypeArguments, methodToCall.ContainingType);
        foreach (ITypeReference typeReference in consolidatedTypeArguments) {
          typeParameterExprs.Add(this.sink.FindOrCreateTypeReferenceInCodeContext(typeReference));
        }
      }
      IGenericMethodInstanceReference methodInstanceReference = methodToCall as IGenericMethodInstanceReference;
      if (methodInstanceReference != null) {
        foreach (ITypeReference typeReference in methodInstanceReference.GenericArguments) {
          typeParameterExprs.Add(this.sink.FindOrCreateTypeReferenceInCodeContext(typeReference));
        }
      }
      Bpl.Expr typeParameterExpr =
        new Bpl.NAryExpr(Bpl.Token.NoToken,
                         new Bpl.FunctionCall(this.sink.FindOrCreateNaryTypeFunction(typeParameterExprs.Count)),
                         typeParameterExprs);
      this.StmtTraverser.StmtBuilder.Add(
        new Bpl.CallCmd(cloc, this.sink.DelegateCreate(unspecializedType),
                        new List<Bpl.Expr>(new Bpl.Expr[] {methodExpr, instanceExpr, typeParameterExpr}), 
                        new List<Bpl.IdentifierExpr>(new Bpl.IdentifierExpr[] {Bpl.Expr.Ident(a)})));
      TranslatedExpressions.Push(Bpl.Expr.Ident(a));
    }
    /// <summary>
    /// 
    /// </summary>
    /// <param name="methodCall"></param>
    /// <remarks>Stub, This one really needs comments!</remarks>
    public override void TraverseChildren(IMethodCall methodCall) {
      var resolvedMethod = ResolveUnspecializedMethodOrThrow(methodCall.MethodToCall);

      Bpl.IToken methodCallToken = methodCall.Token();

      if (this.sink.Options.getMeHere) {
        // TODO: Get a method reference so this isn't a string comparison?
        var methodName = MemberHelper.GetMethodSignature(methodCall.MethodToCall, NameFormattingOptions.None);
        if (methodName.Equals("GetMeHere.GetMeHere.Assert")) {
          // for now, just translate it as "assert e"
          this.Traverse(methodCall.Arguments.First());
          Bpl.Expr e = this.TranslatedExpressions.Pop();
          this.StmtTraverser.StmtBuilder.Add(new Bpl.AssertCmd(methodCallToken, e));
          return;
        }
      }

      // Handle type equality specially when it is testing against a constant, i.e., o.GetType() == typeof(T)
      if (IsOperator(resolvedMethod) && !IsConversionOperator(resolvedMethod) && 
        TypeHelper.TypesAreEquivalent(resolvedMethod.ContainingType, this.sink.host.PlatformType.SystemType)) {
        // REVIEW: Assume the only operators on System.Type are == and !=
        var typeToTest = methodCall.Arguments.ElementAtOrDefault(0) as ITypeOf;
        IMethodCall callToGetType;
        if (typeToTest == null) {
          typeToTest = methodCall.Arguments.ElementAtOrDefault(1) as ITypeOf;
          callToGetType = methodCall.Arguments.ElementAtOrDefault(0) as IMethodCall;
        } else {
          callToGetType = methodCall.Arguments.ElementAtOrDefault(1) as IMethodCall;
        }
        if (typeToTest != null && callToGetType != null &&
          TypeHelper.TypesAreEquivalent(callToGetType.MethodToCall.ContainingType, this.sink.host.PlatformType.SystemObject) &&
          MemberHelper.GetMethodSignature(callToGetType.MethodToCall).Equals("System.Object.GetType")) {

          IExpression objectToTest = callToGetType.ThisArgument;

          // generate: $TypeConstructor($DynamicType(o)) == TypeConstructorId
          var typeConstructorId = this.sink.FindOrDefineType(typeToTest.TypeToGet.ResolvedType).ConstructorId;
          Contract.Assume(typeConstructorId != null);

          this.Traverse(objectToTest);
          var e = this.TranslatedExpressions.Pop();

          var exprs = new List<Bpl.Expr>(new Bpl.Expr[] {this.sink.Heap.DynamicType(e)});
          Bpl.Expr typeTestExpression = 
              Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Eq, 
                              new Bpl.NAryExpr(methodCallToken, new Bpl.FunctionCall(sink.Heap.TypeConstructorFunction), exprs),
                              Bpl.Expr.Ident(typeConstructorId));
          if (MemberHelper.GetMethodSignature(resolvedMethod).Equals("System.Type.op_Inequality"))
            typeTestExpression = Bpl.Expr.Unary( methodCallToken, Bpl.UnaryOperator.Opcode.Not, typeTestExpression);
          this.TranslatedExpressions.Push(typeTestExpression);
          return;
        }
      }

      // Handle calls to Contract.ForAll and Contract.Exists specially (if they are to the overloads that take two ints and a predicate on ints)
      if (resolvedMethod.ContainingTypeDefinition.InternedKey == this.sink.host.PlatformType.SystemDiagnosticsContractsContract.InternedKey)
      {
          var methodName = resolvedMethod.Name.Value;
          if (methodCall.Arguments.Count() == 3 && (methodName == "ForAll" || methodName == "Exists"))
          {
              var noToken = Bpl.Token.NoToken;

              this.Traverse(methodCall.Arguments.ElementAt(0));
              var lb = this.TranslatedExpressions.Pop();
              this.Traverse(methodCall.Arguments.ElementAt(1));
              var ub = this.TranslatedExpressions.Pop();
              var delegateArgument = methodCall.Arguments.ElementAt(2);
              this.Traverse(delegateArgument);
              var del = this.TranslatedExpressions.Pop();

              var boundVar = new Bpl.LocalVariable(noToken, new Bpl.TypedIdent(noToken, TranslationHelper.GenerateTempVarName(), Bpl.Type.Int));

              var resultVar = new Bpl.LocalVariable(noToken, new Bpl.TypedIdent(noToken, TranslationHelper.GenerateTempVarName(), Bpl.Type.Bool));

              var delegateType = delegateArgument.Type;
              var invokeMethod = delegateType.ResolvedType.GetMembersNamed(this.sink.host.NameTable.GetNameFor("Invoke"), false).First() as IMethodReference;
              var unspecializedInvokeMethod = Sink.Unspecialize(invokeMethod).ResolvedMethod;
              var invokeProcedureInfo = sink.FindOrCreateProcedure(unspecializedInvokeMethod);
              var ins = new List<Bpl.Expr>();
              ins.Add(del);
              var localStmtTraverser = this.StmtTraverser.factory.MakeStatementTraverser(this.sink, this.StmtTraverser.PdbReader, this.contractContext);

              var secondArg = new Bpl.NAryExpr(noToken, new Bpl.FunctionCall(this.sink.Heap.Int2Union), new List<Bpl.Expr>(new Bpl.Expr[] {Bpl.Expr.Ident(boundVar)}));
              ins.Add(secondArg);
              var outs = new List<Bpl.IdentifierExpr>();
              outs.Add(Bpl.Expr.Ident(resultVar));

              var callCmd = new Bpl.CallCmd(noToken, invokeProcedureInfo.Decl.Name, ins, outs);
              var blockCmds = new List<Bpl.Cmd>();
              blockCmds.Add(
                new Bpl.AssumeCmd(noToken,
                Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Eq,
                                new Bpl.NAryExpr(noToken, new Bpl.FunctionCall(this.sink.Heap.Union2Int), new List<Bpl.Expr>(new Bpl.Expr[] {secondArg})),
                                Bpl.Expr.Ident(boundVar))));
              blockCmds.Add(callCmd);
              Bpl.Block block = new Bpl.Block(noToken, "A", blockCmds, new Bpl.ReturnExprCmd(noToken, Bpl.Expr.Ident(resultVar)));
              Bpl.Expr body = new Bpl.CodeExpr(new List<Bpl.Variable>(new Bpl.Variable[] {resultVar}), new List<Bpl.Block>{block});


              Bpl.Expr antecedent = Bpl.Expr.And(Bpl.Expr.Le(lb, Bpl.Expr.Ident(boundVar)), Bpl.Expr.Lt(Bpl.Expr.Ident(boundVar), ub));

              Bpl.Expr quantifier;
              if (methodName == "ForAll")
              {
                  body = Bpl.Expr.Imp(antecedent, body);
                  quantifier = new Bpl.ForallExpr(methodCallToken, new List<Bpl.Variable>(new Bpl.Variable[] {boundVar}), body);
              }
              else
              {
                  body = Bpl.Expr.And(antecedent, body);
                  quantifier = new Bpl.ExistsExpr(methodCallToken, new List<Bpl.Variable>(new Bpl.Variable[] {boundVar}), body);
              }
              this.TranslatedExpressions.Push(quantifier);
              return;
          }
      }

      List<Bpl.Expr> inexpr;
      List<Bpl.IdentifierExpr> outvars;
      Bpl.IdentifierExpr thisExpr;
      Dictionary<Bpl.IdentifierExpr, Tuple<Bpl.IdentifierExpr,bool>> toBoxed;
      var proc = TranslateArgumentsAndReturnProcedure(methodCallToken, methodCall.MethodToCall, resolvedMethod, methodCall.IsStaticCall ? null : methodCall.ThisArgument, methodCall.Arguments, out inexpr, out outvars, out thisExpr, out toBoxed);
      string methodname = proc.Name;
      var translateAsFunctionCall = proc is Bpl.Function;
      bool isAsync = false;

      // this code structure is quite chaotic, and some code needs to be evaluated regardless, hence the try-finally
      try {
        if (!translateAsFunctionCall) {
          foreach (var a in resolvedMethod.Attributes) {
            if (TypeHelper.GetTypeName(a.Type).EndsWith("AsyncAttribute")) {
                isAsync = true;
            }
          }
        }

        var deferringCtorCall = resolvedMethod.IsConstructor && methodCall.ThisArgument is IThisReference;
        // REVIEW!! Ask Herman: is the above test enough? The following test is used in FindCtorCall.IsDeferringCtor,
        // but it doesn't work when the type is a struct S because then "this" has a type of "&S".
          //&& TypeHelper.TypesAreEquivalent(resolvedMethod.ContainingType, methodCall.ThisArgument.Type);

        if (resolvedMethod.IsConstructor && resolvedMethod.ContainingTypeDefinition.IsStruct && !deferringCtorCall) {
          handleStructConstructorCall(methodCall, methodCallToken, inexpr, outvars, thisExpr, proc);
          return;
        }

        Bpl.CallCmd call;
        bool isEventAdd = resolvedMethod.IsSpecialName && resolvedMethod.Name.Value.StartsWith("add_");
        bool isEventRemove = resolvedMethod.IsSpecialName && resolvedMethod.Name.Value.StartsWith("remove_");
        if (isEventAdd || isEventRemove) {
          call = translateAddRemoveCall(methodCall, resolvedMethod, methodCallToken, inexpr, outvars, thisExpr, isEventAdd);
        } else {
          if (translateAsFunctionCall) {
            var func = proc as Bpl.Function;
            var exprSeq = new List<Bpl.Expr>();
            foreach (var e in inexpr) {
              exprSeq.Add(e);
            }
            var callFunction = new Bpl.NAryExpr(methodCallToken, new Bpl.FunctionCall(func), exprSeq);
            this.TranslatedExpressions.Push(callFunction);
            return;
          } else {
            EmitLineDirective(methodCallToken);
            call = new Bpl.CallCmd(methodCallToken, methodname, inexpr, outvars);
            call.IsAsync = isAsync;
            this.StmtTraverser.StmtBuilder.Add(call);
          }
        }

        foreach (KeyValuePair<Bpl.IdentifierExpr, Tuple<Bpl.IdentifierExpr,bool>> kv in toBoxed) {
          var lhs = kv.Key;
          var tuple = kv.Value;
          var rhs = tuple.Item1;
          Bpl.Expr fromUnion = this.sink.Heap.FromUnion(Bpl.Token.NoToken, lhs.Type, rhs, tuple.Item2);
          this.StmtTraverser.StmtBuilder.Add(TranslationHelper.BuildAssignCmd(lhs, fromUnion));
        }

        if (this.sink.Options.modelExceptions == 2
          || (this.sink.Options.modelExceptions == 1 && this.sink.MethodThrowsExceptions(resolvedMethod))) {
          Bpl.Expr expr = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Neq, Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable), Bpl.Expr.Ident(this.sink.Heap.NullRef));
          this.StmtTraverser.RaiseException(expr);
        }
      } finally {
        // TODO move away phone related code from the translation, it would be better to have 2 or more translation phases
        if (PhoneCodeHelper.instance().PhonePlugin != null) {
          if (PhoneCodeHelper.instance().PhoneNavigationToggled) {
            if (PhoneCodeHelper.instance().isNavigationCall(methodCall)) {
              Bpl.AssignCmd assignCmd = PhoneCodeHelper.instance().createBoogieNavigationUpdateCmd(sink);
              this.StmtTraverser.StmtBuilder.Add(assignCmd);
            }
          }

          if (PhoneCodeHelper.instance().PhoneFeedbackToggled) {
            if (PhoneCodeHelper.instance().isMethodKnownUIChanger(methodCall)) {
              Bpl.AssumeCmd assumeFalse = new Bpl.AssumeCmd(Bpl.Token.NoToken, Bpl.LiteralExpr.False);
              this.StmtTraverser.StmtBuilder.Add(assumeFalse);
            }
          }
        }
      }
    }
    public override void TraverseChildren(ITryCatchFinallyStatement tryCatchFinallyStatement) {

      if (this.sink.Options.modelExceptions == 0) {
        this.Traverse(tryCatchFinallyStatement.TryBody);
        if (tryCatchFinallyStatement.FinallyBody != null)
          this.Traverse(tryCatchFinallyStatement.FinallyBody);
        return;
      }

      this.sink.nestedTryCatchFinallyStatements.Add(new Tuple<ITryCatchFinallyStatement, Sink.TryCatchFinallyContext>(tryCatchFinallyStatement, Sink.TryCatchFinallyContext.InTry));
      this.Traverse(tryCatchFinallyStatement.TryBody);
      StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.LabelVariable), Bpl.Expr.Literal(-1)));
      StmtBuilder.Add(new Bpl.GotoCmd(Bpl.Token.NoToken, new List<string>(new string[] {this.sink.FindOrCreateFinallyLabel(tryCatchFinallyStatement)})));
      this.sink.nestedTryCatchFinallyStatements.RemoveAt(this.sink.nestedTryCatchFinallyStatements.Count - 1);

      StmtBuilder.AddLabelCmd(this.sink.FindOrCreateCatchLabel(tryCatchFinallyStatement));
      StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.LocalExcVariable), Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable)));
      StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable), Bpl.Expr.Ident(this.sink.Heap.NullRef)));
      List<Bpl.StmtList> catchStatements = new List<Bpl.StmtList>();
      List<Bpl.Expr> typeReferences = new List<Bpl.Expr>();
      this.sink.nestedTryCatchFinallyStatements.Add(new Tuple<ITryCatchFinallyStatement, Sink.TryCatchFinallyContext>(tryCatchFinallyStatement, Sink.TryCatchFinallyContext.InCatch));
      foreach (ICatchClause catchClause in tryCatchFinallyStatement.CatchClauses) {
        typeReferences.Insert(0, this.sink.FindOrCreateTypeReference(catchClause.ExceptionType, true));
        StatementTraverser catchTraverser = this.factory.MakeStatementTraverser(this.sink, this.PdbReader, this.contractContext);
        if (catchClause.ExceptionContainer != Dummy.LocalVariable) {
          Bpl.Variable catchClauseVariable = this.sink.FindOrCreateLocalVariable(catchClause.ExceptionContainer);
          catchTraverser.StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(catchClauseVariable), Bpl.Expr.Ident(this.sink.LocalExcVariable)));
        }
        catchTraverser.Traverse(catchClause.Body);
        catchTraverser.StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.LabelVariable), Bpl.Expr.Literal(-1)));
        catchTraverser.StmtBuilder.Add(new Bpl.GotoCmd(Bpl.Token.NoToken, new List<string>(new string[] {this.sink.FindOrCreateFinallyLabel(tryCatchFinallyStatement)})));
        catchStatements.Insert(0, catchTraverser.StmtBuilder.Collect(catchClause.Token()));
      }
      Bpl.IfCmd elseIfCmd = new Bpl.IfCmd(Bpl.Token.NoToken, Bpl.Expr.Literal(false), TranslationHelper.BuildStmtList(new Bpl.ReturnCmd(Bpl.Token.NoToken)), null, null);
      Bpl.Expr dynTypeOfOperand = this.sink.Heap.DynamicType(Bpl.Expr.Ident(this.sink.LocalExcVariable));
      for (int i = 0; i < catchStatements.Count; i++) {
        Bpl.Expr expr = new Bpl.NAryExpr(Bpl.Token.NoToken, new Bpl.FunctionCall(this.sink.Heap.Subtype), new List<Bpl.Expr>(new Bpl.Expr[] {dynTypeOfOperand, typeReferences[i]}));
        elseIfCmd = new Bpl.IfCmd(Bpl.Token.NoToken, expr, catchStatements[i], elseIfCmd, null);
      }
      this.StmtBuilder.Add(elseIfCmd);
      this.StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable), Bpl.Expr.Ident(this.sink.LocalExcVariable)));
      RaiseException();
      this.sink.nestedTryCatchFinallyStatements.RemoveAt(this.sink.nestedTryCatchFinallyStatements.Count - 1);

      this.StmtBuilder.AddLabelCmd(this.sink.FindOrCreateFinallyLabel(tryCatchFinallyStatement));
      if (tryCatchFinallyStatement.FinallyBody != null) {
        this.sink.nestedTryCatchFinallyStatements.Add(new Tuple<ITryCatchFinallyStatement, Sink.TryCatchFinallyContext>(tryCatchFinallyStatement, Sink.TryCatchFinallyContext.InFinally));
        Bpl.Variable savedExcVariable = this.sink.CreateFreshLocal(this.sink.Heap.RefType);
        Bpl.Variable savedLabelVariable = this.sink.CreateFreshLocal(Bpl.Type.Int);
        StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(savedExcVariable), Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable)));
        StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(savedLabelVariable), Bpl.Expr.Ident(this.sink.LabelVariable)));
        this.Traverse(tryCatchFinallyStatement.FinallyBody);
        StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable), Bpl.Expr.Ident(savedExcVariable)));
        StmtBuilder.Add(TranslationHelper.BuildAssignCmd(Bpl.Expr.Ident(this.sink.LabelVariable), Bpl.Expr.Ident(savedLabelVariable)));
        this.sink.nestedTryCatchFinallyStatements.RemoveAt(this.sink.nestedTryCatchFinallyStatements.Count - 1);
      }
      GenerateDispatchContinuation(tryCatchFinallyStatement);
      StmtBuilder.AddLabelCmd(this.sink.FindOrCreateContinuationLabel(tryCatchFinallyStatement));
      Bpl.Expr raiseExpr = Bpl.Expr.Binary(Bpl.BinaryOperator.Opcode.Neq, Bpl.Expr.Ident(this.sink.Heap.ExceptionVariable), Bpl.Expr.Ident(this.sink.Heap.NullRef));
      RaiseException(raiseExpr);
    }