public override Expression VisitReturnValue(ReturnValue returnValue)
        {
            // return a default value of the same type as the return value
            TypeNode returnType = returnValue.Type;
            ITypeParameter itp = returnType as ITypeParameter;
            if (itp != null)
            {
                Local loc = new Local(returnType);

                UnaryExpression loca = new UnaryExpression(loc, NodeType.AddressOf, loc.Type.GetReferenceType());
                StatementList statements = new StatementList(2);

                statements.Add(new AssignmentStatement(new AddressDereference(loca, returnType, false, 0),
                    new Literal(null, SystemTypes.Object)));

                statements.Add(new ExpressionStatement(loc));

                return new BlockExpression(new Block(statements), returnType);
            }

            if (returnType.IsValueType)
                return new Literal(0, returnType);
            
            return new Literal(null, returnType);
        }
Esempio n. 2
0
        //
        // Our notion of "sizeof" is more flexible - the operand can be either a type or
        // an expression, so we don't want to use the base checker in that case.
        //
        public override Expression VisitUnaryExpression(UnaryExpression unaryExpression)
        {
            if (unaryExpression.NodeType != NodeType.Sizeof)
                return base.VisitUnaryExpression(unaryExpression);

            unaryExpression.Operand = (Expression)this.Visit(unaryExpression.Operand);

            if (unaryExpression.Operand == null)
                return null;

            if (unaryExpression.Operand is Literal)
            {
                // If the operand is a literal, it must be an array type reference
                Literal operand = (Literal)unaryExpression.Operand;

                if (!(operand.Value is ZArray))
                {
                    this.HandleError(unaryExpression.Operand, Error.InvalidSizeofOperand);
                    return null;
                }
            }
            else
            {
                // If the operand is an expression, it must refer to an array, set, or channel.
                TypeNode opndType = unaryExpression.Operand.Type;

                if (!(opndType is ZArray) && !(opndType is Set) && !(opndType is Chan))
                {
                    this.HandleError(unaryExpression.Operand, Error.InvalidSizeofOperand);
                    return null;
                }
            }

            return unaryExpression;
        }
Esempio n. 3
0
        public override Expression VisitUnaryExpression(UnaryExpression unaryExpression)
        {
            bool isFunctionStyle;
            string opString;

            opString = GetUnaryOperator(unaryExpression.NodeType, out isFunctionStyle);

            if (isFunctionStyle)
            {
                Write("{0}(", opString);
                this.VisitExpression(unaryExpression.Operand);
                Write(")");
            }
            else
            {
                Write(opString);
                this.VisitExpression(unaryExpression.Operand);
            }
            return unaryExpression;
        }
Esempio n. 4
0
        public override Expression VisitUnaryExpression(UnaryExpression unaryExpression)
        {
            Expression result = base.VisitUnaryExpression(unaryExpression);

            // The result of sizeof() is always Int32.
            if (unaryExpression.NodeType == NodeType.Sizeof)
                result.Type = SystemTypes.Int32;

            return result;
        }
Esempio n. 5
0
    void AddCallDeserializer(TypeNode type, StatementList statements, Identifier reader, 
      Expression target, Expression required, Expression result) {

      Class memberSerializer = this.CreateSerializerFor(type);      
      // call the Deserialize method on it, and assign result to target object.
      ExpressionList args = new ExpressionList();
      args.Add(reader);
      args.Add(required);
      if (result is Local) 
        result = new UnaryExpression(result, NodeType.AddressOf);
      args.Add(result);
      MethodCall call = new MethodCall();
      Method deserialize = memberSerializer.GetMethod(Identifier.For("Deserialize"), new TypeNode[3] { Runtime.XmlSerializationReader, SystemTypes.Boolean, SystemTypes.Boolean.GetReferenceType() } );
      call.Callee = new MemberBinding(new MemberBinding(null, memberSerializer), deserialize);
      call.Operands = args;
      statements.Add(new AssignmentStatement(target, call));
    }
Esempio n. 6
0
        public override Expression VisitUnaryExpression(UnaryExpression unaryExpression)
        {
            if (unaryExpression.NodeType == NodeType.Sizeof)
            {
                if (unaryExpression.Operand is MemberBinding)
                {
                    Expression sizeofExpr = Templates.GetExpressionTemplate("Sizeof");
                    Replacer.Replace(sizeofExpr, "_sizeofOperand", this.VisitExpression(unaryExpression.Operand));
                    return sizeofExpr;
                }
                else if (unaryExpression.Operand is Literal)
                {
                    // TODO: This only works for fixed-size arrays. It should be disallowed
                    // (by the checker) for variable size arrays.
                    Literal opLiteral = (Literal)unaryExpression.Operand;
                    if (opLiteral.Value is ZArray)
                    {
                        ZArray opArrayType = (ZArray)opLiteral.Value;

                        return new Literal(opArrayType.Sizes[0], SystemTypes.Int32);
                    }
                }
            }

            return base.VisitUnaryExpression(unaryExpression);
        }
Esempio n. 7
0
        void EmitCheckExceptionBody(List<Ensures> asyncPostconditions)
        {
            // We emit the following method:
            //   bool CheckException(Exception e) {
            //     var c1 = e as C1;
            //     if (c1 != null) {
            //       code for handling c1
            //       goto Exit;
            //     }
            //     ...
            //   Exit:
            //     return true; // handled

            if (this.checkExceptionMethod.ExceptionHandlers == null) this.checkExceptionMethod.ExceptionHandlers = new ExceptionHandlerList();

            var body = this.checkExceptionMethod.Body.Statements;
            var returnBlock = new Block(new StatementList());

            for (int i = 0, n = asyncPostconditions.Count; i < n; i++)
            {
                // Normal postconditions are handled separately.
                EnsuresExceptional e = asyncPostconditions[i] as EnsuresExceptional;
                if (e == null)
                    continue;

                // The catchBlock contains the catchBody, and then
                // an empty block that is used in the EH.
                Block catchBlock = new Block(new StatementList());
                Local l = new Local(e.Type);

                body.Add(new AssignmentStatement(l, new BinaryExpression(this.checkExceptionMethod.Parameters[0], new MemberBinding(null, e.Type), NodeType.Isinst)));
                Block skipBlock = new Block();
                body.Add(new Branch(new UnaryExpression(l, NodeType.LogicalNot), skipBlock));
                body.Add(catchBlock);
                body.Add(skipBlock);

                // call Contract.RewriterEnsures
                ExpressionList args = new ExpressionList();
                args.Add(e.PostCondition);
                if (e.UserMessage != null)
                    args.Add(e.UserMessage);
                else
                    args.Add(Literal.Null);
                if (e.SourceConditionText != null)
                {
                    args.Add(e.SourceConditionText);
                }
                else
                {
                    args.Add(Literal.Null);
                }
                args.Add(l);
                var checks = new StatementList();
                checks.Add(new ExpressionStatement(
                  new MethodCall(new MemberBinding(null, this.parent.runtimeContracts.EnsuresOnThrowMethod),
                  args, NodeType.Call, SystemTypes.Void), e.SourceContext));

                this.parent.cleanUpCodeCoverage.VisitStatementList(checks);
                parent.EmitRecursionGuardAroundChecks(this.checkExceptionMethod, catchBlock, checks);

                catchBlock.Statements.Add(new Branch(null, returnBlock));
            }
            // recurse on AggregateException itself
            {
                // var ae = e as AggregateException;
                // if (ae != null) {
                //   ae.Handle(this.CheckException);
                // }
                Block catchBlock = new Block(new StatementList());
                var aggregateType = AggregateExceptionType.Value;

                Local l = new Local(aggregateType);
                body.Add(new AssignmentStatement(l, new BinaryExpression(this.checkExceptionMethod.Parameters[0], new MemberBinding(null, aggregateType), NodeType.Isinst)));
                Block skipBlock = new Block();
                body.Add(new Branch(new UnaryExpression(l, NodeType.LogicalNot), skipBlock));
                body.Add(catchBlock);
                body.Add(skipBlock);

                var funcType = Func2Type.Value;
                funcType = funcType.GetTemplateInstance(this.parent.assemblyBeingRewritten, SystemTypes.Exception, SystemTypes.Boolean);
                var handleMethod = aggregateType.GetMethod(Identifier.For("Handle"), funcType);

                var funcLocal = new Local(funcType);
                var ldftn = new UnaryExpression(new MemberBinding(null, this.checkExceptionMethod), NodeType.Ldftn, CoreSystemTypes.IntPtr);
                catchBlock.Statements.Add(new AssignmentStatement(funcLocal, new Construct(new MemberBinding(null, funcType.GetConstructor(SystemTypes.Object, SystemTypes.IntPtr)), new ExpressionList(this.checkMethod.ThisParameter, ldftn))));
                catchBlock.Statements.Add(new ExpressionStatement(new MethodCall(new MemberBinding(l, handleMethod), new ExpressionList(funcLocal))));
            }

            // add return true to CheckExceptionMethod
            body.Add(returnBlock);
            body.Add(new Return(Literal.True));

        }
Esempio n. 8
0
    //[ContractVerification(true)]
    private void VisitMethodInternal(Method method) {
      if (method.IsAbstract || IsRewriterGenerated(method)) {
        return;
      }
      Block origBody = method.Body;
      if (origBody == null || origBody.Statements == null || origBody.Statements.Count == 0) return;

#if DEBUG
      if (!RewriteHelper.PostNormalizedFormat(method))
        throw new RewriteException("The method body for '" + method.FullName + "' is not structured correctly");
#endif


      #region Rewrite all Assert and Assume methods
      // Happens in-place so any modifications made are persisted even if nothing else is done to method

      RewriteAssertAssumeAndCallSiteRequires raa = new RewriteAssertAssumeAndCallSiteRequires(this.AssertAssumeRewriteMethodTable, this.runtimeContracts, this.contractEmitFlags, this, method);
      method.Body = raa.VisitBlock(method.Body);

      #endregion Rewrite all Assert and Assume methods (if user specified)

      #region Bail out early if publicSurfaceOnly and method is not visible (but not for contract validators!) or contract abbreviator
      if (this.runtimeContracts.PublicSurfaceOnly && !IsCallableFromOutsideAssembly(method) && !ContractNodes.IsValidatorMethod(method)
          || ContractNodes.IsAbbreviatorMethod(method)) return;
      #endregion

      int oldLocalUniqueNameCounter = 0;
      List<Block> contractInitializationBlocks = new List<Block>();
      Block postPreambleBlock = null;
      Dictionary<TypeNode, Local> closureLocals = new Dictionary<TypeNode, Local>();
      Block oldExpressionPreStateValues = new Block(new StatementList());
      #region Gather pre- and postconditions from supertypes and from method contract
      // Create lists of unique preconditions and postconditions.
      List<Requires> preconditions = new List<Requires>();
      List<Ensures> postconditions = new List<Ensures>();
      List<Ensures> asyncPostconditions = new List<Ensures>();
      RequiresList validations = null;
      // For postconditions, wrap all parameters within an old expression (if they are not already within one)
      var wrap = new WrapParametersInOldExpressions();
      EmitAsyncClosure asyncBuilder = null;

      #region Copy the method's contracts.
      if (method.Contract != null && (method.Contract.RequiresCount > 0 || method.Contract.EnsuresCount > 0 || 
                                      method.Contract.ValidationsCount > 0 || method.Contract.AsyncEnsuresCount > 0))
      {
        // Use duplicate of contract because it is going to get modified from processing Old(...) and
        // Result(). Can't have the modified contract get inherited (or else the Old(...) processing
        // will not work properly.)
        // Can't use MethodContract.CopyFrom or HelperMethods.DuplicateMethodBodyAndContract
        // because they assume the new contract is in a different method. Plus the latter duplicates
        // any closure classes needed for anonymous delegates in the contract.
        MethodContract mc = HelperMethods.DuplicateContractAndClosureParts(method, method, this.runtimeContracts.ContractNodes, true);
        validations = mc.Validations;


        if (mc != null) {
          contractInitializationBlocks.Add(mc.ContractInitializer);
          postPreambleBlock = mc.PostPreamble;

          RecordEnsures(method, ref oldLocalUniqueNameCounter, contractInitializationBlocks, closureLocals, oldExpressionPreStateValues, postconditions, asyncPostconditions, wrap, ref asyncBuilder, mc);

        }
      }
      #endregion Copy the method's contracts.
      #region Search the class hierarchy for overridden methods to propagate their contracts.
      if (this.Emit(RuntimeContractEmitFlags.InheritContracts) && method.OverridesBaseClassMember && method.DeclaringType != null && method.OverriddenMethod != null) {
        for (TypeNode super = method.DeclaringType.BaseType; super != null; super = HelperMethods.DoesInheritContracts(super)?super.BaseType:null) {
          var baseMethod = super.GetImplementingMethod(method.OverriddenMethod, false);
          Method baseContractMethod = HelperMethods.GetContractMethod(baseMethod);
          if (baseContractMethod != null) {
            MethodContract mc = HelperMethods.DuplicateContractAndClosureParts(method, baseContractMethod, this.runtimeContracts.ContractNodes, false);
            RewriteHelper.ReplacePrivateFieldsThatHavePublicProperties(method.DeclaringType, super, mc, this.rewriterNodes);
            if (mc != null) {
              contractInitializationBlocks.Add(mc.ContractInitializer);
              // can't have post preambles in overridden methods, since they cannot be constructors.

              // only add requires if baseMethod is the root method
              if (mc.Requires != null && baseMethod.OverriddenMethod == null)
              {
                foreach (RequiresPlain requires in mc.Requires) {
                  if (!EmitRequires(requires, this.skipQuantifiers)) continue;
                  // Debug.Assert(!preconditions.Contains(requires));
                  preconditions.Add(requires);
                }
              }
              RecordEnsures(method, ref oldLocalUniqueNameCounter, contractInitializationBlocks, closureLocals, oldExpressionPreStateValues, postconditions, asyncPostconditions, wrap, ref asyncBuilder, mc);
            }
          }

          // bail out if this base type does not inherit contracts
          if (!HelperMethods.DoesInheritContracts(super)) break;
        }
      }
      #endregion Search the class hierarchy for overridden methods to propagate their contracts.
      #region Propagate explicit interface method contracts.
      if (this.Emit(RuntimeContractEmitFlags.InheritContracts) && method.ImplementedInterfaceMethods != null) {
        foreach (Method interfaceMethod in method.ImplementedInterfaceMethods) {
          if (interfaceMethod != null)
          {
            Method contractMethod = HelperMethods.GetContractMethod(interfaceMethod);

            if (contractMethod != null)
            { // if null, then no contract for this interface method

              // Maybe it would be easier to just duplicate the entire method and then pull the
              // initialization code from the duplicate?
              MethodContract mc=HelperMethods.DuplicateContractAndClosureParts(method, contractMethod, this.runtimeContracts.ContractNodes, false);
              if (mc != null)
              {
                contractInitializationBlocks.Add(mc.ContractInitializer);
                // can't have post preambles in interface methods (not constructors)
                if (mc.Requires != null)
                {
                  foreach (RequiresPlain requires in mc.Requires)
                  {
                    if (!EmitRequires(requires, this.skipQuantifiers)) continue;
                    // Debug.Assert(!preconditions.Contains(requires));
                    preconditions.Add(requires);
                  }
                }
                RecordEnsures(method, ref oldLocalUniqueNameCounter, contractInitializationBlocks, closureLocals, oldExpressionPreStateValues, postconditions, asyncPostconditions, wrap, ref asyncBuilder, mc);
              }
            }
          }
        }
      }
      #endregion Propagate explicit interface method contracts.
      #region Propagate implicit interface method contracts.
      if (this.Emit(RuntimeContractEmitFlags.InheritContracts) && method.ImplicitlyImplementedInterfaceMethods != null) {
        foreach (Method interfaceMethod in method.ImplicitlyImplementedInterfaceMethods) {
          if (interfaceMethod != null) {
            Method contractMethod = HelperMethods.GetContractMethod(interfaceMethod);
            if (contractMethod != null)
            { // if null, then no contract for this method


              // Maybe it would be easier to just duplicate the entire method and then pull the
              // initialization code from the duplicate?
              MethodContract mc = HelperMethods.DuplicateContractAndClosureParts(method, contractMethod, this.runtimeContracts.ContractNodes, false);
              if (mc != null)
              {
                contractInitializationBlocks.Add(mc.ContractInitializer);
                // can't have post preambles in implicit interface method implementations, as they are not constructors.
                if (mc.Requires != null)
                {
                  foreach (RequiresPlain requires in mc.Requires)
                  {
                    if (!EmitRequires(requires, this.skipQuantifiers)) continue;
                    // Debug.Assert(!preconditions.Contains(requires));
                    preconditions.Add(requires);
                  }
                }
                RecordEnsures(method, ref oldLocalUniqueNameCounter, contractInitializationBlocks, closureLocals, oldExpressionPreStateValues, postconditions, asyncPostconditions, wrap, ref asyncBuilder, mc);
              }
            }
          }
        }
      }
      #endregion Propagate implicit interface method contracts.
      #endregion Gather pre- and postconditions from supertypes and from method contract


      #region Return if there is nothing to do
      if (preconditions.Count < 1 && postconditions.Count < 1 && asyncPostconditions.Count < 1 && (validations == null || validations.Count == 0) && this.InvariantMethod == null)
        return;
      #endregion Return if there is nothing to do

      #region Change all short branches to long because code modifications can add code
      {
        // REVIEW: This does *not* remove any short branches in the contracts.
        // I think that is okay, but we should think about it.
        RemoveShortBranches rsb = new RemoveShortBranches();
        rsb.VisitBlock(method.Body);
      }
      #endregion Change all short branches to long because code modifications can add code
      #region Modify method body to change all returns into assignments and branch to unified exit
      // now modify the method body to change all return statements
      // into assignments to the local "result" and a branch to a
      // block at the end that can check the post-condition using
      // "result" and then finally return it.
      // [MAF] we do it later once we know if the branches are leaves or just branch.
      Local result = null;
      if (!HelperMethods.IsVoidType(method.ReturnType)) {
        // don't write huge names. The debugger chokes on them and shows no locals at all.
        //   result = new Local(Identifier.For("Contract.Result<" + typeName + ">()"), method.ReturnType);
        result = new Local(Identifier.For("Contract.Result()"), method.ReturnType);
        if (method.LocalList == null) {
          method.LocalList = new LocalList();
        }
        method.LocalList.Add(result);
      }
      Block newExit = new Block(new StatementList());
      #endregion Modify method body to change all returns into assignments and branch to unified exit

      #region Create the new method's body
      Block newBody = new Block(new StatementList());
      newBody.HasLocals = true;

      #endregion Create the new method's body
      #region If there had been any closure initialization code, put it first in the new body
      if (0 < contractInitializationBlocks.Count) {
        foreach (Block b in contractInitializationBlocks) {
          newBody.Statements.Add(b);
        }
      }
      #endregion

      EmitInterleavedValidationsAndRequires(method, preconditions, validations, newBody);

      #region Turn off invariant checking until the end
      Local oldReEntrancyFlagLocal = null;
      if (MethodShouldHaveInvariantChecked(method) && this.ReentrancyFlag != null && BodyHasCalls(method.Body))
      {
        oldReEntrancyFlagLocal = new Local(SystemTypes.Boolean);
        newBody.Statements.Add(new Block(new StatementList(
          new AssignmentStatement(oldReEntrancyFlagLocal, new MemberBinding(method.ThisParameter, this.ReentrancyFlag)),
          new AssignmentStatement(new MemberBinding(method.ThisParameter, this.ReentrancyFlag), Literal.True))));
      }
      #endregion

      #region Put all of the collected initializations from "old" expressions into the method
      if (oldExpressionPreStateValues.Statements.Count > 0) {
        newBody.Statements.Add(oldExpressionPreStateValues);
      }
      #endregion

      // if there are preamble blocks we need to move them from the origBody in case we will wrap a try-catch
      var preambleIndex = 0;
      while (origBody.Statements.Count > preambleIndex && origBody.Statements[preambleIndex] is PreambleBlock) {
        newBody.Statements.Add(origBody.Statements[preambleIndex]);
        origBody.Statements[preambleIndex] = null;
        preambleIndex++;
      }
      Block newBodyBlock = new Block(new StatementList());
      newBody.Statements.Add(newBodyBlock); // placeholder for eventual body
      newBody.Statements.Add(newExit);

      #region Replace "result" in postconditions (both for method return and out parameters)
      if (result != null)
      {
        foreach (Ensures e in postconditions)
        {
          if (e == null) continue;
          ReplaceResult repResult = new ReplaceResult(method, result, this.assemblyBeingRewritten);
          repResult.Visit(e);
          // now need to initialize closure result fields
          foreach (var target in repResult.NecessaryResultInitialization(closureLocals))
          {
            newBody.Statements.Add(new AssignmentStatement(target, result));
          }
        }
      }
      #endregion

      #region Emit potential post preamble block (from contract duplicate) in constructors
      if (postPreambleBlock != null)
      {
        newBody.Statements.Add(postPreambleBlock);
      }
      #endregion

      #region Emit normal postconditions

      SourceContext lastEnsuresSourceContext = default(SourceContext);
      bool hasLastEnsuresContext = false;
      bool containsExceptionalPostconditions = false;
      var ensuresChecks = new StatementList();
      foreach (Ensures e in postconditions) {
        // Exceptional postconditions are handled separately.
        if (e is EnsuresExceptional) {
          containsExceptionalPostconditions = true;
          continue;
        }

        lastEnsuresSourceContext = e.SourceContext;
        hasLastEnsuresContext = true;
        // call Contract.RewriterEnsures
        Method ensMethod = this.runtimeContracts.EnsuresMethod;
        ExpressionList args = new ExpressionList();
        args.Add(e.PostCondition);
        if (e.UserMessage != null)
          args.Add(e.UserMessage);
        else
          args.Add(Literal.Null);
        if (e.SourceConditionText != null) {
          args.Add(e.SourceConditionText);
        } else {
          args.Add(Literal.Null);
        }
        ensuresChecks.Add(new ExpressionStatement(
          new MethodCall(new MemberBinding(null, ensMethod),
          args, NodeType.Call, SystemTypes.Void), e.SourceContext));
      }
      this.cleanUpCodeCoverage.VisitStatementList(ensuresChecks);
      EmitRecursionGuardAroundChecks(method, newBody, ensuresChecks);
      #endregion Normal postconditions

      #region Emit object invariant
      if (MethodShouldHaveInvariantChecked(method)) {
        // Now turn checking on by restoring old reentrancy flag
        if (this.ReentrancyFlag != null && oldReEntrancyFlagLocal != null) 
        {
          newBody.Statements.Add(new AssignmentStatement(new MemberBinding(method.ThisParameter, this.ReentrancyFlag), oldReEntrancyFlagLocal));
        }
        var callType = (method is InstanceInitializer) || this.InvariantMethod.DeclaringType.IsValueType ? NodeType.Call : NodeType.Callvirt;

        // just add a call to the already existing invariant method, "this.InvariantMethod();"
        // all of the processing needed is done as part of VisitClass
        newBody.Statements.Add(
          new ExpressionStatement(
          new MethodCall(
          new MemberBinding(method.ThisParameter, this.InvariantMethod), null, callType, SystemTypes.Void)));
      }
      #endregion Object invariant

      #region Emit exceptional postconditions

      ReplaceReturns rr;
      if (containsExceptionalPostconditions)
      {
        // -- The following code comes from System.Compiler.Normalizer.CreateTryCatchBlock --

        // The tryCatch holds the try block, the catch blocks, and an empty block that is the
        // target of an unconditional branch for normal execution to go from the try block
        // around the catch blocks.
        if (method.ExceptionHandlers == null) method.ExceptionHandlers = new ExceptionHandlerList();

        Block afterCatches = new Block(new StatementList());

        Block tryCatch = newBodyBlock;
        Block tryBlock = new Block(new StatementList());
        tryBlock.Statements.Add(origBody);
        rr = new ReplaceReturns(result, newExit, leaveExceptionBody:true);
        rr.Visit(origBody);

        tryBlock.Statements.Add(new Branch(null, afterCatches, false, true, true));
        // the EH needs to have a pointer to this block so the writer can
        // calculate the length of the try block. So it should be the *last*
        // thing in the try body.
        Block blockAfterTryBody = new Block(null);
        tryBlock.Statements.Add(blockAfterTryBody);
        tryCatch.Statements.Add(tryBlock);
        for (int i = 0, n = postconditions.Count; i < n; i++)
        {
          // Normal postconditions are handled separately.
          EnsuresExceptional e = postconditions[i] as EnsuresExceptional;
          if (e == null)
            continue;

          // The catchBlock contains the catchBody, and then
          // an empty block that is used in the EH.
          Block catchBlock = new Block(new StatementList());
          Local l = new Local(e.Type);
          Throw rethrow = new Throw();
          rethrow.NodeType = NodeType.Rethrow;

          // call Contract.RewriterEnsures
          ExpressionList args = new ExpressionList();
          args.Add(e.PostCondition);
          if (e.UserMessage != null)
            args.Add(e.UserMessage);
          else
            args.Add(Literal.Null);
          if (e.SourceConditionText != null)
          {
            args.Add(e.SourceConditionText);
          }
          else
          {
            args.Add(Literal.Null);
          }
          args.Add(l);
          var checks = new StatementList();
          checks.Add(new ExpressionStatement(
            new MethodCall(new MemberBinding(null, this.runtimeContracts.EnsuresOnThrowMethod),
            args, NodeType.Call, SystemTypes.Void), e.SourceContext));

          catchBlock.Statements.Add(new AssignmentStatement(l, new Expression(NodeType.Pop), e.SourceContext));
          this.cleanUpCodeCoverage.VisitStatementList(checks);
          EmitRecursionGuardAroundChecks(method, catchBlock, checks);

          #region Emit object invariant on EnsuresOnThrow check
          if (MethodShouldHaveInvariantChecked(method, inExceptionCase: true))
          {
            // Now turn checking on by restoring old reentrancy flag
            if (this.ReentrancyFlag != null && oldReEntrancyFlagLocal != null)
            {
              catchBlock.Statements.Add(new AssignmentStatement(new MemberBinding(method.ThisParameter, this.ReentrancyFlag), oldReEntrancyFlagLocal));
            }
            // just add a call to the already existing invariant method, "this.InvariantMethod();"
            // all of the processing needed is done as part of VisitClass
            catchBlock.Statements.Add(
              new ExpressionStatement(
              new MethodCall(
              new MemberBinding(method.ThisParameter, this.InvariantMethod), null, NodeType.Call, SystemTypes.Void)));
          }
          #endregion Object invariant

          catchBlock.Statements.Add(rethrow);
          // The last thing in each catch block is an empty block that is the target of
          // BlockAfterHandlerEnd in each exception handler.
          // It is used in the writer to determine the length of each catch block
          // so it should be the last thing added to each catch block.
          Block blockAfterHandlerEnd = new Block(new StatementList());
          catchBlock.Statements.Add(blockAfterHandlerEnd);
          tryCatch.Statements.Add(catchBlock);

          // add information to the ExceptionHandlers of this method
          ExceptionHandler exHandler = new ExceptionHandler();
          exHandler.TryStartBlock = origBody;
          exHandler.BlockAfterTryEnd = blockAfterTryBody;
          exHandler.HandlerStartBlock = catchBlock;
          exHandler.BlockAfterHandlerEnd = blockAfterHandlerEnd;
          exHandler.FilterType = l.Type;
          exHandler.HandlerType = NodeType.Catch;
          method.ExceptionHandlers.Add(exHandler);
        }
        tryCatch.Statements.Add(afterCatches);
      }
      else // no exceptional post conditions
      {
        newBodyBlock.Statements.Add(origBody);
        rr = new ReplaceReturns(result, newExit, leaveExceptionBody: false);
        rr.Visit(origBody);
      }
      #endregion Exceptional and finally postconditions

      #region Create a block for the return statement and insert it
      // this is the block that contains the return statements
      // it is (supposed to be) the single exit from the method
      // that way, anything that must always be done can be done
      // in this block
      Block returnBlock = new Block(new StatementList(1));

      if (asyncPostconditions != null && asyncPostconditions.Count > 0)
      {
          asyncBuilder.AddAsyncPost(asyncPostconditions);
          var funcLocal = new Local(asyncBuilder.FuncCtor.DeclaringType);
          var ldftn = new UnaryExpression(new MemberBinding(null, asyncBuilder.CheckMethod), NodeType.Ldftn, CoreSystemTypes.IntPtr);
          returnBlock.Statements.Add(new AssignmentStatement(funcLocal, new Construct(new MemberBinding(null, asyncBuilder.FuncCtor), new ExpressionList(asyncBuilder.ClosureLocal, ldftn))));
          returnBlock.Statements.Add(new AssignmentStatement(result, new MethodCall(new MemberBinding(result, asyncBuilder.ContinueWithMethod), new ExpressionList(funcLocal))));
      }
      Statement returnStatement;
      if (!HelperMethods.IsVoidType(method.ReturnType)) {
        returnStatement = new Return(result);
      }
      else
      {
        returnStatement = new Return();
      }
      if (hasLastEnsuresContext)
      {
        returnStatement.SourceContext = lastEnsuresSourceContext;
      }
      else
      {
        returnStatement.SourceContext = rr.LastReturnSourceContext;
      }
      returnBlock.Statements.Add(returnStatement);
      newBody.Statements.Add(returnBlock);
      #endregion

      method.Body = newBody;

      #region Make sure InitLocals is marked for this method
      // 15 April 2003
      // Since each method has locals added to it, need to make sure this flag is
      // on. Otherwise, the generated code cannot pass peverify.
      if (!method.InitLocals) {
        method.InitLocals = true;
        //WriteToLog("Setting InitLocals for method: {0}", method.FullName);
      }
      #endregion
    }
Esempio n. 9
0
        private void EmitCheckExceptionBody(Method checkExceptionMethod, List<EnsuresExceptional> exceptionalPostconditions)
        {
            Contract.Requires(checkExceptionMethod != null);

            Contract.Requires(exceptionalPostconditions != null);
            Contract.Requires(exceptionalPostconditions.Count > 0);

            // We emit the following method:
            //   bool CheckException(Exception e) {
            //     var ex = e as C1;
            //     if (ex != null) {
            //       EnsuresOnThrow(predicate)
            //     }
            //     else {
            //       var ex2 = e as AggregateException;
            //       if (ex2 != null) {
            //         ex2.Handle(CheckException);
            //       }
            //     }
            //
            //     // Method always returns true. This is by design!
            //     // We need to check all exceptions in the AggregateException
            //     // and fail in EnsuresOnThrow if the postcondition is not met.
            //     return true; // handled

            var body = checkExceptionMethod.Body.Statements;
            var returnBlock = new Block(new StatementList());

            foreach (var e in exceptionalPostconditions)
            {
                // The catchBlock contains the catchBody, and then
                // an empty block that is used in the EH.
                // TODO ST: name is confusing because there is no catch blocks in this method!
                Block catchBlock = new Block(new StatementList());

                // local is: var ex1 = e as C1;
                Local localEx = new Local(e.Type);

                body.Add(
                    new AssignmentStatement(localEx,
                        new BinaryExpression(checkExceptionMethod.Parameters[0],
                            new MemberBinding(null, e.Type),
                            NodeType.Isinst)));

                Block skipBlock = new Block();
                body.Add(new Branch(new UnaryExpression(localEx, NodeType.LogicalNot), skipBlock));
                body.Add(catchBlock);
                body.Add(skipBlock);

                // call Contract.EnsuresOnThrow
                ExpressionList args = new ExpressionList();
                args.Add(e.PostCondition);

                args.Add(e.UserMessage ?? Literal.Null);

                args.Add(e.SourceConditionText ?? Literal.Null);

                args.Add(localEx);
                var checks = new StatementList();

                checks.Add(
                    new ExpressionStatement(
                        new MethodCall(
                            new MemberBinding(null, this.rewriter.RuntimeContracts.EnsuresOnThrowMethod),
                            args,
                            NodeType.Call,
                            SystemTypes.Void),
                        e.SourceContext));

                this.rewriter.CleanUpCodeCoverage.VisitStatementList(checks);

                // TODO ST: actually I can't see this recursion guard check in the resulting IL!!
                rewriter.EmitRecursionGuardAroundChecks(checkExceptionMethod, catchBlock, checks);

                catchBlock.Statements.Add(new Branch(null, returnBlock));
            }

            // recurse on AggregateException itself
            {
                // var ae = e as AggregateException;
                // if (ae != null) {
                //   ae.Handle(this.CheckException);
                // }
                Block catchBlock = new Block(new StatementList());
                var aggregateType = aggregateExceptionType.Value;

                // var ex2 = e as AggregateException;
                Local localEx2 = new Local(aggregateType);
                body.Add(
                    new AssignmentStatement(localEx2,
                        new BinaryExpression(
                            checkExceptionMethod.Parameters[0],
                            new MemberBinding(null, aggregateType),
                            NodeType.Isinst)));

                Block skipBlock = new Block();
                body.Add(new Branch(new UnaryExpression(localEx2, NodeType.LogicalNot), skipBlock));
                body.Add(catchBlock);
                body.Add(skipBlock);

                var funcType = func2Type.Value;
                funcType = funcType.GetTemplateInstance(this.rewriter.AssemblyBeingRewritten, SystemTypes.Exception, SystemTypes.Boolean);

                var handleMethod = aggregateType.GetMethod(Identifier.For("Handle"), funcType);

                var funcLocal = new Local(funcType);
                var ldftn =
                    new UnaryExpression(
                        new MemberBinding(null, checkExceptionMethod),
                        NodeType.Ldftn,
                        CoreSystemTypes.IntPtr);

                catchBlock.Statements.Add(
                    new AssignmentStatement(funcLocal,
                        new Construct(
                            new MemberBinding(null, funcType.GetConstructor(SystemTypes.Object, SystemTypes.IntPtr)),
                            new ExpressionList(checkExceptionMethod.ThisParameter, ldftn))));

                catchBlock.Statements.Add(
                    new ExpressionStatement(new MethodCall(new MemberBinding(localEx2, handleMethod),
                        new ExpressionList(funcLocal))));
            }

            // add return true to CheckException method
            body.Add(returnBlock);
            body.Add(new Return(Literal.True));
        }
Esempio n. 10
0
        private void AddContinueWithMethodToReturnBlock(Block returnBlock, Local taskBasedResult)
        {
            Contract.Requires(returnBlock != null);
            Contract.Requires(taskBasedResult != null);

            var taskType = taskBasedResult.Type;

            // To find appropriate ContinueWith method task type should be unwrapped
            var taskTemplate = HelperMethods.Unspecialize(taskType);

            var continueWithMethodLocal = GetContinueWithMethod(closureClass, taskTemplate, taskType);

            // TODO: not sure that this is possible situation when continueWith method is null. 
            // Maybe Contract.Assert(continueWithMethod != null) should be used instead!

            if (continueWithMethodLocal != null)
            {
                // We need to create delegate instance that should be passed to ContinueWith method
                var funcType = continueWithMethodLocal.Parameters[0].Type;
                var funcCtor = funcType.GetConstructor(SystemTypes.Object, SystemTypes.IntPtr);

                Contract.Assume(funcCtor != null);

                var funcLocal = new Local(funcCtor.DeclaringType);

                // Creating a method pointer to the AsyncClosure.CheckMethod
                // In this case we can't use checkMethod field.
                // Getting CheckMethod from clsoureClassInstance will provide correct (potentially updated)
                // generic arguments for enclosing type.
                var checkMethodFromClosureInstance = (Method) closureClassInstance.GetMembersNamed(CheckMethodId)[0];
                Contract.Assume(checkMethodFromClosureInstance != null);

                var ldftn = new UnaryExpression(
                    new MemberBinding(null, checkMethodFromClosureInstance),
                    NodeType.Ldftn,
                    CoreSystemTypes.IntPtr);

                // Creating delegate that would be used as a continuation for original task
                returnBlock.Statements.Add(
                    new AssignmentStatement(funcLocal,
                        new Construct(new MemberBinding(null, funcCtor),
                            new ExpressionList(closureLocal, ldftn))));

                // Wrapping continuation into TaskExtensions.Unwrap method
                // (this helps to preserve original exception and original result of the task,
                // but allows to throw postconditions violations).

                // Generating: result.ContinueWith(closure.CheckPost);
                var taskContinuationOption = new Literal(TaskContinuationOptions.ExecuteSynchronously);
                var continueWithCall =
                    new MethodCall(
                        new MemberBinding(taskBasedResult, continueWithMethodLocal),
                        new ExpressionList(funcLocal, taskContinuationOption));

                // Generating: TaskExtensions.Unwrap(result.ContinueWith(...))
                var unwrapMethod = GetUnwrapMethod(checkMethodTaskType);
                var unwrapCall =
                    new MethodCall(
                        new MemberBinding(null, unwrapMethod), new ExpressionList(continueWithCall));

                // Generating: result = Unwrap(...);
                var resultAssignment =
                    new AssignmentStatement(taskBasedResult, unwrapCall);
                returnBlock.Statements.Add(resultAssignment);
            }
        }
Esempio n. 11
0
    public override Expression VisitPopExpr(UnaryExpression unex) {
      Expression operand = (Expression)this.Visit(unex.Operand);

      unex = (UnaryExpression)unex.Clone();
      unex.Operand = operand;
      return unex;
    }
Esempio n. 12
0
 /// <summary>
 /// </summary>
 /// <param name="expression">Cloned</param>
 public override Expression VisitUnaryExpression(UnaryExpression expression)
 {
   expression = (UnaryExpression)expression.Clone();
   switch(expression.NodeType)
   {
     case NodeType.Ldtoken:
       return expression;
     case NodeType.Ldftn:
       expression.Operand = (Expression)this.Visit(expression.Operand);
       return expression;
     case NodeType.AddressOf:
     case NodeType.ReadOnlyAddressOf:
     case NodeType.OutAddress: // alias of AddressOf
     case NodeType.RefAddress: // alias of AddressOf
       expression.Operand = simplify_addressof_operand(expression.Operand);
       return expression;
   }
   expression.Operand = simplify(expression.Operand);
   return expression;
 }
Esempio n. 13
0
 public override Expression VisitUnaryExpression(UnaryExpression unaryExpression) {
   if (unaryExpression == null) return null;
   unaryExpression = (UnaryExpression)unaryExpression.Clone();
   unaryExpression.Operand = this.VisitExpression(unaryExpression.Operand);
   return unaryExpression;
 }
        public override Expression VisitUnaryExpression(UnaryExpression unaryExpression)
        {
            var temp = base.VisitUnaryExpression(unaryExpression);

            if (temp.NodeType == NodeType.AddressOf)
            {
                var unary = temp as UnaryExpression;
                if (unary != null)
                {
                    if (!IsAddressoffable(unary.Operand.NodeType))
                    {
                        var newVar = new Local(unary.Operand.Type);
                        var sl = new StatementList();
                        sl.Add(new AssignmentStatement(newVar, unary.Operand));

                        unary.Operand = newVar;
                        sl.Add(new ExpressionStatement(unary));

                        return new BlockExpression(new Block(sl));
                    }
                }
            }

            return temp;
        }
Esempio n. 15
0
        private UnaryExpression VisitChoose(UnaryExpression expr)
        {
            if (expr == null) return null;

            if (!this.validChooses.Contains(expr))
            {
                this.HandleError(expr, Error.EmbeddedChoose);
                return null;
            }
            return expr;
        }
Esempio n. 16
0
 private UnaryExpression VisitChoose(UnaryExpression expr)
 {
     if (expr == null) return null;
     UnaryExpression result = (UnaryExpression)base.VisitUnaryExpression(expr);
     return result;
 }
Esempio n. 17
0
    public override Expression VisitUnaryExpression(UnaryExpression unaryExpression) {
      if (unaryExpression == null) return null;
      switch (unaryExpression.NodeType) {
        case NodeType.AddressOf:
          if (unaryExpression.Type is Reference) return unaryExpression;
          if (!this.typeSystem.insideUnsafeCode && unaryExpression.SourceContext.Document != null) {
            this.HandleError(unaryExpression, Error.UnsafeNeeded);
            return null;
          }

          // change by drunje: you can obtain a pointer to managed structure
          Expression opnd = unaryExpression.Operand = this.VisitExpression(unaryExpression.Operand);
          if (opnd != null && this.CheckFixed(opnd) && opnd.Type != null && !opnd.Type.IsUnmanaged) {
            // this is not compatible with C#
            SpecSharpCompilerOptions options = this.currentOptions as SpecSharpCompilerOptions;
            if (options != null && options.AllowPointersToManagedStructures) {

              // pointers to all structures are allowed now
              if (opnd.Type.IsValueType)
                return unaryExpression;

              // we can convert a reference on any structure to a pointer as well
              if ((opnd.Type is Reference) && ((opnd.Type as Reference).ElementType.IsValueType))
                return unaryExpression;
            }

            if ((opnd.Type is Reference) && ((opnd.Type as Reference).ElementType.IsUnmanaged))
              return unaryExpression;

            this.HandleError(unaryExpression, Error.ManagedAddr, this.GetTypeName(opnd.Type));
            return null;
          }
          // end of change by drunje

          return unaryExpression;
        default:
          break;
      }
      return base.VisitUnaryExpression(unaryExpression);
    }
Esempio n. 18
0
    private void ParseMethodContract(Method m, TokenSet followers, ref bool swallowedSemicolonAlready){
      bool savedParsingStatement = this.parsingStatement;
      if (this.currentToken != Token.EndOfFile) this.parsingStatement = true;
      if (!swallowedSemicolonAlready) m.SourceContext.EndPos = this.scanner.endPos;
      MethodContract mc = new MethodContract(m);
      SourceContext initialSourceContext = this.scanner.CurrentSourceContext;
      while ( Parser.ContractStart[this.currentToken] ) {
        SourceContext ctx = this.scanner.CurrentSourceContext;
        Node n = null;
        int finalPos = 0;
        switch ( this.currentToken ) {
          case Token.Requires: {
            this.GetNextToken();
            if (this.currentToken == Token.LeftBrace){
              this.HandleError(Error.ExpectedExpression);
              break; // without this, the left bracket gets parsed as an anonymous nested function
            }
            Expression e = this.ParseExpression(followers|ContractStart|Token.Otherwise);
            if (mc.Requires == null) mc.Requires = new RequiresList();
            if (this.currentToken != Token.Otherwise) {
              Requires r = new RequiresPlain(e);
              n = r;
              mc.Requires.Add(r);
            }else {
              this.Skip(Token.Otherwise);
              Expression e2 = this.ParseExpression(followers|ContractStart);
              Requires r = new RequiresOtherwise(e,e2);
              n = r;
              mc.Requires.Add(r);
            }
            finalPos = this.scanner.CurrentSourceContext.EndPos;
            swallowedSemicolonAlready= (this.currentToken == Token.Semicolon);
            this.SkipSemiColon(followers|ContractStart);
            break;
          }
          case Token.Modifies: {
            // modifies expressions have their source context set here within this
            // case, so don't use the variable "n" to hold on to the AST otherwise
            // it will have the wrong source context set for it at the end of the switch
            // statement
            n = null;
            this.insideModifiesClause = true;
            list : {
              this.GetNextToken(); // Token.Modifies or Token.Comma
              SourceContext sctx = this.scanner.CurrentSourceContext;
              Expression e = this.ParseExpression(followers | ContractStart | Token.Comma);
              if (mc.Modifies == null) mc.Modifies = new ExpressionList();
              if (e != null) { // REVIEW: does this just silently miss errors?
                sctx.EndPos = e.SourceContext.EndPos;
                ModifiesClause modClause = e as ModifiesClause;
                if (modClause != null) {
                  e.SourceContext = sctx;
                }
                else {
                  e = new UnaryExpression(e, NodeType.RefAddress, sctx);
                }
                mc.Modifies.Add(e);
              }
              if (this.currentToken == Token.Comma)
                goto list;
            }
            swallowedSemicolonAlready= (this.currentToken == Token.Semicolon);
            finalPos = this.scanner.CurrentSourceContext.EndPos;
            this.SkipSemiColon(followers|ContractStart);
            this.insideModifiesClause = false;
            break;
          }
          case Token.Ensures: {
            InEnsuresContext = true;
            this.GetNextToken();
            if (this.currentToken == Token.LeftBrace){
              this.HandleError(Error.ExpectedExpression);
              break; // without this, the left bracket gets parsed as an anonymous nested function
            }
            Expression e = this.ParseExpression(followers|ContractStart);
            if (mc.Ensures == null) mc.Ensures = new EnsuresList();
            EnsuresNormal en = new EnsuresNormal(e);
            n = en;
            mc.Ensures.Add(en);
            finalPos = this.scanner.CurrentSourceContext.EndPos;
            swallowedSemicolonAlready= (this.currentToken == Token.Semicolon);
            this.SkipSemiColon(followers|ContractStart);
            InEnsuresContext = false;
            break;
          }
          case Token.Throws: {
            this.GetNextToken();
            // throws (E1) ensures P;
            // throws (E1 e) ensures P;
            // throws E1 ensures P;
            // throws E1, E2, ...;
            // Note, for constuctors, only the last of these forms is allowed.
            if (mc.Ensures == null) {
              mc.Ensures = new EnsuresList();
              // Note, this list may be left empty in case of parsing errors below.
            }
            EnsuresExceptional exc = new EnsuresExceptional();
            exc.SourceContext = this.scanner.CurrentSourceContext;

            bool hasLeftParen = false;
            if (this.currentToken == Token.LeftParenthesis) {
              hasLeftParen = true;
              this.Skip(Token.LeftParenthesis);
            }
            exc.Type = exc.TypeExpression = this.ParseTypeExpression(Identifier.Empty, followers|Token.Identifier|Token.RightParenthesis|ContractStart);
            if (hasLeftParen && Parser.IdentifierOrNonReservedKeyword[this.currentToken]) {
              exc.Variable = this.scanner.GetIdentifier();
              exc.Variable.Type = exc.Type;
              this.GetNextToken();
            }else{
              exc.Variable = null; // need to be able to distinguish whether the source contains a variable or not
            }
            if (hasLeftParen) {
              this.Skip(Token.RightParenthesis);
            }

            if (hasLeftParen || this.currentToken == Token.Ensures) {
              // throws (E1) ensures P;
              // throws (E1 e) ensures P;
              // throws E1 ensures P;
              SourceContext ctxEnsures = this.scanner.CurrentSourceContext;
              this.Skip(Token.Ensures);
              InEnsuresContext = true;
              Expression ens = this.ParseExpression(followers|ContractStart);
              InEnsuresContext = false;
              // Do the constructor check now.  This is rather late, since the whole throws...ensures
              // has now been parsed, but this may lead to better parse-error recovery.
              if (m is InstanceInitializer) {
                this.HandleError(ctxEnsures, Error.ThrowsEnsuresOnConstructor);
                // ignore what was parsed
                exc.PostCondition = new Literal(true, null, ctx);
              }else{
                exc.PostCondition = ens;
              }
              mc.Ensures.Add(exc);
            }else{
              // throws E1, E2, ...;
//              exc.PostCondition = new Literal(true, null, ctx);
              mc.Ensures.Add(exc);

              while (this.currentToken == Token.Comma) {
                this.GetNextToken();
                exc = new EnsuresExceptional();
                exc.SourceContext = this.scanner.CurrentSourceContext;
                exc.Type = exc.TypeExpression = this.ParseTypeExpression(Identifier.Empty, followers|Token.Comma|ContractStart);
                exc.Variable = new Local(TypeExpressionFor("System", "Exception"));
                exc.Variable.SourceContext = ctx;
                exc.PostCondition = new Literal(true, null, ctx);
                mc.Ensures.Add(exc);
              }
            }

            finalPos = this.scanner.CurrentSourceContext.EndPos;
            swallowedSemicolonAlready= (this.currentToken == Token.Semicolon);
            this.SkipSemiColon(followers|ContractStart);
            n = exc;
            break;
          }

        }
        if (n != null) {
          n.SourceContext= ctx;
          n.SourceContext.EndPos = finalPos ;
        }
        m.SourceContext.EndPos = finalPos;
      }
      // What error to generate here?
      if (!followers[this.currentToken])
        this.SkipTo(followers);
      if (initialSourceContext.EndPos != this.scanner.CurrentSourceContext.EndPos) {
        // then a contract really was parsed
        m.Contract = mc;
      }
      if (this.currentToken != Token.EndOfFile) this.parsingStatement = savedParsingStatement;
    }
Esempio n. 19
0
        public void AddAsyncPost(List<Ensures> asyncPostconditions)
        {
            var origBody = new Block(this.checkBody);
            origBody.HasLocals = true;

            var newBodyBlock = new Block(new StatementList());
            newBodyBlock.HasLocals = true;

            var methodBody = new StatementList();
            var methodBodyBlock = new Block(methodBody);
            methodBodyBlock.HasLocals = true;
            checkMethod.Body = methodBodyBlock;

            methodBody.Add(newBodyBlock);
            Block newExitBlock = new Block();
            methodBody.Add(newExitBlock);

            #region Map closure locals to fields and initialize closure fields

            foreach (Ensures e in asyncPostconditions)
            {
                if (e == null) continue;
                this.Visit(e);
                if (this.forwarder != null) { this.forwarder.Visit(e); }
                ReplaceResult repResult = new ReplaceResult(this.checkMethod, this.originalResultLocal, this.parent.assemblyBeingRewritten);
                repResult.Visit(e);
                // now need to initialize closure result fields
                foreach (var target in repResult.NecessaryResultInitializationAsync(this.closureLocals))
                {
                    // note: target here 
                    methodBody.Add(new AssignmentStatement(target, this.originalResultLocal));
                }
            }

            #endregion

            #region Emit normal postconditions

            SourceContext lastEnsuresSourceContext = default(SourceContext);
            bool hasLastEnsuresContext = false;
            bool containsExceptionalPostconditions = false;
            var ensuresChecks = new StatementList();
            foreach (Ensures e in asyncPostconditions)
            {
                // Exceptional postconditions are handled separately.
                if (e is EnsuresExceptional)
                {
                    containsExceptionalPostconditions = true;
                    continue;
                }

                if (IsVoidTask()) break; // something is wrong in the original contract

                lastEnsuresSourceContext = e.SourceContext;
                hasLastEnsuresContext = true;
                // call Contract.RewriterEnsures
                Method ensMethod = this.parent.runtimeContracts.EnsuresMethod;
                ExpressionList args = new ExpressionList();
                args.Add(e.PostCondition);
                if (e.UserMessage != null)
                    args.Add(e.UserMessage);
                else
                    args.Add(Literal.Null);
                if (e.SourceConditionText != null)
                {
                    args.Add(e.SourceConditionText);
                }
                else
                {
                    args.Add(Literal.Null);
                }
                ensuresChecks.Add(new ExpressionStatement(
                  new MethodCall(new MemberBinding(null, ensMethod),
                  args, NodeType.Call, SystemTypes.Void), e.SourceContext));
            }
            this.parent.cleanUpCodeCoverage.VisitStatementList(ensuresChecks);
            this.parent.EmitRecursionGuardAroundChecks(this.checkMethod, methodBodyBlock, ensuresChecks);
            #endregion Normal postconditions

            #region Exceptional postconditions
            if (containsExceptionalPostconditions)
            {
                // Because async tasks wrap exceptions into Aggregate exceptions, we have to catch AggregateException
                // and iterate over the internal exceptions of the Aggregate.

                // We thus emit the following handler:
                //
                //  catch(AggregateException ae) {
                //    ae.Handle(this.CheckException);
                //    rethrow;
                //  }
                //
                //  alternatively, if the Task has no Result, we emit
                //
                //    var ae = t.Exception as AggregateException;
                //    if (ae != null) {
                //      ae.Handle(this.CheckException);
                //      throw ae;
                //    }

                var aggregateType = AggregateExceptionType.Value;

                var exnParameter = new Parameter(Identifier.For("e"), SystemTypes.Exception);
                this.checkExceptionMethod = new Method(this.closureClass, null, this.checkExceptionMethodId, new ParameterList(exnParameter), SystemTypes.Boolean, new Block(new StatementList()));
                this.checkExceptionMethod.Body.HasLocals = true;
                checkExceptionMethod.CallingConvention = CallingConventionFlags.HasThis;
                checkExceptionMethod.Flags |= MethodFlags.Public;

                this.closureClass.Members.Add(checkExceptionMethod);

                if (this.IsVoidTask())
                {
                    var blockAfterTest = new Block();
                    methodBody.Add(origBody);
                    methodBody.Add(new Branch(new UnaryExpression(this.newResultLocal, NodeType.LogicalNot), blockAfterTest));
                    var funcType = Func2Type.Value;
                    funcType = funcType.GetTemplateInstance(this.parent.assemblyBeingRewritten, SystemTypes.Exception, SystemTypes.Boolean);
                    var handleMethod = aggregateType.GetMethod(Identifier.For("Handle"), funcType);

                    var funcLocal = new Local(funcType);
                    var ldftn = new UnaryExpression(new MemberBinding(null, this.checkExceptionMethod), NodeType.Ldftn, CoreSystemTypes.IntPtr);
                    methodBody.Add(new AssignmentStatement(funcLocal, new Construct(new MemberBinding(null, funcType.GetConstructor(SystemTypes.Object, SystemTypes.IntPtr)), new ExpressionList(this.checkMethod.ThisParameter, ldftn))));
                    methodBody.Add(new ExpressionStatement(new MethodCall(new MemberBinding(this.newResultLocal, handleMethod), new ExpressionList(funcLocal))));
                    methodBody.Add(new Throw(this.newResultLocal));
                    methodBody.Add(blockAfterTest);
                }
                else
                {
                    // The tryCatch holds the try block, the catch blocks, and an empty block that is the
                    // target of an unconditional branch for normal execution to go from the try block
                    // around the catch blocks.
                    if (this.checkMethod.ExceptionHandlers == null) this.checkMethod.ExceptionHandlers = new ExceptionHandlerList();

                    Block afterCatches = new Block(new StatementList());

                    Block tryCatch = newBodyBlock;
                    Block tryBlock = new Block(new StatementList());
                    tryBlock.Statements.Add(origBody);
                    tryBlock.Statements.Add(new Branch(null, afterCatches, false, true, true));
                    // the EH needs to have a pointer to this block so the writer can
                    // calculate the length of the try block. So it should be the *last*
                    // thing in the try body.
                    Block blockAfterTryBody = new Block(null);
                    tryBlock.Statements.Add(blockAfterTryBody);
                    tryCatch.Statements.Add(tryBlock);
                    // The catchBlock contains the catchBody, and then
                    // an empty block that is used in the EH.

                    Block catchBlock = new Block(new StatementList());
                    Local l = new Local(aggregateType);
                    Throw rethrow = new Throw();
                    rethrow.NodeType = NodeType.Rethrow;

                    catchBlock.Statements.Add(new AssignmentStatement(l, new Expression(NodeType.Pop)));

                    var funcType = Func2Type.Value;
                    funcType = funcType.GetTemplateInstance(this.parent.assemblyBeingRewritten, SystemTypes.Exception, SystemTypes.Boolean);
                    var handleMethod = aggregateType.GetMethod(Identifier.For("Handle"), funcType);

                    var funcLocal = new Local(funcType);
                    var ldftn = new UnaryExpression(new MemberBinding(null, this.checkExceptionMethod), NodeType.Ldftn, CoreSystemTypes.IntPtr);
                    catchBlock.Statements.Add(new AssignmentStatement(funcLocal, new Construct(new MemberBinding(null, funcType.GetConstructor(SystemTypes.Object, SystemTypes.IntPtr)), new ExpressionList(this.checkMethod.ThisParameter, ldftn))));
                    catchBlock.Statements.Add(new ExpressionStatement(new MethodCall(new MemberBinding(l, handleMethod), new ExpressionList(funcLocal))));
                    // Handle method should return if all passes
                    catchBlock.Statements.Add(rethrow);
                    // The last thing in each catch block is an empty block that is the target of
                    // BlockAfterHandlerEnd in each exception handler.
                    // It is used in the writer to determine the length of each catch block
                    // so it should be the last thing added to each catch block.
                    Block blockAfterHandlerEnd = new Block(new StatementList());
                    catchBlock.Statements.Add(blockAfterHandlerEnd);
                    tryCatch.Statements.Add(catchBlock);

                    // add information to the ExceptionHandlers of this method
                    ExceptionHandler exHandler = new ExceptionHandler();
                    exHandler.TryStartBlock = origBody;
                    exHandler.BlockAfterTryEnd = blockAfterTryBody;
                    exHandler.HandlerStartBlock = catchBlock;
                    exHandler.BlockAfterHandlerEnd = blockAfterHandlerEnd;
                    exHandler.FilterType = l.Type;
                    exHandler.HandlerType = NodeType.Catch;
                    this.checkMethod.ExceptionHandlers.Add(exHandler);

                    tryCatch.Statements.Add(afterCatches);
                }
                EmitCheckExceptionBody(asyncPostconditions);
            }
            else // no exceptional post conditions
            {
                newBodyBlock.Statements.Add(origBody);
            }
            #endregion Exceptional and finally postconditions


            #region Create a block for the return statement and insert it
            // this is the block that contains the return statements
            // it is (supposed to be) the single exit from the method
            // that way, anything that must always be done can be done
            // in this block
            Statement returnStatement;
            if (this.IsVoidTask())
            {
                returnStatement = new Return();
            }
            else
            {
                returnStatement = new Return(this.newResultLocal);
            }
            if (hasLastEnsuresContext)
            {
                returnStatement.SourceContext = lastEnsuresSourceContext;
            }
            Block returnBlock = new Block(new StatementList(1));
            returnBlock.Statements.Add(returnStatement);
            methodBody.Add(returnBlock);
            #endregion
        }
Esempio n. 20
0
 private Expression ParseUnaryExpression(TokenSet followers){
   if (this.currentToken == Token.EndOfFile) {
     if (this.returnedEmptyIdentForEOF)
       return null;
     else {
       this.returnedEmptyIdentForEOF = true;
       return this.scanner.GetIdentifier();
     }
   }
   Expression expression;
   switch(this.currentToken){
     case Token.Plus:
     case Token.BitwiseNot:
     case Token.LogicalNot:
     case Token.Subtract:
     case Token.BitwiseAnd:
       UnaryExpression uexpr = new UnaryExpression();
       uexpr.SourceContext = this.scanner.CurrentSourceContext;
       uexpr.NodeType = Parser.ConvertToUnaryNodeType(this.currentToken);
       this.GetNextToken();
       uexpr.Operand = this.ParseUnaryExpression(followers);
       if (uexpr.Operand == null) return null;
       uexpr.SourceContext.EndPos = uexpr.Operand.SourceContext.EndPos;
       expression = uexpr;
       break;
     case Token.Multiply:
       AddressDereference adref = new AddressDereference();
       adref.SourceContext = this.scanner.CurrentSourceContext;
       adref.ExplicitOperator = AddressDereference.ExplicitOp.Star;
       this.GetNextToken();
       adref.Address = this.ParseUnaryExpression(followers);
       if (adref.Address == null) return null;
       adref.SourceContext.EndPos = adref.Address.SourceContext.EndPos;
       expression = adref;
       break;
     case Token.AddOne:
     case Token.SubtractOne:
       PrefixExpression prefixExpr = new PrefixExpression();
       prefixExpr.SourceContext = this.scanner.CurrentSourceContext;
       prefixExpr.Operator = Parser.ConvertToBinaryNodeType(this.currentToken);
       this.GetNextToken();
       prefixExpr.Expression = this.ParseUnaryExpression(followers);
       if (prefixExpr.Expression == null) return null;
       prefixExpr.SourceContext.EndPos = prefixExpr.Expression.SourceContext.EndPos;
       expression = prefixExpr;
       break;
     case Token.LeftParenthesis:
       expression = this.ParseCastExpression(followers);
       break;
     case Token.LeftBrace:
       expression = this.ParseBlockExpression(ScannerState.Code, this.scanner.CurrentSourceContext, followers);
       break;
     case Token.Exists:
     case Token.Forall:
     case Token.Count:
     case Token.Sum:
     case Token.Max:
     case Token.Min:
     case Token.Product:
       Quantifier q = new Quantifier();
       q.SourceContext = this.scanner.CurrentSourceContext;
       ScannerState ss = this.scanner.state;
       Token quantType = this.currentToken;
       SourceContext sctx = this.scanner.CurrentSourceContext;
       this.GetNextToken();
       if (this.currentToken == Token.Unique){
         quantType = this.currentToken;
         this.GetNextToken();
       }
       // not necessarily a quantifier unless there is an open curly!!
       // REVIEW: Is that enough of a test? Or do we need to try parsing the comprehension?
       if (this.currentToken != Token.LeftBrace) {
         //Restore prior state and reparse as expression
         this.scanner.endPos = q.SourceContext.StartPos;
         this.scanner.state = ss;
         this.currentToken = Token.None;
         this.GetNextToken();
         goto default;
       }
       q.QuantifierType = Parser.ConvertToQuantifierType(quantType);
       this.Skip(Token.LeftBrace);
       Comprehension c = this.ParseComprehension(followers, sctx);
       if (c == null) {
         return null;
       }
       q.Comprehension = c;
       q.SourceContext.EndPos = c.SourceContext.EndPos;
       expression = q;
       break;
     default:
       expression = this.ParsePrimaryExpression(followers);
       break;
   }
   return expression;
 }
Esempio n. 21
0
 public virtual Expression VisitUnaryExpression(UnaryExpression unaryExpression)
 {
     if (unaryExpression == null) return null;
     unaryExpression.Operand = this.VisitExpression(unaryExpression.Operand);
     return unaryExpression;
 }
Esempio n. 22
0
    private Expression ParsePrimaryExpression(TokenSet followers){
      Expression expression = null;
      SourceContext sctx = this.scanner.CurrentSourceContext;
      switch(this.currentToken){
        case Token.ArgList:
          this.GetNextToken();
          expression = new ArglistExpression(sctx);
          break;
        case Token.Delegate:{
          this.GetNextToken();
          ParameterList parameters = null;
          if (this.currentToken == Token.LeftParenthesis)
            parameters = this.ParseParameters(Token.RightParenthesis, followers|Token.LeftBrace);
          Block block = null;
          if (this.currentToken == Token.LeftBrace)
            block = this.ParseBlock(this.scanner.CurrentSourceContext, followers);
          else
            this.SkipTo(followers, Error.ExpectedLeftBrace);
          sctx.EndPos = this.scanner.endPos;
          return new AnonymousNestedDelegate(parameters, block, sctx);}
        case Token.New:
          expression = this.ParseNew(followers|Token.Dot|Token.LeftBracket|Token.Arrow);
          break;
        case Token.Identifier:
          expression = this.scanner.GetIdentifier();
          if (this.sink != null) {
            this.sink.StartName((Identifier)expression);
          }
          this.GetNextToken();
          if (this.currentToken == Token.DoubleColon){
            this.GetNextToken();
            Identifier id = this.scanner.GetIdentifier();
            id.Prefix = (Identifier)expression;
            id.SourceContext.StartPos = expression.SourceContext.StartPos;
            expression = id;
            if (this.currentToken != Token.EndOfFile)
              this.GetNextToken();
          }else if (this.currentToken == Token.Lambda){
            Parameter par = new Parameter((Identifier)expression, null);
            par.SourceContext = expression.SourceContext;
            return this.ParseLambdaExpression(par.SourceContext, new ParameterList(par), followers);
          }
          break;
        case Token.Null:
          expression = new Literal(null, null, sctx);
          this.GetNextToken();
          break;
        case Token.True:
          expression = new Literal(true, null, sctx);
          this.GetNextToken();
          break;
        case Token.False:
          expression = new Literal(false, null, sctx);
          this.GetNextToken();
          break;
        case Token.CharLiteral:
          expression = new Literal(this.scanner.charLiteralValue, null, sctx);
          this.GetNextToken();
          break;
        case Token.HexLiteral:
          expression = this.ParseHexLiteral();
          break;
        case Token.IntegerLiteral:
          expression = this.ParseIntegerLiteral();
          break;
        case Token.RealLiteral:
          expression = this.ParseRealLiteral();
          break;
        case Token.StringLiteral:
          expression = this.scanner.GetStringLiteral();
          this.GetNextToken();
          break;
        case Token.This:
          expression = new This(sctx, false);
          if (this.sink != null) {
            this.sink.StartName(expression);
          }
          this.GetNextToken();
          if (this.currentToken == Token.LeftParenthesis
            && (this.inInstanceConstructor==BaseOrThisCallKind.None
            || this.inInstanceConstructor==BaseOrThisCallKind.InCtorBodyThisSeen)){
            QualifiedIdentifier thisCons = new QualifiedIdentifier(expression, StandardIds.Ctor, this.scanner.CurrentSourceContext);
            MethodCall thisConstructorCall = new MethodCall(thisCons, null, NodeType.Call);
            thisConstructorCall.SourceContext = sctx;
            SourceContext lpCtx = this.scanner.CurrentSourceContext;
            this.Skip(Token.LeftParenthesis);
            thisConstructorCall.Operands = this.ParseArgumentList(followers|Token.LeftBrace|Token.Semicolon, lpCtx, out thisConstructorCall.SourceContext.EndPos);
            expression = thisConstructorCall;
            this.inInstanceConstructor=BaseOrThisCallKind.InCtorBodyThisSeen;
            goto done;
          }
          break;
        case Token.Base:
          Base ba = new Base(sctx, false);
          expression = ba;
          if (this.sink != null) {
            this.sink.StartName(expression);
          }
          this.GetNextToken();
          if (this.currentToken == Token.Semicolon &&
            (this.inInstanceConstructor == BaseOrThisCallKind.ColonThisOrBaseSeen
            || this.inInstanceConstructor == BaseOrThisCallKind.None)) {
            // When there are non-null fields, then the base ctor call can happen only after they are
            // initialized.
            // In Spec#, we allow a base ctor call in the body of the ctor. But if someone is using
            // the C# comment convention, then they cannot do that.
            // So allow "base;" as a marker to indicate where the base ctor call should happen.
            // There may be an explicit "colon base call" or it may be implicit.
            //
            // Just leave expression as a bare "Base" node; later pipeline stages will all have
            // to ignore it. Mark the current ctor as having (at least) one of these bad boys
            // in it.
            ba.UsedAsMarker = true;
            this.currentCtor.ContainsBaseMarkerBecauseOfNonNullFields = true;
            goto done;
          }
          if (this.currentToken == Token.LeftParenthesis
            && (this.inInstanceConstructor==BaseOrThisCallKind.None
              || this.inInstanceConstructor==BaseOrThisCallKind.InCtorBodyBaseSeen)){
            QualifiedIdentifier supCons = new QualifiedIdentifier(expression, StandardIds.Ctor, this.scanner.CurrentSourceContext);
            MethodCall superConstructorCall = new MethodCall(supCons, null, NodeType.Call);
            superConstructorCall.SourceContext = sctx;
            SourceContext lpCtx = this.scanner.CurrentSourceContext;
            this.Skip(Token.LeftParenthesis);
            superConstructorCall.Operands = this.ParseArgumentList(followers|Token.LeftBrace|Token.Semicolon, lpCtx, out superConstructorCall.SourceContext.EndPos);
            expression = superConstructorCall;
            this.inInstanceConstructor=BaseOrThisCallKind.InCtorBodyBaseSeen;
            goto done;
          }
          break;
        case Token.Typeof:
        case Token.Sizeof:
        case Token.Default:{
          //if (this.currentToken == Token.Sizeof && !this.inUnsafeCode)
            //this.HandleError(Error.SizeofUnsafe);
          UnaryExpression uex = new UnaryExpression(null,
            this.currentToken == Token.Typeof ? NodeType.Typeof : this.currentToken == Token.Sizeof ? NodeType.Sizeof : NodeType.DefaultValue);
          uex.SourceContext = sctx;
          this.GetNextToken();
          this.Skip(Token.LeftParenthesis);
          TypeNode t = null;
          if (this.currentToken == Token.Void && uex.NodeType == NodeType.Typeof){
            t = this.TypeExpressionFor(Token.Void); this.GetNextToken();
          }else
            t = this.ParseTypeExpression(null, followers|Token.RightParenthesis, false, false, uex.NodeType == NodeType.Typeof);
          if (t == null){this.SkipTo(followers); return null;}
          uex.Operand = new MemberBinding(null, t, t.SourceContext, null);
          uex.Operand.SourceContext = t.SourceContext;
          uex.SourceContext.EndPos = this.scanner.endPos;
          this.Skip(Token.RightParenthesis);
          expression = uex;
          break;}
        case Token.Stackalloc:{
          this.GetNextToken();
          TypeNode elementType = this.ParseBaseTypeExpression(null, followers|Token.LeftBracket, false, false);
          if (elementType == null){this.SkipTo(followers); return null;}
          Token openingDelimiter = this.currentToken;
          if (this.currentToken != Token.LeftBracket){
            this.HandleError(Error.BadStackAllocExpr);
            if (this.currentToken == Token.LeftParenthesis) this.GetNextToken();
          }else
            this.GetNextToken();
          Expression numElements = this.ParseExpression(followers|Token.RightBracket|Token.RightParenthesis);
          sctx.EndPos = this.scanner.endPos;
          if (this.currentToken == Token.RightParenthesis && openingDelimiter == Token.LeftParenthesis)
            this.GetNextToken();
          else
            this.Skip(Token.RightBracket);
          this.SkipTo(followers);
          return new StackAlloc(elementType, numElements, sctx);}
        case Token.Checked:
        case Token.Unchecked:
          //TODO: use NodeType.SkipCheck and NodeType.EnforceCheck
          Block b = new Block(new StatementList(1), this.currentToken == Token.Checked, this.currentToken == Token.Unchecked, this.inUnsafeCode);
          b.SourceContext = sctx;
          this.GetNextToken();
          this.Skip(Token.LeftParenthesis);
          b.Statements.Add(new ExpressionStatement(this.ParseExpression(followers|Token.RightParenthesis)));
          this.Skip(Token.RightParenthesis);
          expression = new BlockExpression(b);
          expression.SourceContext = b.SourceContext;
          break;
        case Token.RefType:{
          this.GetNextToken();
          this.Skip(Token.LeftParenthesis);
          Expression e = this.ParseExpression(followers|Token.RightParenthesis);
          this.Skip(Token.RightParenthesis);
          expression = new RefTypeExpression(e, sctx);
          break;
        }
        case Token.RefValue:{
          this.GetNextToken();
          this.Skip(Token.LeftParenthesis);
          Expression e = this.ParseExpression(followers|Token.Comma);
          this.Skip(Token.Comma);
          TypeNode te = this.ParseTypeOrFunctionTypeExpression(followers|Token.RightParenthesis, false, true);
          Expression operand2 = new MemberBinding(null, te);
          if (te is TypeExpression)
            operand2.SourceContext = te.SourceContext;
          else
            operand2.SourceContext = sctx;
          this.Skip(Token.RightParenthesis);
          expression = new RefValueExpression(e, operand2, sctx);
          break;
        }
        case Token.Bool:
        case Token.Decimal:
        case Token.Sbyte:
        case Token.Byte:
        case Token.Short:
        case Token.Ushort:
        case Token.Int:
        case Token.Uint:
        case Token.Long:
        case Token.Ulong:
        case Token.Char:
        case Token.Float:
        case Token.Double:
        case Token.Object:
        case Token.String:
          MemberBinding mb = new MemberBinding(null, this.TypeExpressionFor(this.currentToken), sctx);
          this.GetNextToken();
          expression = this.ParseIndexerCallOrSelector(mb, followers);
          goto done;
        case Token.LeftParenthesis:
          expression = this.ParseParenthesizedExpression(followers|Token.Dot|Token.LeftBracket|Token.Arrow, true);
          break;
        default:
          if (Parser.IdentifierOrNonReservedKeyword[this.currentToken]) goto case Token.Identifier;
          if (Parser.InfixOperators[this.currentToken]){
            this.HandleError(Error.InvalidExprTerm, this.scanner.GetTokenSource());
            this.GetNextToken();
          }else
            this.SkipTo(followers|Parser.PrimaryStart, Error.InvalidExprTerm, this.scanner.GetTokenSource());
          if (Parser.PrimaryStart[this.currentToken]) return this.ParsePrimaryExpression(followers);
          goto done;
      }
      if (expression is Base && this.currentToken != Token.Dot && this.currentToken != Token.LeftBracket){
        this.HandleError(expression.SourceContext, Error.BaseIllegal);
        expression = null;
      }

      expression = this.ParseIndexerCallOrSelector(expression, followers|Token.AddOne|Token.SubtractOne);
      for(;;){
        switch(this.currentToken){
          case Token.AddOne:
          case Token.SubtractOne:
            SourceContext ctx = expression.SourceContext;
            ctx.EndPos = this.scanner.endPos;
            PostfixExpression pex = new PostfixExpression(expression, Parser.ConvertToBinaryNodeType(this.currentToken), ctx);
            this.GetNextToken();
            expression = pex;
            break;
          case Token.Dot:
            expression = this.ParseIndexerCallOrSelector(expression, followers|Token.AddOne|Token.SubtractOne);
            break;
          default:
            goto done;
        }
      }
      done:
        this.SkipTo(followers);
      return expression;
    }
Esempio n. 23
0
 public override Expression VisitUnaryExpression(UnaryExpression unaryExpression){
   if (unaryExpression == null) return null;
   if (unaryExpression.NodeType == NodeType.Typeof) this.AbstractSealedUsedAsType = Cci.Error.None;
   Expression result = base.VisitUnaryExpression(unaryExpression);
   this.AbstractSealedUsedAsType = Cci.Error.NotAType;
   return result;
 }
Esempio n. 24
0
        public override Expression VisitUnaryExpression(UnaryExpression unaryExpression)
        {
            if ((unaryExpression.NodeType != NodeType.Sizeof && ((ZingNodeType)unaryExpression.NodeType) != ZingNodeType.Choose)
                || !(unaryExpression.Operand is MemberBinding))
                return base.VisitUnaryExpression(unaryExpression);

            Debug.Assert(unaryExpression.Operand is MemberBinding);
            MemberBinding mb = (MemberBinding)unaryExpression.Operand;
            Debug.Assert(mb.BoundMember is TypeExpression);
            TypeExpression te = (TypeExpression)mb.BoundMember;
            if (te.Expression is Identifier)
            {
                Identifier id = (Identifier)te.Expression;

                this.encounteredTypeRefError = false;

                this.ignoreTypeRefErrors = true;
                unaryExpression.Operand = this.VisitExpression(unaryExpression.Operand);
                this.ignoreTypeRefErrors = false;

                if (encounteredTypeRefError)
                {
                    // If this didn't resolve to a type, then treat it as an expression and let
                    // the resolver deal with it (or report an error).
                    unaryExpression.Operand = this.VisitExpression(id);

                    NameBinding nb = unaryExpression.Operand as NameBinding;
                    if (nb != null && nb.BoundMembers.Count == 0)
                    {
                        this.HandleTypeExpected(nb.Identifier);
                        return null;
                    }
                }
            }

            return unaryExpression;
        }
Esempio n. 25
0
    Expression GetConvertFromString(TypeNode targetType, Expression src, bool always) {
      if (targetType == SystemTypes.String) 
        return src;// nothing to do!

      if (targetType is EnumNode) {
        // e.g. return (DayOfWeek)Enum.Parse(typeof(DayOfWeek),"Sunday");
        Method method = SystemTypes.Enum.GetMethod(Identifier.For("Parse"), new TypeNode[2]{ SystemTypes.Type, SystemTypes.String});
        UnaryExpression typeOfEnum = new UnaryExpression(new MemberBinding(null, targetType), NodeType.Typeof);
        MethodCall call = new MethodCall(new MemberBinding(new MemberBinding(null, targetType), method), 
          new ExpressionList(new Expression[2]{typeOfEnum, src }), NodeType.Call, SystemTypes.Object);
        return CastTo(call, targetType);
      }
      // See if it has a type converter.
      Class converterClass = Checker.GetTypeConverter(targetType);
      if (converterClass != null) {
        TypeConverter converter = TypeDescriptor.GetConverter(targetType.GetRuntimeType());
        if (converter != null) {
          Type converterType = converter.GetType();
          AssemblyNode converterAssembly = AssemblyNode.GetAssembly(converterType.Assembly, cache, false, true);
          converterClass = converterAssembly.GetType(Identifier.For(converterType.Namespace), Identifier.For(converterType.Name)) as Class;          
          Expression e = tempChecker.GetConverterFromString(converter, converterClass, SystemTypes.String, src, SystemTypes.Object);
          if (e != null) {
            //Do I need to add namespace and assembly reference for type converter?
            return CastTo(e, targetType);
          }
        }   
      }
      if (always) {
        // e.g. return PointArray.Parse("10,20 30,40 50,60");
        Method method = targetType.GetImplicitCoercionFromMethod(SystemTypes.String);
        if (method == null) {
          method = targetType.GetMethod(Identifier.For("Parse"), new TypeNode[1]{ SystemTypes.String});
        }
        if (method != null) {
          MemberBinding typeBinding  = new MemberBinding(null, targetType);
          MethodCall call = new MethodCall(new MemberBinding(typeBinding, method), 
            new ExpressionList(new Expression[1]{ src }), NodeType.Call, targetType );
          return call;
        }
      }
      return null;
    }
Esempio n. 26
0
 private UnaryExpression VisitChoose(UnaryExpression expr)
 {
     return (UnaryExpression)this.VisitUnaryExpression(expr);
 }
Esempio n. 27
0
        private UnaryExpression VisitChoose(UnaryExpression expr)
        {
            expr.Operand = this.VisitExpression(expr.Operand);

            if (expr.Operand.Type.FullName == "Boolean")
            {
                expr.Type = SystemTypes.Boolean;
            }
            else if (expr.Operand.Type == SystemTypes.Type)
            {
                Literal typeExpr = expr.Operand as Literal;
                Debug.Assert(typeExpr != null);

                if (typeExpr.Value is EnumNode)
                    expr.Type = (TypeNode)typeExpr.Value;
                else if (typeExpr.Value is Range)
                    expr.Type = SystemTypes.Int32;
                else
                {
                    this.HandleError(expr.Operand, Error.InvalidChoiceType);
                    return null;
                }
            }
            else
            {
                // We have a variable - must be an array or set
                if (expr.Operand.Type is ZArray)
                    expr.Type = ((ZArray)expr.Operand.Type).ElementType;
                else if (expr.Operand.Type is Set)
                    expr.Type = ((Set)expr.Operand.Type).SetType;
                else
                {
                    this.HandleError(expr.Operand, Error.InvalidChoiceExpr);
                    return null;
                }
            }
            return expr;
        }
Esempio n. 28
0
 public override Expression VisitUnaryExpression(UnaryExpression unaryExpression)
 {
     if (unaryExpression == null) return null;
     unaryExpression = (UnaryExpression)base.VisitUnaryExpression((UnaryExpression)unaryExpression.Clone());
     return unaryExpression;
 }
Esempio n. 29
0
        private UnaryExpression VisitChoose(UnaryExpression expr)
        {
            Write("choose");
            this.VisitParenthesizedExpression(expr.Operand);

            return expr;
        }
 public EventingVisitor(Action<UnaryExpression> visitUnaryExpression) { VisitedUnaryExpression += visitUnaryExpression; } public event Action<UnaryExpression> VisitedUnaryExpression; public override Expression VisitUnaryExpression(UnaryExpression unaryExpression) { if (VisitedUnaryExpression != null) VisitedUnaryExpression(unaryExpression); return base.VisitUnaryExpression(unaryExpression); }