示例#1
0
 public ExpressionStatement this[ExpressionStatement key] {
   get {
     ExpressionStatement result;
     this.orig2New.TryGetValue(key, out result);
     return result;
   }
 }
        // Requires:
        //  statement.Expression is MethodCall
        //  statement.Expression.Callee is MemberBinding
        //  statement.Expression.Callee.BoundMember is Method
        //  statement.Expression.Callee.BoundMember == "Requires" or "Ensures"
        //
        //  inline  <==> replacementMethod == null
        //  replacementMethod != null
        //           ==> replacementMethod.ReturnType == methodToReplace.ReturnType
        //               && replacementMethod.Parameters.Count == 1
        //               && methodToReplace.Parameters.Count == 1
        //               && replacementMethod.Parameters[0].Type == methodToReplace.Parameters[0].Type
        //
        private static Statement RewriteContractCall(
            ExpressionStatement statement,
            Method /*!*/ methodToReplace,
            Method /*?*/ replacementMethod,
            Literal /*?*/ sourceTextToUseAsSecondArg)
        {
            Contract.Requires(statement != null);

            MethodCall call = statement.Expression as MethodCall;

            if (call == null || call.Callee == null)
            {
                return statement;
            }

            MemberBinding mb = call.Callee as MemberBinding;
            if (mb == null)
            {
                return statement;
            }

            Method m = mb.BoundMember as Method;
            if (m == null)
            {
                return statement;
            }

            if (m != methodToReplace)
            {
                return statement;
            }

            mb.BoundMember = replacementMethod;

            if (call.Operands.Count == 3)
            {
                // then the invariant was found in a reference assembly
                // it already has all of its arguments
                return statement;
            }

            if (call.Operands.Count == 1)
            {
                call.Operands.Add(Literal.Null);
            }

            Literal extraArg = sourceTextToUseAsSecondArg;
            if (extraArg == null)
            {
                extraArg = Literal.Null;
                //extraArg = new Literal("No other information available", SystemTypes.String);
            }

            call.Operands.Add(extraArg);

            return statement;
        }
        public override void VisitExpressionStatement(ExpressionStatement statement)
        {
            Method methodCall = HelperMethods.IsMethodCall(statement);

            if (methodCall == this.contractNodes.AssertMethod ||
                methodCall == this.contractNodes.AssertWithMsgMethod ||
                methodCall == this.contractNodes.AssumeMethod ||
                methodCall == this.contractNodes.AssumeWithMsgMethod)
            {
                this.BadStuffFound = true;
            }

            base.VisitExpressionStatement(statement);
        }
示例#4
0
 public override Statement VisitExpressionStatement(ExpressionStatement statement) {
   Method contractMethod = Rewriter.ExtractCallFromStatement(statement);
   if (contractMethod == null) {
     return base.VisitExpressionStatement(statement);
   }
   if (this.rcm.ContractNodes.IsInvariantMethod(contractMethod))
   {
     Statement s =
       RewriteInvariant.RewriteContractCall(
       statement,
       contractMethod,
       this.rcm.InvariantMethod,
       this.sourceTextOfInvariant
     );
     return s;
   } else {
     return base.VisitExpressionStatement(statement);
   }
 }
示例#5
0
 public override void VisitExpressionStatement(ExpressionStatement statement)
 {
   if (statement == null) return;
   if (IsLiteral0Or1(statement.Expression))
   {
     // assume this is from an && or || shortcut evaluation. A single block
     // whack out its source context so code coverage handles it as covered
     statement.SourceContext = new SourceContext(HiddenDocument.Document);
   }
   base.VisitExpressionStatement(statement);
 }
示例#6
0
 public override InstanceInitializer InjectDefaultConstructor(TypeNode typeNode) {
   if (this.DontInjectDefaultConstructors || typeNode.IsNormalized) return null;
   Class Class = typeNode as Class;
   if (Class != null && Class.Name != null && !(Class is ClassParameter) && ClassHasNoExplicitConstructors(typeNode)) {
     if (Class.IsAbstractSealedContainerForStatics) return null;
     if (Class.PartiallyDefines != null){
       this.InjectDefaultConstructor(Class.PartiallyDefines);
       InstanceInitializer defCons = Class.PartiallyDefines.GetConstructor();
       if (defCons != null && !defCons.HasCompilerGeneratedSignature) 
         defCons = null; //Not an orphan
       if (defCons != null){
         //This is an injected default constructor that is an orphan, adopt it
         defCons.HasCompilerGeneratedSignature = false; //abuse this flag to stop other partial types from adopting it
         Class.Members.Add(defCons);
         Class.BaseClass = ((Class)Class.PartiallyDefines).BaseClass;
       }
       return defCons; //Ok if defCons null, this type should not show up in inheritance chains
     }else{
       //Inject a default constructor
       This thisParameter = new This(Class);
       Class baseClass = Class.BaseClass;
       StatementList statements = new StatementList(2);
       statements.Add(new FieldInitializerBlock(typeNode, false));
       if (baseClass != null) {
         MethodCall mcall = new MethodCall(new QualifiedIdentifier(new Base(), StandardIds.Ctor, typeNode.Name.SourceContext), null);
         mcall.SourceContext = typeNode.Name.SourceContext;
         ExpressionStatement callSupCons = new ExpressionStatement(mcall);
         callSupCons.SourceContext = typeNode.Name.SourceContext;
         statements.Add(callSupCons);
       }
       InstanceInitializer defCons = new InstanceInitializer(typeNode, null, null, new Block(statements));
       defCons.Name = new Identifier(".ctor", typeNode.Name.SourceContext);
       defCons.SourceContext = typeNode.Name.SourceContext;
       defCons.ThisParameter = thisParameter;
       if (typeNode.IsAbstract)
         defCons.Flags |= MethodFlags.Family|MethodFlags.HideBySig;
       else
         defCons.Flags |= MethodFlags.Public|MethodFlags.HideBySig;
       defCons.CallingConvention = CallingConventionFlags.HasThis;
       defCons.IsCompilerGenerated = true;
       typeNode.Members.Add(defCons);
       return defCons;
     }
   }
   return null;
 }
示例#7
0
 internal void RecordNecessaryCheck(ExpressionStatement es) {
   if (es == null || !eliminateCheck.ContainsKey(es)) return;
   eliminateCheck.Remove(es);
 }
示例#8
0
        /// <summary>
        /// Method replaces Requires to Assume in the MoveNext method of the async or iterator state machine.
        /// </summary>
        private void ReplaceRequiresWithAssumeInMoveNext(RequiresList origPreconditions, AssumeBlock originalContractPosition)
        {
            Contract.Assert(origPreconditions != null);

            if (originalContractPosition != null && originalContractPosition.Statements != null
                /*&& origPreconditions != null */&& origPreconditions.Count > 0)
            {
                var origStatements = originalContractPosition.Statements;
                foreach (var pre in origPreconditions)
                {
                    if (pre == null) continue;

                    var assume = new MethodCall(
                        new MemberBinding(null, this.contractNodes.AssumeMethod),
                        new ExpressionList(pre.Condition), NodeType.Call);

                    assume.SourceContext = pre.SourceContext;
                    var assumeStmt = new ExpressionStatement(assume);

                    assumeStmt.SourceContext = pre.SourceContext;
                    origStatements.Add(assumeStmt);
                }
            }
        }
示例#9
0
        public override Statement VisitExpressionStatement(ExpressionStatement statement)
        {
            // Check for statements that require special handling
            AssignmentExpression assignmentExpr = statement.Expression as AssignmentExpression;
            AssignmentStatement assignmentStatement = null;
            MethodCall methodCall = statement.Expression as MethodCall;
            UnaryExpression choose = null;

            if (assignmentExpr != null)
            {
                assignmentStatement = assignmentExpr.AssignmentStatement as AssignmentStatement;
                if (assignmentStatement != null && assignmentStatement.Source is MethodCall)
                    methodCall = (MethodCall)assignmentStatement.Source;

                if (assignmentStatement != null && assignmentStatement.Source is UnaryExpression &&
                    assignmentStatement.Source.NodeType == (NodeType)ZingNodeType.Choose)
                    choose = (UnaryExpression)assignmentStatement.Source;
            }

            if (methodCall != null)
            {
                Block stmtBlock = new Block();
                stmtBlock.Statements = new StatementList();

                // The following if statement (and the if-branch) added by Jiri Adamek
                // Reason: the NativeZOM method calls are generated differntly from
                //         common Zing method calls
                // The original code is in the else-branch
                if (((MemberBinding)methodCall.Callee).BoundMember.DeclaringType is NativeZOM)
                {
                    GenerateNativeZOMCall(stmtBlock, methodCall, statement is AsyncMethodCall, assignmentStatement);
                }
                else
                {
                    if (this.secondOfTwo)
                        GenerateMethodReturn(stmtBlock, assignmentStatement, methodCall);
                    else
                        GenerateMethodCall(stmtBlock, methodCall, statement is AsyncMethodCall);
                }

                return stmtBlock;
            }
            else if (choose != null)
            {
                Statement chooseStmt;

                if (this.secondOfTwo)
                {
                    // Finishing a "choose" is always the same...
                    chooseStmt = Templates.GetStatementTemplate("FinishChoose");
                    TypeNode tn = choose.Type;
                    if (tn is Set || tn is ZArray || tn is Class || tn is Chan)
                        Replacer.Replace(chooseStmt, "_targetType", new Identifier("Pointer"));
                    else
                        Replacer.Replace(chooseStmt, "_targetType", this.VisitExpression(choose.Type.Name));

                    Replacer.Replace(chooseStmt, "_target", this.VisitExpression(assignmentStatement.Target));
                }
                else
                {
                    // Starting a "choose" is different for the static and dynamic cases
                    if (choose.Operand.Type.FullName == "Boolean")
                    {
                        chooseStmt = Templates.GetStatementTemplate("StartChooseByBoolType");
                    }
                    else if (choose.Operand.Type == SystemTypes.Type)
                    {
                        // static
                        Literal lit = choose.Operand as Literal;
                        Debug.Assert(lit != null);
                        TypeNode tn = lit.Value as TypeNode;
                        Debug.Assert(tn != null);
                        chooseStmt = Templates.GetStatementTemplate("StartChooseByType");
                        Replacer.Replace(chooseStmt, "_typeExpr", new QualifiedIdentifier(new Identifier("Application"), tn.Name));
                    }
                    else
                    {
                        // dynamic
                        chooseStmt = Templates.GetStatementTemplate("StartChooseByValue");
                        Replacer.Replace(chooseStmt, "_ptrExpr", this.VisitExpression(choose.Operand));
                    }
                }

                return chooseStmt;
            }
            else if (assignmentStatement != null && assignmentStatement.Target.Type is Set &&
                assignmentStatement.Source is BinaryExpression)
            {
                BinaryExpression binaryExpression = (BinaryExpression)assignmentStatement.Source;
                Statement setOpStmt;

                if (binaryExpression.Operand1.Type == binaryExpression.Operand2.Type)
                {
                    if (binaryExpression.NodeType == NodeType.Add)
                        setOpStmt = Templates.GetStatementTemplate("SetAddSet");
                    else
                        setOpStmt = Templates.GetStatementTemplate("SetRemoveSet");
                }
                else
                {
                    if (binaryExpression.NodeType == NodeType.Add)
                        setOpStmt = Templates.GetStatementTemplate("SetAddItem");
                    else
                        setOpStmt = Templates.GetStatementTemplate("SetRemoveItem");
                }

                Replacer.Replace(setOpStmt, "_ptrExpr", this.VisitExpression(binaryExpression.Operand1));
                Replacer.Replace(setOpStmt, "_itemExpr", this.VisitExpression(binaryExpression.Operand2));

                return setOpStmt;
            }
            else
            {
                // The default scenario...

                inExpressionStatement = true;
                Expression newExpr = this.VisitExpression(statement.Expression);
                inExpressionStatement = false;

                //
                // In some scenarios, a simple assignment becomes something much more
                // complicated. We have to detect when such a case has occurred and
                // return the more complex statement directly rather than leaving it
                // embedded within an ExpressionStatement.
                //
                AssignmentExpression newAssignmentExpr = newExpr as AssignmentExpression;
                if (newAssignmentExpr != null && !(newAssignmentExpr.AssignmentStatement is AssignmentStatement))
                    return newAssignmentExpr.AssignmentStatement;

                Statement result = new ExpressionStatement(newExpr, statement.SourceContext);
                return result;
            }
        }
示例#10
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
      }
    }
示例#11
0
 public virtual Statement VisitExpressionStatement(ExpressionStatement statement)
 {
     if (statement == null) return null;
     statement.Expression = this.VisitExpression(statement.Expression);
     return statement;
 }
示例#12
0
 public override Statement VisitExpressionStatement(ExpressionStatement statement)
 {
     if (statement == null) return null;
     Expression e = statement.Expression = this.VisitExpression(statement.Expression);
     if (e == null || e.Type == CoreSystemTypes.Void) return statement;
     if (e.NodeType == NodeType.Dup) return this.localsStack.Dup();
     return this.localsStack.Push(e);
 }
示例#13
0
      // Requires:
      //  statement.Expression is MethodCall
      //  statement.Expression.Callee is MemberBinding
      //  statement.Expression.Callee.BoundMember is Method
      //  statement.Expression.Callee.BoundMember == "Assert" or "Assume"
      //
      //  replacementMethod.ReturnType == methodToReplace.ReturnType
      //  && replacementMethod.Parameters.Count == 1
      //  && methodToReplace.Parameters.Count == 1
      //  && replacementMethod.Parameters[0].Type == methodToReplace.Parameters[0].Type
      //
      private static Statement RewriteContractCall(
        MethodCall call,
        ExpressionStatement statement,
        Method/*!*/ methodToReplace,
        Method/*?*/ replacementMethod
        )
      {
        Contract.Requires(call != null);

        Debug.Assert(call == statement.Expression as MethodCall);

        MemberBinding mb = (MemberBinding)call.Callee;
        Debug.Assert(mb.BoundMember == methodToReplace);

        mb.BoundMember = replacementMethod;

        if (call.Operands.Count == 1)
        {
          call.Operands.Add(Literal.Null);
        }

#if false
        SourceContext sctx = statement.SourceContext;
        if (sctx.IsValid && sctx.Document.Text != null && sctx.Document.Text.Source != null)
        {
          call.Operands.Add(new Literal(sctx.Document.Text.Source, SystemTypes.String));
        }
#else
        ContractAssumeAssertStatement casas = statement as ContractAssumeAssertStatement;
        if (casas != null) {
          call.Operands.Add(new Literal(casas.SourceText, SystemTypes.String));
        }
#endif
        else {
          call.Operands.Add(Literal.Null);
          //call.Operands.Add(new Literal("No other information available", SystemTypes.String));
        }

        return statement;
      }
示例#14
0
    /// <summary>
    /// </summary>
    /// <param name="expr_stat">Cloned</param>
    /// <returns></returns>
    public override Statement VisitExpressionStatement(ExpressionStatement expr_stat) {
      // The AST may have shared nodes. 
      if (this.orig2Copy.ContainsKey(expr_stat)) {
        return this.orig2Copy[expr_stat];
      }
      Expression newexpr = this.VisitExpression(expr_stat.Expression);
      if (newexpr == null) {
        // turn into nop statement
        return new Statement(NodeType.Nop);
      }
      // check for special case where we now have a PopExpression as the expression.
      // this corresponds to a push(pop), which is a noop and we need to represent it that way.
      if (newexpr.NodeType == NodeType.Pop && !(newexpr is UnaryExpression)) {
        return new Statement(NodeType.Nop);
      }
      ExpressionStatement copy = (ExpressionStatement)expr_stat.Clone();
      copy.Expression = newexpr;
      copy.SourceContext = this.current_source_context;
      this.orig2Copy.Add(expr_stat, copy);

      return copy;
    }
示例#15
0
    /// <summary>
    /// </summary>
    /// <param name="cons">Cloned</param>
    /// <returns></returns>
		public override Expression VisitConstruct(Construct cons)
		{
			ExpressionList operands = this.VisitExpressionList(cons.Operands);
			MemberBinding mb = this.VisitExpression(cons.Constructor) as MemberBinding;
      if (mb == null) return null;

			Debug.Assert(mb.TargetObject == null, "constructor target not null!");

			if ( this.expandAllocations ) 
			{
				// Now split the expression into 3:
				//  allocTemp = new T;
				//  allocTemp..ctor(args...);
				//  allocTemp

				// For value types, the construction is even more involved:
				//  valTemp = new VT;
				//  allocTemp = &valTemp;
				//  allocTemp..ctor(args...);
				//  valTemp

				if (mb.BoundMember != null && mb.BoundMember.DeclaringType != null && mb.BoundMember.DeclaringType.IsValueType) 
				{
					Variable valTemp = StackVariable.NEWValueTemp(mb.BoundMember.DeclaringType);

					Construct newcons = new Construct(new MemberBinding(null, mb.BoundMember), new ExpressionList(0), mb.BoundMember.DeclaringType);
					AssignmentStatement new_stat = new AssignmentStatement(valTemp, newcons);
					new_stat.SourceContext = this.current_source_context;
					new_stats.Add(new_stat);

          Variable allocTemp = StackVariable.NEWTemp(mb.BoundMember.DeclaringType);
          new_stats.Add(new AssignmentStatement(allocTemp, new UnaryExpression(valTemp, NodeType.AddressOf, mb.BoundMember.DeclaringType.GetReferenceType()), NodeType.Nop));
          mb.TargetObject = allocTemp;

					ExpressionStatement call_stat = new ExpressionStatement(new MethodCall(mb, operands, NodeType.Call, Cci.SystemTypes.Void));
					call_stat.SourceContext = this.current_source_context;
					new_stats.Add(call_stat);

					return valTemp;
				}
				else 
				{
					Variable vtemp = StackVariable.NEWTemp(mb.BoundMember.DeclaringType);

					Construct newcons = new Construct(new MemberBinding(null, mb.BoundMember), new ExpressionList(0), mb.BoundMember.DeclaringType);
					AssignmentStatement new_stat = new AssignmentStatement(vtemp, newcons);
					new_stat.SourceContext = this.current_source_context;
					new_stats.Add(new_stat);

					mb.TargetObject = vtemp;

					ExpressionStatement call_stat = new ExpressionStatement(new MethodCall(mb, operands, NodeType.Call, Cci.SystemTypes.Void));
					call_stat.SourceContext = this.current_source_context;
					new_stats.Add(call_stat);

					return vtemp;
				}
			}
			else 
			{
				Construct newcons = new Construct(mb, operands, mb.BoundMember.DeclaringType);
				newcons.SourceContext = this.current_source_context;

				return newcons;
			}
		}
示例#16
0
		private Expression pushPop(Expression expression) 
		{
      SourceContext ctxt = expression.SourceContext.Document != null? expression.SourceContext:this.current_source_context;

			ExpressionStatement new_stat = new ExpressionStatement(expression, ctxt);
			Debug.Assert(new_stats != null, "must have been initialized by now.");

			new_stats.Add(new_stat);
      return Pop(expression.Type, ctxt);
		}
示例#17
0
 private void WarnIfExplicit(ExpressionStatement es) {
   if (es == null) return;
   MethodCall mcall = es.Expression as MethodCall;
   if (mcall == null) return;
   MemberBinding mb = mcall.Callee as MemberBinding;
   if (mb == null) return;
   if (checker.IsAssertNotNullMethod(mb.BoundMember as Method)) {
     checker.HandleError(es, mcall, Error.UnnecessaryNonNullCoercion);
   }
 }
示例#18
0
		public override Statement VisitExpressionStatement(ExpressionStatement statement)
		{
			// skip VisitExpression because these could be of a form that do not produce a value, in which case we don't want to introduce a BlockExpression
			statement.Expression = (Expression)this.Visit(statement.Expression);

			return statement;
		}
示例#19
0
      public override Statement VisitExpressionStatement(ExpressionStatement statement)
      {
        MethodCall call;
        Method contractMethod = Rewriter.ExtractCallFromStatement(statement, out call);
        if (contractMethod == null)
        {
          return base.VisitExpressionStatement(statement);
        }
        Method keyToLookUp = contractMethod;
        if (this.methodTable.ContainsKey(keyToLookUp))
        {
          var isAssert = keyToLookUp.Name.Name == "Assert";
          Method repMethod;
          if (isAssert)
          {
            repMethod = this.runtimeContracts.AssertMethod;
          }
          else
          {
            // assume it is Assume
            repMethod = this.runtimeContracts.AssumeMethod;
          }
          if (repMethod == null)
          {
            return base.VisitExpressionStatement(statement);
          }
          if (isAssert && (!this.emitFlags.Emit(RuntimeContractEmitFlags.Asserts) || this.runtimeContracts.PublicSurfaceOnly))
          {
            var pops = CountPopExpressions.Count(call);
            if (pops > 0)
            {
              var block = new Block(new StatementList(pops));
              while (pops-- > 0)
              {
                // emit a pop
                block.Statements.Add(new ExpressionStatement(new UnaryExpression(null, NodeType.Pop)));
              }
              return block;
            }
            return null;
          }
          if (!isAssert && (!this.emitFlags.Emit(RuntimeContractEmitFlags.Assumes) || this.runtimeContracts.PublicSurfaceOnly))
          {
            var pops = CountPopExpressions.Count(call);
            if (pops > 0)
            {
              var block = new Block(new StatementList(pops));
              while (pops-- > 0)
              {
                // emit a pop
                block.Statements.Add(new ExpressionStatement(new UnaryExpression(null, NodeType.Pop)));
              }
              return block;
            }
            return null;
          }
          var result =
            RewriteAssertAssumeAndCallSiteRequires.RewriteContractCall(
            call,
            statement,
            contractMethod,
            repMethod
          );
 
          return result;
        }
        else
        {
          return base.VisitExpressionStatement(statement);
        }
      }
示例#20
0
 private StatementList ParseForIncrementer(TokenSet followers){
   StatementList statements = new StatementList();
   if (this.currentToken == Token.RightParenthesis)
     return statements;
   TokenSet followerOrComma = followers|Token.Comma;
   for(;;){
     Expression e = this.ParseExpression(followerOrComma);
     if (e == null) return statements;
     if (!(e is AssignmentExpression || e is MethodCall || e is PostfixExpression || e is PrefixExpression || e is Construct))
       this.HandleError(e.SourceContext, Error.IllegalStatement);
     Statement s = new ExpressionStatement(e);
     s.SourceContext = e.SourceContext;
     statements.Add(s);
     if (this.currentToken != Token.Comma) break;
     this.GetNextToken();
   }
   this.SkipTo(followers);
   return statements;
 }
示例#21
0
 private Statement ParseNewStatement(TokenSet followers, bool preferExpressionToDeclaration){
   Debug.Assert(this.currentToken == Token.New);
   Expression e = this.ParseExpression(followers);
   Statement s = new ExpressionStatement(e);
   s.SourceContext = e.SourceContext;
   if (this.currentToken == Token.Semicolon || !preferExpressionToDeclaration)
     this.SkipSemiColon(followers);
   this.SkipTo(followers);
   return s;
 }
示例#22
0
 private Statement ParseObjectLiteralStatement(TokenSet followers, bool preferExpressionToDeclaration){
   Expression e = this.ParseObjectLiteral(followers|Token.Semicolon);
   ExpressionStatement es = new ExpressionStatement(e);
   es.SourceContext = e.SourceContext;
   if (this.currentToken == Token.Semicolon || !preferExpressionToDeclaration)
     this.SkipSemiColon(followers);
   this.SkipTo(followers);
   return es;
 }
示例#23
0
            public override void VisitExpressionStatement(ExpressionStatement estmt)
            {
                Expression source = estmt.Expression;
                Construct sourceConstruct = source as Construct;

                if (sourceConstruct != null)
                {
                    if (sourceConstruct.Type != null && sourceConstruct.Type.Name.Name.StartsWith(this.closureTag))
                    {
                        if (sourceConstruct.Type.Template != null)
                        {
                            TypeNode template = sourceConstruct.Type.Template;
                            while (template.Template != null)
                            {
                                template = template.Template;
                            }

                            this.closureClass = (Class) template;
                        }
                        else
                        {
                            this.closureClass = (Class) sourceConstruct.Type;
                        }
                    }
                }
            }
示例#24
0
 private Statement ParseExpressionStatementOrDeclaration(bool acceptComma, TokenSet followers, bool preferExpressionToDeclaration, bool skipSemicolon){
   SourceContext startingContext = this.scanner.CurrentSourceContext;
   ScannerState ss = this.scanner.state;
   Token tok = this.currentToken;
   TypeNode t = this.ParseTypeOrFunctionTypeExpression(followers|Parser.IdentifierOrNonReservedKeyword, true, false);
   if (t is PointerTypeExpression && !this.inUnsafeCode)
     this.HandleError(t.SourceContext, Error.UnsafeNeeded);
   if (t == null || (!Parser.IdentifierOrNonReservedKeyword[this.currentToken] &&
       (this.sink == null || this.currentToken == Token.LeftParenthesis ||
       (this.currentToken == Token.EndOfFile && (t.TemplateArguments == null || t.TemplateArguments.Count == 0))))){
     //Tried to parse a type expression and failed, or clearly not dealing with a declaration.
     //Restore prior state and reparse as expression
     this.scanner.state = ss;
     this.scanner.endPos = startingContext.StartPos;
     this.currentToken = Token.None;
     this.GetNextToken();
     TokenSet followersOrCommaOrColon = followers|Token.Comma|Token.Colon;
     Expression e = this.ParseExpression(followersOrCommaOrColon);
     ExpressionStatement eStat = new ExpressionStatement(e, startingContext);
     if (e != null) eStat.SourceContext = e.SourceContext;
     Identifier id = null;
     if (this.currentToken == Token.Colon && !acceptComma && (id = e as Identifier) != null)
       return this.ParseLabeledStatement(id, followers);
     if (!acceptComma || this.currentToken != Token.Comma){
       if (!preferExpressionToDeclaration){
         if (!(e == null || e is AssignmentExpression || e is QueryExpression ||
           e is MethodCall || e is PostfixExpression || e is PrefixExpression ||
           e is Construct || followers[Token.RightParenthesis] ||
           (e is Base && this.currentCtor != null && this.inInstanceConstructor == BaseOrThisCallKind.ColonThisOrBaseSeen)
           )
           )
           this.HandleError(e.SourceContext, Error.IllegalStatement);
         if (this.currentToken == Token.Semicolon)
           this.GetNextToken();
         else if (skipSemicolon)
           this.SkipSemiColon(followers);
       }else if (skipSemicolon && (this.currentToken != Token.RightBrace || !followers[Token.RightBrace])){
         if (this.currentToken == Token.Semicolon && followers[Token.RightBrace]){
           //Dealing with an expression block.
           this.GetNextToken();
           if (this.currentToken != Token.RightBrace){
             //Not the last expression in the block. Complain if it is not a valid expression statement.
             if (!(e == null || e is AssignmentExpression || e is MethodCall || e is PostfixExpression || e is PrefixExpression || e is Construct || followers[Token.RightParenthesis]))
               this.HandleError(e.SourceContext, Error.IllegalStatement);
           }
         }else{
           if (this.currentToken == Token.Comma && this.arrayInitializerOpeningContext != null){
             startingContext = (SourceContext)this.arrayInitializerOpeningContext;
             this.scanner.endPos = startingContext.StartPos;
             this.scanner.state = ss;
             this.currentToken = Token.None;
             this.GetNextToken();
             this.HandleError(Error.ArrayInitToNonArrayType);
             this.ParseArrayInitializer(1, this.TypeExpressionFor(Token.Object), followers, true);
             return null;
           }
           if (this.currentToken == Token.Comma){
             this.HandleError(Error.ExpectedSemicolon);
             this.GetNextToken();
           }else
             this.SkipSemiColon(followers);
         }
       }
       this.SkipTo(followers);
     }
     return eStat;
   }
   return this.ParseLocalDeclarations(t, startingContext, false, false, preferExpressionToDeclaration, skipSemicolon, followers|Parser.UnaryStart);
 }
示例#25
0
        public override Statement VisitAssignmentStatement(AssignmentStatement assignment)
        {
            if (assignment.Source == null || assignment.Target == null)
                return null;

            Expression normalizedSource = this.VisitExpression(assignment.Source);
            Expression normalizedTarget = this.VisitExpression(assignment.Target);

            assignment.Source = normalizedSource;
            assignment.Target = normalizedTarget;

            if (inExpressionStatement)
                return assignment;
            else
            {
                // This form shows up in initialized local variables. We have to wrap the
                // assignment back up to get the decompiler to generate appropriate code.
                ExpressionStatement exprStmt = new ExpressionStatement(new AssignmentExpression(assignment));
                exprStmt.SourceContext = assignment.SourceContext;
                return exprStmt;
            }
        }
示例#26
0
 private Statement ParseLocalDeclarations(TypeNode t, SourceContext ctx, bool constant, bool initOnly, bool preferExpressionToDeclaration, bool skipSemicolon, TokenSet followers){
   TypeNode firstT = t;
   LocalDeclarationsStatement result = new LocalDeclarationsStatement();
   result.SourceContext = ctx;
   result.Constant = constant;
   result.InitOnly = initOnly;
   ScannerState oss = this.scanner.state;
   LocalDeclarationList locList = result.Declarations = new LocalDeclarationList();
   result.Type = result.TypeExpression = t;
   for(;;){
     LocalDeclaration loc = new LocalDeclaration();
     loc.SourceContext = this.scanner.CurrentSourceContext;
     locList.Add(loc);
     loc.Name = this.scanner.GetIdentifier();
     this.SkipIdentifierOrNonReservedKeyword();
     if (this.currentToken == Token.LeftBracket){
       this.HandleError(Error.CStyleArray);
       int endPos = this.scanner.endPos;
       int rank = this.ParseRankSpecifier(true, followers|Token.RightBracket|Parser.IdentifierOrNonReservedKeyword|Token.Assign|Token.Semicolon|Token.Comma);
       if (rank > 0)
         t = result.Type = result.TypeExpression =
           this.ParseArrayType(rank, t, followers|Token.RightBracket|Parser.IdentifierOrNonReservedKeyword|Token.Assign|Token.Semicolon|Token.Comma);
       else{
         this.currentToken = Token.LeftBracket;
         this.scanner.endPos = endPos;
         this.GetNextToken();
         while (!this.scanner.TokenIsFirstAfterLineBreak &&
           this.currentToken != Token.RightBracket && this.currentToken != Token.Assign && this.currentToken != Token.Semicolon)
           this.GetNextToken();
         if (this.currentToken == Token.RightBracket) this.GetNextToken();
       }
     }
     if (this.currentToken == Token.LeftParenthesis){
       this.HandleError(Error.BadVarDecl);
       int dummy;
       SourceContext lpCtx = this.scanner.CurrentSourceContext;
       this.GetNextToken();
       this.ParseArgumentList(followers|Token.LeftBrace|Token.Semicolon|Token.Comma, lpCtx, out dummy);
     }else if (this.currentToken == Token.Assign || constant){
       this.Skip(Token.Assign);
       if (this.currentToken == Token.LeftBrace)
         loc.InitialValue = this.ParseArrayInitializer(t, followers|Token.Semicolon|Token.Comma);
       else
         loc.InitialValue = this.ParseExpression(followers|Token.Semicolon|Token.Comma);
     }
     if (loc.InitialValue != null)
       loc.SourceContext.EndPos = loc.InitialValue.SourceContext.EndPos;
     else
       loc.SourceContext.EndPos = this.scanner.endPos;
     if (this.currentToken != Token.Comma) break;
     this.GetNextToken();
     SourceContext sctx = this.scanner.CurrentSourceContext;
     ScannerState ss = this.scanner.state;
     TypeNode ty = this.ParseTypeExpression(null, followers|Token.Identifier|Token.Comma|Token.Semicolon, true);
     if (ty == null || this.currentToken != Token.Identifier){
       this.scanner.endPos = sctx.StartPos;
       this.scanner.state = ss;
       this.currentToken = Token.None;
       this.GetNextToken();
     }else
       this.HandleError(sctx, Error.MultiTypeInDeclaration);
   }
   if (Parser.IsVoidType(firstT)){
     this.HandleError(ctx, Error.NoVoidHere);
     result.Type = this.TypeExpressionFor(Token.Object);
     result.Type.SourceContext = firstT.SourceContext;
   }
   if (preferExpressionToDeclaration && this.currentToken != Token.Semicolon && locList.Count == 1 && locList[0].InitialValue == null){
     //The parse as a declaration is going to fail. Since an expression is preferred, restore the state and reparse as an expression
     this.scanner.endPos = ctx.StartPos;
     this.scanner.state = oss;
     this.currentToken = Token.None;
     this.GetNextToken();
     ExpressionStatement eStat = new ExpressionStatement(this.ParseExpression(followers));
     if (eStat.Expression != null) eStat.SourceContext = eStat.Expression.SourceContext;
     return eStat;
   }
   if (skipSemicolon) this.SkipSemiColon(followers);
   this.SkipTo(followers);
   return result;
 }
示例#27
0
        // The method added by Jiri Adamek
        // It generates NAtiveZOM calls
        private void GenerateNativeZOMCall(Block block, MethodCall call, bool callIsAsync, AssignmentStatement assignmentStatement)
        {
            ZMethod method = (ZMethod)((MemberBinding)call.Callee).BoundMember;

            // Eventually, this will be checked by an earlier phase.
            Debug.Assert(method.Parameters.Count == call.Operands.Count);

            // Asynchronous calls
            Debug.Assert(!callIsAsync, "async not supporrted for NativeZOM calls");

            // Debugging - parameters
            for (int i = 0, n = call.Operands.Count; i < n; i++)
            {
                Parameter param = method.Parameters[i];

                Debug.Assert(param != null);

                // In fact, call.operands[i] MAY BE null due to the error recovery (if the type of the
                // expression does not match the type in the method definition)
                //
                // Debug.Assert(call.Operands[i] != null);

                Debug.Assert((param.Flags & ParameterFlags.Out) == 0, "out parameters not supported for NativeZOM calls");
            }

            Expression typename = new QualifiedIdentifier(new Identifier("Microsoft.Zing"), method.DeclaringType.Name);
            Expression callee;

            if (!method.IsStatic)
            {
                callee = Templates.GetExpressionTemplate("NativeZOMCallee");
                Replacer.Replace(callee, "_TypeName", typename);
                Expression pointer = this.VisitExpression(((MemberBinding)call.Callee).TargetObject);
                Replacer.Replace(callee, "_Pointer", pointer);
                Replacer.Replace(callee, "_MethodName", method.Name);
            }
            else
            {
                callee = Templates.GetExpressionTemplate("NativeZOMStaticCall");
                Replacer.Replace(callee, "_ClassName", typename);
                Replacer.Replace(callee, "_MethodName", method.Name);
            }

            ExpressionList argumentList = new ExpressionList();
            argumentList.Add(Templates.GetExpressionTemplate("NativeZOMCallFirstArgument"));
            foreach (Expression operand in call.Operands) argumentList.Add(this.VisitExpression(operand));
            MethodCall nativeCall = new MethodCall(callee, argumentList);

            Statement newStatement;
            if (assignmentStatement != null)
            {
                newStatement = Templates.GetStatementTemplate("NativeZOMCallWithAssignment");
                Replacer.Replace(newStatement, "_Dest", this.VisitExpression(assignmentStatement.Target));
                Replacer.Replace(newStatement, "_Source", nativeCall);
            }
            else
            {
                newStatement = new ExpressionStatement(nativeCall);
            }

            block.Statements.Add(newStatement);
        }
示例#28
0
 public override Statement VisitExpressionStatement(ExpressionStatement statement)
 {
     if (statement == null) return null;
     return base.VisitExpressionStatement((ExpressionStatement)statement.Clone());
 }
示例#29
0
        public override Statement VisitExpressionStatement(ExpressionStatement statement)
        {
            WriteStart(string.Empty);

            int len = this.SourceLength;
            base.VisitExpressionStatement(statement);
            if (len != this.SourceLength)
                Write(";");

            WriteFinish(string.Empty);

            return statement;
        }
示例#30
0
 internal void RecordUnnecessaryCheck(ExpressionStatement es) {
   if (es == null) return;
   eliminateCheck[es] = true;
 }