public override Expression VisitMethodCall(MethodCall call)
        {
            MemberBinding mb = call.Callee as MemberBinding;

            if (mb == null)
            {
                return(call);
            }

            Method calledMethod = mb.BoundMember as Method;

            if (calledMethod == null)
            {
                return(call);
            }

            Method template = calledMethod.Template;

            if (contractNodes.IsOldMethod(template))
            {
                OldExpression oe = new OldExpression(ExtractOldExpression(call));
                oe.Type = call.Type;
                return(oe);
            }

            if (contractNodes.IsValueAtReturnMethod(template))
            {
                return(new AddressDereference(call.Operands[0], calledMethod.TemplateArguments[0], call.SourceContext));
            }

            if (contractNodes.IsResultMethod(template))
            {
                // check if we are in an Task returning method
                if (this.declaringMethod != null && this.declaringMethod.ReturnType != null)
                {
                    var rt    = this.declaringMethod.ReturnType;
                    var templ = rt.Template;

                    if (templ != null && templ.Name.Name == "Task`1" && rt.TemplateArguments != null &&
                        rt.TemplateArguments.Count == 1)
                    {
                        var targ = rt.TemplateArguments[0];
                        if (calledMethod.TemplateArguments[0] == targ)
                        {
                            // use of ReturnValue<T>() instead of ReturnValue<Task<T>>().Result
                            var retExp     = new ReturnValue(rt, call.SourceContext);
                            var resultProp = rt.GetProperty(Identifier.For("Result"));
                            if (resultProp != null && resultProp.Getter != null)
                            {
                                return(new MethodCall(new MemberBinding(retExp, resultProp.Getter), new ExpressionList()));
                            }
                        }
                    }
                }

                return(new ReturnValue(calledMethod.ReturnType, call.SourceContext));
            }

            return(base.VisitMethodCall(call));
        }
        /// <summary>
        /// Performs a bunch of transformations that the basic Extractor doesn't seem to do:
        ///  - Turns calls to Old contract method into OldExpressions
        ///  - Turns references to "result" into ResultExpressions
        ///  -
        /// </summary>
        public override Expression VisitMethodCall(MethodCall call)
        {
            MemberBinding mb = call.Callee as MemberBinding;

            if (mb == null)
            {
                return(call);
            }

            Method calledMethod = mb.BoundMember as Method;

            if (calledMethod == null)
            {
                return(call);
            }

            Method template = calledMethod.Template;

            if (contractNodes.IsOldMethod(template))
            {
                Expression result = base.VisitMethodCall(call);

                call = result as MethodCall;
                if (call == null)
                {
                    return(result);
                }

                result      = new OldExpression(call.Operands[0]);
                result.Type = call.Type;

                return(result);
            }

            if (contractNodes.IsValueAtReturnMethod(template))
            {
                return(new AddressDereference(call.Operands[0], calledMethod.TemplateArguments[0], call.SourceContext));
            }

            if (calledMethod.Parameters != null)
            {
                if (calledMethod.Parameters.Count == 0)
                {
                    if (contractNodes.IsResultMethod(template))
                    {
                        return(new ReturnValue(calledMethod.ReturnType, call.SourceContext));
                    }
                }
                else if (insideInvariant &&
                         contractNodes.IsInvariantMethod(calledMethod))
                {
                    Expression condition = call.Operands[0];
                    condition.SourceContext = call.SourceContext;

                    return(VisitExpression(condition));
                }
            }

            return(base.VisitMethodCall(call));
        }
        private Local GetLocalForOldExpression(OldExpression oldExpression)
        {
            Contract.Requires(oldExpression != null);

            string localName = BestGuessForLocalName(oldExpression);

            return(new Local(Identifier.For("Contract.Old(" + localName + ")"), oldExpression.Type));
        }
        public override Expression VisitParameter(Parameter parameter)
        {
            if (parameter == null) return null;

            var oe = new OldExpression(parameter);
            oe.Type = parameter.Type;

            return oe;
        }
 public override Expression VisitOldExpression(OldExpression oldExpression)
 {
     //Debug.Assert(false, "old was not substituted");
     TypeNode returnType = oldExpression.Type;
     if (returnType.IsValueType)
         return new Literal(0, returnType);
     
     return new Literal(null, returnType);
 }
        public override Expression VisitOldExpression(OldExpression oldExpression)
        {
            //Debug.Assert(false, "old was not substituted");
            TypeNode returnType = oldExpression.Type;

            if (returnType.IsValueType)
            {
                return(new Literal(0, returnType));
            }

            return(new Literal(null, returnType));
        }
        public override Expression VisitMethodCall(MethodCall call)
        {
            MemberBinding mb = call.Callee as MemberBinding;
            if (mb == null) return call;

            Method calledMethod = mb.BoundMember as Method;
            if (calledMethod == null) return call;

            Method template = calledMethod.Template;

            if (contractNodes.IsOldMethod(template))
            {
                OldExpression oe = new OldExpression(ExtractOldExpression(call));
                oe.Type = call.Type;
                return oe;
            }

            if (contractNodes.IsValueAtReturnMethod(template))
            {
                return new AddressDereference(call.Operands[0], calledMethod.TemplateArguments[0], call.SourceContext);
            }

            if (contractNodes.IsResultMethod(template))
            {
                // check if we are in an Task returning method
                if (this.declaringMethod != null && this.declaringMethod.ReturnType != null)
                {
                    var rt = this.declaringMethod.ReturnType;
                    var templ = rt.Template;

                    if (templ != null && templ.Name.Name == "Task`1" && rt.TemplateArguments != null &&
                        rt.TemplateArguments.Count == 1)
                    {
                        var targ = rt.TemplateArguments[0];
                        if (calledMethod.TemplateArguments[0] == targ)
                        {
                            // use of ReturnValue<T>() instead of ReturnValue<Task<T>>().Result
                            var retExp = new ReturnValue(rt, call.SourceContext);
                            var resultProp = rt.GetProperty(Identifier.For("Result"));
                            if (resultProp != null && resultProp.Getter != null)
                            {
                                return new MethodCall(new MemberBinding(retExp, resultProp.Getter), new ExpressionList());
                            }
                        }
                    }
                }

                return new ReturnValue(calledMethod.ReturnType, call.SourceContext);
            }

            return base.VisitMethodCall(call);
        }
        public override Expression VisitParameter(Parameter parameter)
        {
            if (parameter == null)
            {
                return(null);
            }

            var oe = new OldExpression(parameter);

            oe.Type = parameter.Type;

            return(oe);
        }
        /// <summary>
        /// Checks for errors before applying a rule.
        /// </summary>
        /// <param name="node">The node instance to check.</param>
        /// <param name="dataList">Optional data collected during inspection of sources.</param>
        /// <param name="data">Private data to give to Apply() upon return.</param>
        /// <returns>True if an error occured.</returns>
        public override bool CheckConsistency(IOldExpression node, IDictionary <ISourceTemplate, object> dataList, out object data)
        {
            data = null;
            bool Success = true;

            Success &= OldExpression.ResolveCompilerReferences(node, ErrorList, out ResolvedExpression ResolvedExpression);

            if (Success)
            {
                data = ResolvedExpression;
            }

            return(Success);
        }
Beispiel #10
0
 public override Expression VisitOldExpression(OldExpression oldExpression)
 {
     if (oldExpression == null || oldExpression.expression == null)
     {
         return(null);
     }
     if (this._string == null)
     {
         this._string = new StringBuilder();
     }
     this._string.Append("\\old(");
     this.VisitExpression(oldExpression.expression);
     this._string.Append(")");
     return(oldExpression);
 }
        private string BestGuessForLocalName(OldExpression oldExpression)
        {
            Contract.Requires(oldExpression != null);

            MemberBinding mb = oldExpression.expression as MemberBinding;

            if (mb != null)
            {
                return(mb.BoundMember.Name.Name);
            }

            MethodCall mc = oldExpression.expression as MethodCall;

            if (mc != null)
            {
                mb = mc.Callee as MemberBinding;
                if (mb != null)
                {
                    Method calledMethod = mb.BoundMember as Method;
                    if (calledMethod != null && calledMethod.IsPropertyGetter)
                    {
                        Property prop = calledMethod.DeclaringMember as Property;
                        if (prop != null)
                        {
                            return(prop.Name.Name);
                        }

                        return(mb.BoundMember.Name.Name);
                    }

                    return(mb.BoundMember.Name.Name);
                }
            }

            Parameter p = oldExpression.expression as Parameter;

            if (p != null)
            {
                return(p.Name.Name);
            }

            // Didn't find something good to use for the name, so just make it unique.
            var x = this.counter.ToString();

            this.counter++;

            return(x);
        }
Beispiel #12
0
    private string BestGuessForLocalName(OldExpression oldExpression) {
      Contract.Requires(oldExpression != null);

      MemberBinding mb = oldExpression.expression as MemberBinding;
      if (mb != null) {
        return mb.BoundMember.Name.Name;
      }
      MethodCall mc = oldExpression.expression as MethodCall;
      if (mc != null) {
        mb = mc.Callee as MemberBinding;
        if (mb != null) {
          Method calledMethod = mb.BoundMember as Method;
          if (calledMethod != null && calledMethod.IsPropertyGetter) {
            Property prop = calledMethod.DeclaringMember as Property;
            if (prop != null)
              return prop.Name.Name;
            else
              return mb.BoundMember.Name.Name;
          } else {
            return mb.BoundMember.Name.Name;
          }
        }
      }
      Parameter p = oldExpression.expression as Parameter;
      if (p != null) {
        return p.Name.Name;
      }
      // Didn't find something good to use for the name, so just make it unique.
      var x = this.counter.ToString();
      this.counter++;
      return x;
    }
Beispiel #13
0
 public override Expression VisitOldExpression(OldExpression oldExpression) {
   // no point descending down into any old expressions
   return oldExpression;
 }
Beispiel #14
0
    public override Expression VisitOldExpression(OldExpression oldExpression) {
      if (this.topLevelClosureClass != null) {
        #region In Closure ==> Create a field
        // Since we're within a closure, we can't create a local to hold the value of the old expression
        // but instead have to create a field for it. That field can be a member of the top-level
        // closure class since nothing mentioned in the old expression (except possibly for the
        // bound variables of enclosing quantifications) should be anything captured from
        // an inner anonymous delegate.

        // BUT, first we have to know if the old expression depends on any of the bound
        // variables of the closures in which it is located. If not, then we can implement
        // it as a scalar and just generate the assignment "closure_class.field := e" for
        // "Old(e)" to take a snapshot of e's value in the prestate. If it does depend on
        // any of the bound variables, then we need to generate a set of for-loops that
        // compute the indices and values of e for each tuple of indices so it can be retrieved
        // (given the indices) in the post-state.
        CollectBoundVariables cbv = new CollectBoundVariables(this.stackOfBoundVariables);
        cbv.VisitExpression(oldExpression.expression);

        SubstituteClosureClassWithinOldExpressions subst =
            new SubstituteClosureClassWithinOldExpressions(this.closureLocals);
        Expression e = subst.VisitExpression(oldExpression.expression);
        if (cbv.FoundVariables.Count == 0) {
          #region Use a scalar for the old variable
          Local closureLocal;
          if (!this.closureLocals.TryGetValue(this.topLevelClosureClass, out closureLocal))
          {
            Contract.Assume(false, "can't find closure local!");
          }
          #region Define a scalar
          var clTemplate = HelperMethods.Unspecialize(this.topLevelClosureClass);
          Field f = new Field(clTemplate,
            null,
            FieldFlags.CompilerControlled | FieldFlags.Public,
            Identifier.For("_old" + oldExpression.expression.UniqueKey.ToString()), // unique name for this old expr.
            oldExpression.Type,
            null);
          clTemplate.Members.Add(f);
          // now produce properly instantiated field
          f = (Field)Rewriter.GetMemberInstanceReference(f, this.topLevelClosureClass);
          #endregion
          #region Generate code to store value in prestate
          this.prestateValuesOfOldExpressions.Statements.Add(new AssignmentStatement(new MemberBinding(closureLocal, f), e));
          #endregion
          #region Return expression to be used in poststate
          // Return an expression that will evaluate in the poststate to the value of the old
          // expression in the prestate. This will be this.up.f where "up" is the field C#
          // generated to point to the instance of the top-level closure class.
          if (this.PointerToTopLevelClosureClass == null) {
            // then the old expression occurs in the top-level closure class. Just return "this.f"
            // where "this" refers to the top-level closure class.
            return new MemberBinding(new This(this.currentClosureClass), f);
          } else {
            return new MemberBinding(
              new MemberBinding(new This(this.currentClosureClass), this.PointerToTopLevelClosureClass),
              f);
          }
          #endregion
          #endregion
        } else {
          // the Old expression *does* depend upon at least one of the bound variable
          // in a ForAll or Exists expression
          #region Use an indexed variable for the old variable
          TypeNode oldVariableTypeDomain;
          #region Decide if domain is one-dimensional or not
          bool oneDimensional = cbv.FoundVariables.Count == 1 && cbv.FoundVariables[0].Type.IsValueType;
          if (oneDimensional) {
            // a one-dimensional old-expression can use the index variable directly
            oldVariableTypeDomain = cbv.FoundVariables[0].Type;
          } else {
            oldVariableTypeDomain = SystemTypes.GenericList.GetTemplateInstance(this.module, SystemTypes.Int32);
          }
          #endregion
          TypeNode oldVariableTypeRange = oldExpression.Type;
          TypeNode oldVariableType = SystemTypes.GenericDictionary.GetTemplateInstance(this.module, oldVariableTypeDomain, oldVariableTypeRange);
          Local closureLocal;
          if (!this.closureLocals.TryGetValue(this.topLevelClosureClass, out closureLocal))
          {
            Contract.Assume(false, "can't find closure local");
          }
          #region Define an indexed variable
          var clTemplate = HelperMethods.Unspecialize(this.topLevelClosureClass);
          Field f = new Field(clTemplate,
            null,
            FieldFlags.CompilerControlled | FieldFlags.Assembly, // can't be private or protected because it needs to be accessed from inner (closure) classes that don't inherit from the class this field is added to.
            Identifier.For("_old" + oldExpression.expression.UniqueKey.ToString()), // unique name for this old expr.
            oldVariableType,
            null);
          clTemplate.Members.Add(f);
          // instantiate f
          f = (Field)Rewriter.GetMemberInstanceReference(f, closureLocal.Type);
          #endregion
          #region Generate code to initialize the indexed variable
          Statement init = new AssignmentStatement(
            new MemberBinding(closureLocal, f),
            new Construct(new MemberBinding(null, oldVariableType.GetConstructor()), null));
          this.prestateValuesOfOldExpressions.Statements.Add(init);
          #endregion
          #region Generate code to store values in prestate
          #region Create assignment: this.closure.f[i,j,k,...] = e;
          Method setItem = oldVariableType.GetMethod(Identifier.For("set_Item"), oldVariableTypeDomain, oldVariableTypeRange);
          Expression index;
          if (oneDimensional) {
            index = cbv.FoundVariables[0];
          } else {
            //InstanceInitializer ctor =
            //  ContractNodes.TupleClass.GetConstructor(SystemTypes.Int32.GetArrayType(1));
            //Expression index = new Construct(new MemberBinding(null,ctor),new ExpressionList(
            index = Literal.Null;
          }
          MethodCall mc = new MethodCall(new MemberBinding(new MemberBinding(closureLocal, f), setItem),
            new ExpressionList(index, e));
          Statement stat = new ExpressionStatement(mc);
          #endregion
          List<Local> locals = new List<Local>(this.stackOfBoundVariables.Count);
          TrivialHashtable paramMap = new TrivialHashtable();
          #region Generate a local for each bound variable to use in for-loop
          foreach (Variable v in this.stackOfBoundVariables) {
            Local l = new Local(Identifier.Empty, v.Type);
            paramMap[v.UniqueKey] = l;
            locals.Add(l);
          }
          #endregion
          #region Substitute locals for bound variables in old expression *AND* in inner loop bounds
          SubstituteParameters sps = new SubstituteParameters(paramMap, this.stackOfBoundVariables);
          sps.Visit(stat);
          #endregion
          #region Create nested for-loops around assignment
          // keep track of when the first variable is used (from innermost to outermost)
          // as soon as the first one is needed because the old expression depends on it,
          // then keep all enclosing loops. It would be possible to keep only those where
          // the necessary loops have loop bounds that depend on an enclosing loop, but I
          // haven't calculated that, so just keep them all. For instance, if the old expression
          // depends on j and the loops are "for i,0,n" and inside that "for j,0,i", then need
          // both loops. If the inner loop bounds were 0 and n, then wouldn't need the outer
          // loop.
          bool usedAVariable = false;
          for (int i = this.stackOfBoundVariables.Count - 1; 0 <= i; i--) {
            if (!usedAVariable
              && !cbv.FoundVariables.Contains(this.stackOfBoundVariables[i])) continue;
            usedAVariable = true;
            Expression lowerBound = new Duplicator(this.module, this.currentClosureClass).VisitExpression(
              this.stackOfMethods[i].Operands[0]);
            lowerBound = subst.VisitExpression(lowerBound);
            lowerBound = sps.VisitExpression(lowerBound);
            Expression upperBound = new Duplicator(this.module, this.currentClosureClass).VisitExpression(
              this.stackOfMethods[i].Operands[1]);
            upperBound = subst.VisitExpression(upperBound);
            upperBound = sps.VisitExpression(upperBound);
            stat = RewriteHelper.GenerateForLoop(locals[i], lowerBound, upperBound, stat);
          }
          #endregion
          this.prestateValuesOfOldExpressions.Statements.Add(stat);
          #endregion
          #region Return expression to be used in poststate
          Method getItem = oldVariableType.GetMethod(Identifier.For("get_Item"), oldVariableTypeDomain);
          if (oneDimensional) {
            index = cbv.FoundReferences[0];
          } else {
            //InstanceInitializer ctor =
            //  ContractNodes.TupleClass.GetConstructor(SystemTypes.Int32.GetArrayType(1));
            //Expression index = new Construct(new MemberBinding(null,ctor),new ExpressionList(
            index = Literal.Null;
          }
          // Return an expression that will evaluate in the poststate to the value of the old
          // expression in the prestate. This will be this.up.f[i,j,k,...] where "up" is the field C#
          // generated to point to the instance of the top-level closure class.
          MemberBinding thisDotF;
          if (this.PointerToTopLevelClosureClass == null) {
            // then the old expression occurs in the top-level closure class. Just return "this.f"
            // where "this" refers to the top-level closure class.
            Contract.Assume(f != null);
            thisDotF = new MemberBinding(new This(clTemplate), HelperMethods.Unspecialize(f));
          } else {
            thisDotF = new MemberBinding(
              new MemberBinding(new This(clTemplate), this.PointerToTopLevelClosureClass),
              f);
          }
          return new MethodCall(new MemberBinding(thisDotF, getItem), new ExpressionList(index));
          #endregion
          #endregion
        }
        #endregion
      } else {
        #region Not in closure ==> Create a local variable
        Local l = GetLocalForOldExpression(oldExpression);
        #region Make sure local can be seen in the debugger (for the entire method, unfortunately)
        if (currentMethod.LocalList == null) {
          currentMethod.LocalList = new LocalList();
        }
        currentMethod.LocalList.Add(l);
        currentMethod.Body.HasLocals = true;
        #endregion
        this.prestateValuesOfOldExpressions.Statements.Add(
          new AssignmentStatement(l, oldExpression.expression));

        // Return an expression that will evaluate in the poststate to the value of the old
        // expression in the prestate. When we're not in a closure, this is just the local
        // itself.
        return l;
        #endregion
      }
    }
 public EventingVisitor(Action<OldExpression> visitOldExpression) { VisitedOldExpression += visitOldExpression; } public event Action<OldExpression> VisitedOldExpression; public override Expression VisitOldExpression(OldExpression oldExpression) { if (VisitedOldExpression != null) VisitedOldExpression(oldExpression); return base.VisitOldExpression(oldExpression); }
Beispiel #16
0
 public virtual void VisitOldExpression(OldExpression oldExpression)
 {
   if (oldExpression == null) return;
   this.VisitExpression(oldExpression.expression);
 }
private static string oldExpression2str(OldExpression oe)
  {
      StringBuilder sb = new StringBuilder();
    
      sb.Append(oldExpression2str(oe.NodeType));
      sb.Append("(");
      sb.Append(expression2str(oe.expression));
      sb.Append(")");

      return sb.ToString();
  }
        public override Expression VisitOldExpression(OldExpression oldExpression)
        {
            if (this.topLevelClosureClass != null)
            {
                // In Closure ==> Create a field

                // Since we're within a closure, we can't create a local to hold the value of the old expression
                // but instead have to create a field for it. That field can be a member of the top-level
                // closure class since nothing mentioned in the old expression (except possibly for the
                // bound variables of enclosing quantifications) should be anything captured from
                // an inner anonymous delegate.

                // BUT, first we have to know if the old expression depends on any of the bound
                // variables of the closures in which it is located. If not, then we can implement
                // it as a scalar and just generate the assignment "closure_class.field := e" for
                // "Old(e)" to take a snapshot of e's value in the prestate. If it does depend on
                // any of the bound variables, then we need to generate a set of for-loops that
                // compute the indices and values of e for each tuple of indices so it can be retrieved
                // (given the indices) in the post-state.
                CollectBoundVariables cbv = new CollectBoundVariables(this.stackOfBoundVariables);
                cbv.VisitExpression(oldExpression.expression);

                SubstituteClosureClassWithinOldExpressions subst = new SubstituteClosureClassWithinOldExpressions(this.closureLocals);
                Expression e = subst.VisitExpression(oldExpression.expression);
                if (cbv.FoundVariables.Count == 0)
                {
                    // Use a scalar for the old variable

                    Local closureLocal;
                    if (!this.closureLocals.TryGetValue(this.topLevelClosureClass, out closureLocal))
                    {
                        Contract.Assume(false, "can't find closure local!");
                    }

                    // Define a scalar

                    var   clTemplate = HelperMethods.Unspecialize(this.topLevelClosureClass);
                    Field f          = new Field(clTemplate,
                                                 null,
                                                 FieldFlags.CompilerControlled | FieldFlags.Public,
                                                 Identifier.For("_old" + oldExpression.expression.UniqueKey.ToString()),
                                                 // unique name for this old expr.
                                                 oldExpression.Type,
                                                 null);

                    clTemplate.Members.Add(f);

                    // now produce properly instantiated field
                    f = (Field)Rewriter.GetMemberInstanceReference(f, this.topLevelClosureClass);

                    // Generate code to store value in prestate

                    this.prestateValuesOfOldExpressions.Statements.Add(
                        new AssignmentStatement(new MemberBinding(closureLocal, f), e));

                    // Return expression to be used in poststate

                    // Return an expression that will evaluate in the poststate to the value of the old
                    // expression in the prestate. This will be this.up.f where "up" is the field C#
                    // generated to point to the instance of the top-level closure class.
                    if (this.PointerToTopLevelClosureClass == null)
                    {
                        // then the old expression occurs in the top-level closure class. Just return "this.f"
                        // where "this" refers to the top-level closure class.
                        return(new MemberBinding(new This(this.currentClosureClass), f));
                    }
                    else
                    {
                        return(new MemberBinding(
                                   new MemberBinding(new This(this.currentClosureClass), this.PointerToTopLevelClosureClass),
                                   f));
                    }
                }
                else
                {
                    // the Old expression *does* depend upon at least one of the bound variable
                    // in a ForAll or Exists expression

                    // Use an indexed variable for the old variable

                    TypeNode oldVariableTypeDomain;

                    // Decide if domain is one-dimensional or not

                    bool oneDimensional = cbv.FoundVariables.Count == 1 && cbv.FoundVariables[0].Type.IsValueType;
                    if (oneDimensional)
                    {
                        // a one-dimensional old-expression can use the index variable directly
                        oldVariableTypeDomain = cbv.FoundVariables[0].Type;
                    }
                    else
                    {
                        oldVariableTypeDomain = SystemTypes.GenericList.GetTemplateInstance(this.module,
                                                                                            SystemTypes.Int32);
                    }

                    TypeNode oldVariableTypeRange = oldExpression.Type;
                    TypeNode oldVariableType      = SystemTypes.GenericDictionary.GetTemplateInstance(this.module,
                                                                                                      oldVariableTypeDomain, oldVariableTypeRange);

                    Local closureLocal;
                    if (!this.closureLocals.TryGetValue(this.topLevelClosureClass, out closureLocal))
                    {
                        Contract.Assume(false, "can't find closure local");
                    }

                    // Define an indexed variable

                    var clTemplate = HelperMethods.Unspecialize(this.topLevelClosureClass);

                    Field f = new Field(clTemplate,
                                        null,
                                        FieldFlags.CompilerControlled | FieldFlags.Assembly,
                                        // can't be private or protected because it needs to be accessed from inner (closure) classes that don't inherit from the class this field is added to.
                                        Identifier.For("_old" + oldExpression.expression.UniqueKey.ToString()),
                                        // unique name for this old expr.
                                        oldVariableType,
                                        null);

                    clTemplate.Members.Add(f);

                    // instantiate f
                    f = (Field)Rewriter.GetMemberInstanceReference(f, closureLocal.Type);

                    // Generate code to initialize the indexed variable

                    Statement init = new AssignmentStatement(
                        new MemberBinding(closureLocal, f),
                        new Construct(new MemberBinding(null, oldVariableType.GetConstructor()), null));

                    this.prestateValuesOfOldExpressions.Statements.Add(init);

                    // Generate code to store values in prestate

                    // Create assignment: this.closure.f[i,j,k,...] = e;

                    Method setItem = oldVariableType.GetMethod(Identifier.For("set_Item"), oldVariableTypeDomain, oldVariableTypeRange);

                    Expression index;
                    if (oneDimensional)
                    {
                        index = cbv.FoundVariables[0];
                    }
                    else
                    {
                        //InstanceInitializer ctor =
                        //  ContractNodes.TupleClass.GetConstructor(SystemTypes.Int32.GetArrayType(1));
                        //Expression index = new Construct(new MemberBinding(null,ctor),new ExpressionList(
                        index = Literal.Null;
                    }

                    MethodCall mc = new MethodCall(new MemberBinding(new MemberBinding(closureLocal, f), setItem),
                                                   new ExpressionList(index, e));

                    Statement stat = new ExpressionStatement(mc);

                    List <Local>     locals   = new List <Local>(this.stackOfBoundVariables.Count);
                    TrivialHashtable paramMap = new TrivialHashtable();

                    // Generate a local for each bound variable to use in for-loop

                    foreach (Variable v in this.stackOfBoundVariables)
                    {
                        Local l = new Local(Identifier.Empty, v.Type);
                        paramMap[v.UniqueKey] = l;
                        locals.Add(l);
                    }

                    // Substitute locals for bound variables in old expression *AND* in inner loop bounds

                    SubstituteParameters sps = new SubstituteParameters(paramMap, this.stackOfBoundVariables);
                    sps.Visit(stat);

                    // Create nested for-loops around assignment

                    // keep track of when the first variable is used (from innermost to outermost)
                    // as soon as the first one is needed because the old expression depends on it,
                    // then keep all enclosing loops. It would be possible to keep only those where
                    // the necessary loops have loop bounds that depend on an enclosing loop, but I
                    // haven't calculated that, so just keep them all. For instance, if the old expression
                    // depends on j and the loops are "for i,0,n" and inside that "for j,0,i", then need
                    // both loops. If the inner loop bounds were 0 and n, then wouldn't need the outer
                    // loop.
                    bool usedAVariable = false;

                    for (int i = this.stackOfBoundVariables.Count - 1; 0 <= i; i--)
                    {
                        if (!usedAVariable &&
                            !cbv.FoundVariables.Contains(this.stackOfBoundVariables[i]))
                        {
                            continue;
                        }
                        usedAVariable = true;
                        Expression lowerBound = new Duplicator(this.module, this.currentClosureClass).VisitExpression(
                            this.stackOfMethods[i].Operands[0]);

                        lowerBound = subst.VisitExpression(lowerBound);
                        lowerBound = sps.VisitExpression(lowerBound);

                        Expression upperBound = new Duplicator(this.module, this.currentClosureClass).VisitExpression(
                            this.stackOfMethods[i].Operands[1]);

                        upperBound = subst.VisitExpression(upperBound);
                        upperBound = sps.VisitExpression(upperBound);

                        stat = RewriteHelper.GenerateForLoop(locals[i], lowerBound, upperBound, stat);
                    }

                    this.prestateValuesOfOldExpressions.Statements.Add(stat);

                    // Return expression to be used in poststate

                    Method getItem = oldVariableType.GetMethod(Identifier.For("get_Item"), oldVariableTypeDomain);
                    if (oneDimensional)
                    {
                        index = cbv.FoundReferences[0];
                    }
                    else
                    {
                        //InstanceInitializer ctor =
                        //  ContractNodes.TupleClass.GetConstructor(SystemTypes.Int32.GetArrayType(1));
                        //Expression index = new Construct(new MemberBinding(null,ctor),new ExpressionList(
                        index = Literal.Null;
                    }

                    // Return an expression that will evaluate in the poststate to the value of the old
                    // expression in the prestate. This will be this.up.f[i,j,k,...] where "up" is the field C#
                    // generated to point to the instance of the top-level closure class.
                    MemberBinding thisDotF;

                    if (this.PointerToTopLevelClosureClass == null)
                    {
                        // then the old expression occurs in the top-level closure class. Just return "this.f"
                        // where "this" refers to the top-level closure class.
                        Contract.Assume(f != null);

                        thisDotF = new MemberBinding(new This(clTemplate), HelperMethods.Unspecialize(f));
                    }
                    else
                    {
                        thisDotF = new MemberBinding(
                            new MemberBinding(new This(clTemplate), this.PointerToTopLevelClosureClass),
                            f);
                    }

                    return(new MethodCall(new MemberBinding(thisDotF, getItem), new ExpressionList(index)));
                }
            }
            else
            {
                // Not in closure ==> Create a local variable

                Local l = GetLocalForOldExpression(oldExpression);

                // Make sure local can be seen in the debugger (for the entire method, unfortunately)

                if (currentMethod.LocalList == null)
                {
                    currentMethod.LocalList = new LocalList();
                }

                currentMethod.LocalList.Add(l);
                currentMethod.Body.HasLocals = true;

                this.prestateValuesOfOldExpressions.Statements.Add(new AssignmentStatement(l, oldExpression.expression));

                // Return an expression that will evaluate in the poststate to the value of the old
                // expression in the prestate. When we're not in a closure, this is just the local
                // itself.
                return(l);
            }
        }
Beispiel #19
0
    private Local GetLocalForOldExpression(OldExpression oldExpression) {
      Contract.Requires(oldExpression != null);

      string localName = BestGuessForLocalName(oldExpression);
      return new Local(Identifier.For("Contract.Old(" + localName + ")"), oldExpression.Type);
    }
Beispiel #20
0
 public override Expression VisitOldExpression(OldExpression old){
   if (old == null) return null;
   old.expression = this.VisitExpression(old.expression);
   if (old.expression == null) return null;
   old.Type = old.expression.Type;
   return old;
 }
 public override void VisitOldExpression(OldExpression oldExpression)
 {
     this.errorHandler(new Error(1023, "OldValue() can be used only in Ensures.", lastSC));
 }
 public override Expression VisitOldExpression(OldExpression oldExpression)
 {
     // no point descending down into any old expressions
     return(oldExpression);
 }
Beispiel #23
0
 // TODO: allow arr[i][x][j], where i,j are quantified variables, and x is not
 // TODO: multidimensional array...
 public override Expression VisitIndexer(Indexer indexer) {
   //^ assert this.dependents.Contains(indexer)
   bool operandsDependentOnQuantifiedVar = false;
   foreach (Expression e1 in indexer.Operands) {
     if (this.dependents.ContainsKey(e1)) {
       operandsDependentOnQuantifiedVar = true;
       break;
     }
   }
   bool objectDependentOnQuantifiedVar = this.dependents.ContainsKey(indexer.Object);
   if (operandsDependentOnQuantifiedVar) {
     this.currentIndexLevel ++;
     Expression newArr = this.VisitExpression(indexer.Object);
     OldExpression olde = newArr as OldExpression;
     if (olde == null && !objectDependentOnQuantifiedVar) {
       // If this is an array expression that does not depend on any of the quantified vars
       // create an old expression
       olde = new OldExpression(newArr);
     }
     if (olde != null) {
       olde.ShallowCopyUptoDimension = this.currentIndexLevel;
       indexer.Object = olde;
     } else {
       indexer.Object = newArr;
     }
     this.currentIndexLevel --;
     indexer.Operands = this.VisitExpressionList(indexer.Operands);
     return indexer;
   }
   return base.VisitIndexer(indexer);
 }
Beispiel #24
0
 private Expression ParseIndexerCallOrSelector(Expression expression, TokenSet followers){
   TokenSet followersOrContinuers = followers|Token.LeftBracket|Token.LeftParenthesis|Token.Dot;
   for(;;){
     switch (this.currentToken){
       case Token.LeftBracket:
         SourceContext lbCtx = this.scanner.CurrentSourceContext;
         this.GetNextToken();
         if (this.insideModifiesClause && this.currentToken == Token.Multiply){
           // Handle code such as
           //
           //     modifies myArray[*];
           //
           // which means that the method may modify all elements of myArray.
           int savedStartPos = this.scanner.startPos;
           int savedEndPos = this.scanner.endPos;
           this.GetNextToken();
           if (this.currentToken == Token.RightBracket){
             SourceContext sctxt = this.scanner.CurrentSourceContext;
             sctxt.StartPos = lbCtx.StartPos;
             this.GetNextToken();
             return new ModifiesArrayClause(expression, sctxt);
           }
           this.scanner.startPos = savedStartPos;
           this.scanner.endPos = savedEndPos;
         }
         int endCol;
         ExpressionList indices = this.ParseIndexList(followersOrContinuers, lbCtx, out endCol);
         Indexer indexer = new Indexer(expression, indices);
         indexer.SourceContext = expression.SourceContext;
         indexer.SourceContext.EndPos = endCol;
         indexer.ArgumentListIsIncomplete = this.scanner.GetChar(endCol-1) != ']';
         expression = indexer;
         break;
       case Token.LessThan:
         SourceContext ltCtx = this.scanner.CurrentSourceContext;
         ScannerState ss = this.scanner.state;
         int arity;
         TypeNodeList typeArguments = this.ParseTypeArguments(true, false, followers|Token.LeftParenthesis, out endCol, out arity);
         if (typeArguments == null || (typeArguments.Count > 1 && Parser.TypeArgumentListNonFollower[this.currentToken])) {
           this.scanner.endPos = ltCtx.StartPos;
           this.scanner.state = ss;
           this.currentToken = Token.None;
           this.GetNextToken();
           return expression;
         }
         TemplateInstance instance = new TemplateInstance(expression, typeArguments);
         instance.TypeArgumentExpressions = typeArguments == null ? null : typeArguments.Clone();
         instance.SourceContext = expression.SourceContext;
         instance.SourceContext.EndPos = endCol;
         expression = instance;
         break;
       case Token.LeftParenthesis:
         SourceContext lpCtx = this.scanner.CurrentSourceContext;
         this.GetNextToken();
         ExpressionList arguments = this.ParseArgumentList(followersOrContinuers, lpCtx, out endCol);
         if (expression == null) return null;
         if (expression is Identifier && arguments.Count == 1 && ((Identifier)expression).Name == "old" && InEnsuresContext){
           OldExpression old = new OldExpression(arguments[0]);
           typeArguments = null;
           old.SourceContext = expression.SourceContext;
           old.SourceContext.EndPos = endCol;
           expression = old;
           break;
         }
         if (expression is TemplateInstance)
           ((TemplateInstance)expression).IsMethodTemplate = true;
         MethodCall mcall = new MethodCall(expression, arguments);
         typeArguments = null;
         mcall.GiveErrorIfSpecialNameMethod = true;
         mcall.SourceContext = expression.SourceContext;
         mcall.SourceContext.EndPos = endCol;
         mcall.ArgumentListIsIncomplete = this.scanner.GetChar(endCol-1) != ')';
         expression = mcall;
         break;
       case Token.LeftBrace:
         if (this.compatibilityOn || this.scanner.TokenIsFirstAfterLineBreak) goto default;
         Expression quant = this.ParseComprehension(followers);
         if (quant == null) { break; }
         Block argBlock = new Block(new StatementList(new ExpressionStatement(quant)),quant.SourceContext,
           this.insideCheckedBlock, this.insideUncheckedBlock, this.inUnsafeCode);
         argBlock.IsUnsafe = this.inUnsafeCode;
         argBlock.SourceContext = quant.SourceContext;
         ExpressionList arguments2 = new ExpressionList(new AnonymousNestedFunction(new ParameterList(0), argBlock, quant.SourceContext));
         MethodCall mcall2 = new MethodCall(expression, arguments2);
         typeArguments = null;
         mcall2.GiveErrorIfSpecialNameMethod = true;
         mcall2.SourceContext = expression.SourceContext;
         mcall2.SourceContext.EndPos = this.scanner.endPos;
         expression = mcall2;
         break;
       case Token.Dot:
         expression = this.ParseQualifiedIdentifier(expression, followersOrContinuers);
         break;
       case Token.RealLiteral:
         string tokStr = this.scanner.GetTokenSource();
         if (this.insideModifiesClause && tokStr == ".0") {
           // this case is here only for parsing ".0" while parsing a modifies clause
           // e.g., "modifies this.0;"
           this.GetNextToken(); // eat the ".0"
           return new ModifiesNothingClause(expression, this.scanner.CurrentSourceContext);
         } else {
           return expression;
         }
       case Token.Arrow:
         if (!this.allowUnsafeCode){
           this.HandleError(Error.IllegalUnsafe);
           this.allowUnsafeCode = true;
         }
         this.currentToken = Token.Dot;
         AddressDereference ad = new AddressDereference();
         ad.Address = expression;
         ad.ExplicitOperator = AddressDereference.ExplicitOp.Arrow;
         ad.SourceContext = expression.SourceContext;
         expression = this.ParseQualifiedIdentifier(ad, followersOrContinuers);
         break;
       default:
         return expression;
     }
   }
 }
Beispiel #25
0
    public override Expression VisitOldExpression(OldExpression oldExp) {
      Expression/*?*/ transformedExpression = oldExp;
      if (this.toplevelOldExpression == null) {
        this.toplevelOldExpression = oldExp;
        this.collectSubExpsDependentOnQuantifiedVars(oldExp);
        transformedExpression = this.markOldSubExps(oldExp);
      }
      if (transformedExpression != oldExp) {
        // if we are not at the toplevel, or the transformed top level is not the old expression, 
        // which means the old operator has been pushed down using the distribution law. 
        Expression result = this.VisitExpression(transformedExpression);
        if (this.toplevelOldExpression == oldExp) {
          // leave top level old expression
          this.toplevelOldExpression = null;
          this.subExpsDependentOnQuantifiedVars = null;
        }
        return result;
      } else {
        OldExpression oldExpression = transformedExpression as OldExpression;
        //^ assert oldExpression != null;
        TypeNode t = oldExpression.Type;
        Reference rt = t as Reference;
        Expression e = oldExpression.expression;
        if (rt != null) {
          e = new AddressDereference(e, rt.ElementType, e.SourceContext);
        }
        string oldName = e.SourceContext.SourceText != null && e.SourceContext.SourceText.Length > 0
          ? "old(" + e.SourceContext.SourceText + ")" : "$SSold" + e.UniqueKey;
        Local l = new Local(Identifier.For(oldName), e.Type);
        #region Add local to method's local list so it gets the right debug scope
        // Since the scope of the "old" local is the entire method body, it suffices
        // to add it to the method's local list. Because of how that is processed in Writer,
        // that means the local's scope will be the entire method body.
        if (this.currentMethod.LocalList == null) {
          this.currentMethod.LocalList = new LocalList();
        }
        this.currentMethod.LocalList.Add(l);
        #endregion
        // normalize the old expression itself
        e = this.VisitExpression(e);
        Statement a = this.initializeOldExp(l, e, oldExpression.ShallowCopyUptoDimension);
        
        this.currentContractPrelude.Statements.Add(a);
        this.currentContractPrelude.HasLocals = true;

        if (this.toplevelOldExpression == oldExpression) {
          this.toplevelOldExpression = null;
          this.subExpsDependentOnQuantifiedVars = null;
        }

        if (rt != null)
          return new UnaryExpression(l, NodeType.AddressOf, t, e.SourceContext);
        else
          return l;
      }
    }
	void Factor(Expression target, out Expression e) {
		e = null;
		Member  m;
		ExpressionList es; Expression p;
		Expression p1; Expression p2;
		TypeNode t1;
		/*Identifier blockVarId;*/
		MemberBinding mb;
		
		switch (la.kind) {
		case 2: case 3: case 4: case 70: case 71: case 72: case 73: case 74: case 75: {
			Literal(out e);
			break;
		}
		case 27: case 30: case 55: {
			Local(out p);
			e = p; 
			break;
		}
		case 1: case 6: case 7: case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15: case 16: case 17: case 18: case 19: case 20: case 21: case 25: case 26: case 28: case 35: {
			MemberRef(out m);
			Debug.Assert(m != null); e = new MemberBinding(target,m); 
			if (la.kind == 49) {
				ArgExprs(out es);
				Method meth = (Method)m;
				if ( ! meth.IsVirtual){
				 e = new MethodCall(e, es, NodeType.Call);
				}else{
				 e = new MethodCall(e, es, NodeType.Callvirt); /*dangerous*/
				}
				e.Type = meth.ReturnType;
				
			}
			break;
		}
		case 54: {
			BlockVar(out mb);
			Debug.Assert(target == null);
			e = mb;
			Debug.Assert(e != null);  // block variable not found
			
			break;
		}
		case 5: {
			Get();
			Expect(38);
			Expect(22);
			Expr(out e);
			OldExpression oe = new OldExpression(e);
			oe.Type = e.Type;
			e = oe;
			
			Expect(24);
			break;
		}
		case 22: {
			Get();
			Expr(out e);
			Expect(24);
			break;
		}
		case 39: {
			Get();
			Expect(22);
			Expr(out p);
			Expect(23);
			PType(out t1);
			Expect(24);
			e = new BinaryExpression(p,new Literal(t1,SystemTypes.Type),NodeType.ExplicitCoercion);
			e.Type = t1;
			
			break;
		}
		case 40: {
			Get();
			Expect(22);
			Expr(out p);
			Expect(23);
			PType(out t1);
			Expect(24);
			e = new BinaryExpression(p,new Literal(t1,SystemTypes.Type),NodeType.Is);
			e.Type = SystemTypes.Boolean;
			
			break;
		}
		case 41: {
			Get();
			Expect(22);
			Expr(out p);
			Expect(23);
			PType(out t1);
			Expect(24);
			e = new BinaryExpression(p,new Literal(t1,SystemTypes.Type),NodeType.Castclass);
			e.Type = t1;
			
			break;
		}
		case 42: {
			Get();
			Expect(22);
			PType(out t1);
			Expect(24);
			e = new UnaryExpression(new Literal(t1, SystemTypes.Type), NodeType.Typeof, OptionalModifier.For(SystemTypes.NonNullType, SystemTypes.Type));
			
			break;
		}
		case 43: {
			Get();
			Expect(22);
			Expr(out p);
			Expect(23);
			Expr(out p1);
			Expect(23);
			Expr(out p2);
			Expect(23);
			PType(out t1);
			Expect(24);
			e = new TernaryExpression(p,p1,p2,NodeType.Conditional,t1);
			
			break;
		}
		case 44: {
			Get();
			Expect(22);
			Expr(out p);
			Expect(23);
			PType(out t1);
			Expect(24);
			e = new BinaryExpression(p,new MemberBinding(null,t1),NodeType.Box);
			e.Type = SystemTypes.Object;
			
			break;
		}
		case 45: {
			Get();
			Expect(22);
			Expr(out p);
			Expect(23);
			PType(out t1);
			Expect(24);
			e = new BinaryExpression(p,new MemberBinding(null,t1),NodeType.Unbox);
			e.Type = t1.GetReferenceType();
			
			break;
		}
		case 46: {
			Get();
			Expect(22);
			Expr(out p);
			Expect(24);
			e = new UnaryExpression(p, NodeType.RefAddress, p.Type);
			
			break;
		}
		case 57: case 58: case 59: case 60: case 61: case 62: case 63: case 64: {
			Quantifier(out e);
			break;
		}
		case 65: {
			TrueComprehension(out e);
			break;
		}
		case 47: {
			Get();
			if (la.kind == 48 || la.kind == 51 || la.kind == 52) {
				if (la.kind == 48) {
					Get();
					Expect(22);
					PType(out t1);
					Expect(24);
					Expect(49);
					Expr(out p);
					Expect(50);
					TypeNode newType = p.Type.GetReferenceType();
					e = new UnaryExpression(p,NodeType.AddressOf,newType);
					
				} else if (la.kind == 51) {
					Get();
					Expect(49);
					Expr(out p);
					Expect(50);
					Reference r = (Reference) p.Type;
					if (r != null)
					 e = new AddressDereference(p,r.ElementType);
					else
					 e = new AddressDereference(p, SystemTypes.UInt8);
					
				} else {
					TypeNode tt1 = null, tt2 = null, tt3 = null; 
					Get();
					Expect(22);
					PType(out tt1);
					Expect(23);
					PType(out tt2);
					Expect(24);
					Expect(49);
					Expr(out p);
					Expect(23);
					PType(out tt3);
					Expect(50);
					e = new BinaryExpression(p, new Literal(tt3, SystemTypes.Type), NodeType.Isinst); e.Type = tt3; 
				}
			} else if (la.kind == 53) {
				TypeNode tt1 = null, tt2 = null, tt3 = null; 
				Get();
				Expect(22);
				PType(out tt1);
				Expect(23);
				PType(out tt2);
				Expect(24);
				Expect(49);
				Expr(out p);
				Expect(23);
				PType(out tt3);
				Expect(50);
				e = new BinaryExpression(p, new Literal(tt3, SystemTypes.Type), NodeType.Isinst); e.Type = tt3; 
			} else if (StartOf(2)) {
				OperatorNode(out p);
				e = p; 
			} else SynErr(111);
			break;
		}
		default: SynErr(112); break;
		}
	}
Beispiel #27
0
 public virtual Expression VisitOldExpression(OldExpression oldExpression1, OldExpression oldExpression2) {
   if (oldExpression1 == null) return null;
   if (oldExpression2 == null)
     oldExpression1.expression = this.VisitExpression(oldExpression1.expression, null);
   else
     oldExpression1.expression = this.VisitExpression(oldExpression1.expression, oldExpression2.expression);
   return oldExpression1;
 }
Beispiel #28
0
 public override Expression VisitOldExpression(OldExpression oldExpression) {
   if (oldExpression == null) return null;
   if (insidePureContract && insideEnsures)
     this.HandleError(oldExpression, Error.OldExprInPureEnsures);
   return base.VisitOldExpression(oldExpression);
 }
Beispiel #29
0
 public override Expression VisitOldExpression(OldExpression oldExpression) {
   if (oldExpression == null) return null;
   return base.VisitOldExpression((OldExpression)oldExpression.Clone());
 }
Beispiel #30
0
 public virtual Expression VisitOldExpression (OldExpression oldExpression) {
   if (oldExpression == null) return null;
   oldExpression.expression = this.VisitExpression(oldExpression.expression);
   return oldExpression;
 }
Beispiel #31
0
 public override Expression VisitOldExpression(OldExpression oldExpression) {
   if (oldExpression == null || oldExpression.expression == null) return null;
   if (this._string == null){ this._string = new StringBuilder(); }
   this._string.Append("\\old(");
   this.VisitExpression(oldExpression.expression);
   this._string.Append(")");
   return oldExpression;
 }
            public override void VisitOldExpression(OldExpression oldExpression)
            {
                if (oldExpression == null) return;

                // Make sure the argument to Old() isn't just a literal.
                if (oldExpression.expression is Literal)
                    this.HandleError(1000, "Literal expression in Old expression.");
                
                base.VisitOldExpression(oldExpression);
            }
        /// <summary>
        /// Performs a bunch of transformations that the basic Extractor doesn't seem to do:
        ///  - Turns calls to Old contract method into OldExpressions
        ///  - Turns references to "result" into ResultExpressions
        ///  - 
        /// </summary>
        public override Expression VisitMethodCall(MethodCall call)
        {
            MemberBinding mb = call.Callee as MemberBinding;
            if (mb == null) return call;

            Method calledMethod = mb.BoundMember as Method;
            if (calledMethod == null) return call;

            Method template = calledMethod.Template;
            if (contractNodes.IsOldMethod(template))
            {
                Expression result = base.VisitMethodCall(call);

                call = result as MethodCall;
                if (call == null) return result;

                result = new OldExpression(call.Operands[0]);
                result.Type = call.Type;

                return result;
            }

            if (contractNodes.IsValueAtReturnMethod(template))
            {
                return new AddressDereference(call.Operands[0], calledMethod.TemplateArguments[0], call.SourceContext);
            }

            if (calledMethod.Parameters != null)
            {
                if (calledMethod.Parameters.Count == 0)
                {
                    if (contractNodes.IsResultMethod(template))
                    {
                        return new ReturnValue(calledMethod.ReturnType, call.SourceContext);
                    }
                }
                else if (insideInvariant &&
                         contractNodes.IsInvariantMethod(calledMethod))
                {
                    Expression condition = call.Operands[0];
                    condition.SourceContext = call.SourceContext;

                    return VisitExpression(condition);
                }
            }

            return base.VisitMethodCall(call);
        }