private bool ExtractFromClump(StatementList contractClump, Method method, GatherLocals gatherLocals,
            RequiresList Preconditions, EnsuresList Postconditions, RequiresList validations,
            EnsuresList modelPostconditions, SourceContext defaultContext, Method originalMethod,
            Block contractInitializer, ref HelperMethods.StackDepthTracker dupStackTracker)
        {
            // set the state so that the contract clump is used for extraction (as opposed to the method body as it used to)
            StatementList stmts = contractClump;

            int beginning = 0;
            int n = stmts.Count;
            int seginning = HelperMethods.FindNextRealStatement(((Block) stmts[beginning]).Statements, 0);

            bool endContractFound = false;
            bool postConditionFound = false;

            SourceContext currentSourceContext;

            for (int i = beginning; i < n; i++)
            {
                Block b = (Block) stmts[i];
                if (b == null) continue;

                for (int j = 0, m = b.Statements == null ? 0 : b.Statements.Count; j < m; j++)
                {
                    if (dupStackTracker.IsValid && dupStackTracker.Depth >= 0)
                    {
                        b.Statements[j] = dupStackTracker.Visit(b.Statements[j]);
                    }

                    Statement s = b.Statements[j];
                    if (s == null) continue;

                    Block currentClump;
                    Throw t = null;
                    t = s as Throw;

                    Method calledMethod = HelperMethods.IsMethodCall(s);
                    if ((t != null ||
                         (calledMethod != null &&
                          calledMethod.DeclaringType != null &&
                          calledMethod.DeclaringType != this.contractNodes.ContractClass &&
                          HelperMethods.IsVoidType(calledMethod.ReturnType) &&
                          !this.contractNodes.IsContractOrValidatorOrAbbreviatorMethod(calledMethod))))
                    {
                        // Treat throw statements as (part of) a precondition

                        // don't accept "throw ..." unless it comes in the "precondition section"
                        // then treat the current clump as a precondition, but need to massage it a bit:
                        // all branches to the block just after the throw should be modified to be branches to
                        // a new manufactured block that sets a fresh local to "true". The
                        // throw itself should be changed to set the same local to "false". That way the
                        // clump can be treated as the value of precondition (because the branch polarity has
                        // already been negated as part of the code gen).

                        // This test was supposed to be a sanity check that the current block contained
                        // only "throw ..." or else "nop; throw ...". But I've also seen "ThrowHelper.Throw(...); nop",
                        // so I'm just going to comment this out for now.
                        //if (!((m == 1 && j == 0) || (m == 2 && j == 1))) {
                        //  Preconditions = new RequiresList();
                        //  Postconditions = new EnsuresList();
                        //  return; // throw new ExtractorException();
                        //}

                        Expression exception;

                        // The clump being extracted may contain code/blocks that represent (part of)
                        // the expression that is being thrown (if the original throw expression had
                        // control flow in it from boolean expressions and/or ternary expressions).

                        b.Statements[j] = null; // wipe out throw statement

                        currentClump = new Block(HelperMethods.ExtractClump(stmts, beginning, seginning, i, j));
                        int currentClumpLength = i - beginning + 1;

                        // there better be a next block because that must have been the target for all of the branches
                        // that didn't cause the throw to happen
                        if (!(i < n - 1))
                        {
                            this.HandleError(method, 1027, "Malformed contract.", s.SourceContext);
                            return false;
                        }

                        Block nextBlock = (Block) stmts[i + 1]; // cast succeeds because body is clump
                        Local valueOfPrecondition = new Local(Identifier.For("_preConditionHolds"), SystemTypes.Boolean);
                        Block preconditionHolds = new Block(new StatementList(new AssignmentStatement(valueOfPrecondition, Literal.True)));

                        ReplaceBranchTarget rbt = new ReplaceBranchTarget(nextBlock, preconditionHolds);
                        rbt.VisitBlock(currentClump);

                        int ILOffset;
                        CountPopExpressions cpe = new CountPopExpressions();
                        currentSourceContext = s.SourceContext;
                        cpe.Visit(s);

                        if (0 < cpe.PopOccurrences)
                        {
                            // then there is a set of blocks that represent the exception: the Reader
                            // was not able to decompile it back into an expression. Extract the set
                            // from the current clump and make it into a block expression

                            // Find the last block that has a branch to "preconditionHolds". After that are all of the blocks
                            // that represent the evaluation of the exception
                            int branchBlockIndex = currentClumpLength - 2;

                            // can't be the current block: that has the throw in it
                            while (0 <= branchBlockIndex)
                            {
                                Block possibleBranchBlock = currentClump.Statements[branchBlockIndex] as Block;
                                Branch br = possibleBranchBlock.Statements[possibleBranchBlock.Statements.Count - 1] as Branch;
                                if (br != null && br.Target == preconditionHolds)
                                {
                                    break;
                                }

                                branchBlockIndex--;
                            }

                            if (branchBlockIndex < 0)
                            {
                                this.HandleError(method, 1028, "Malformed exception constructor in contract.", defaultContext);
                                return false;
                            }

                            Block exceptionBlock =
                                new Block(HelperMethods.ExtractClump(currentClump.Statements, branchBlockIndex + 1, 0,
                                    currentClumpLength - 1,
                                    ((Block) currentClump.Statements[currentClumpLength - 1]).Statements.Count - 1));

                            exceptionBlock.Statements.Add(new ExpressionStatement(t.Expression));
                            SourceContext sctx = ((Block) exceptionBlock.Statements[0]).Statements[0].SourceContext;

                            if (sctx.IsValid)
                            {
                                currentSourceContext = sctx;
                            }
                            else
                            {
                                SourceContext tmp;
                                bool foundContext = HelperMethods.GetLastSourceContext(exceptionBlock.Statements, out tmp);
                                if (foundContext)
                                    currentSourceContext = tmp;
                            }

                            if (!CheckClump(method, gatherLocals, currentSourceContext, exceptionBlock)) return false;
                            
                            exception = new BlockExpression(exceptionBlock, SystemTypes.Exception);
                            ILOffset = t.ILOffset;
                        }
                        else
                        {
                            currentSourceContext = s.SourceContext;
                            if (t != null)
                            {
                                // then the statement is "throw ..."
                                exception = t.Expression;
                                ILOffset = t.ILOffset;
                            }
                            else
                            {
                                ExpressionStatement throwHelperCall = s as ExpressionStatement;

                                Debug.Assert(throwHelperCall != null);

                                exception = throwHelperCall.Expression;
                                ILOffset = s.ILOffset;
                            }

                            exception.SourceContext = currentSourceContext;
                            SourceContext tmp;

                            bool foundContext = HelperMethods.GetLastSourceContext(currentClump.Statements, out tmp);
                            if (foundContext)
                                currentSourceContext = tmp;
                        }

                        Block returnValueOfPrecondition = new Block(new StatementList(new ExpressionStatement(valueOfPrecondition)));
                        Statement extraAssumeFalse = this.ExtraAssumeFalseOnThrow();

                        Block preconditionFails =
                            new Block(new StatementList(new AssignmentStatement(valueOfPrecondition, Literal.False),
                                extraAssumeFalse, new Branch(null, returnValueOfPrecondition, true, false, false)));

                        //Block preconditionFails = new Block(new StatementList(new AssignmentStatement(valueOfPrecondition, Literal.False), new Branch(null, returnValueOfPrecondition, true, false, false)));
                        currentClump.Statements.Add(preconditionFails); // replace throw statement
                        currentClump.Statements.Add(preconditionHolds);
                        currentClump.Statements.Add(returnValueOfPrecondition);

                        if (!CheckClump(originalMethod, gatherLocals, currentSourceContext, currentClump)) return false;

                        BlockExpression be = new BlockExpression(currentClump, SystemTypes.Boolean);
                        be.SourceContext = currentSourceContext;

                        var ro = new RequiresOtherwise(be, exception);
                        ro.ILOffset = ILOffset;
                        ro.SourceContext = currentSourceContext;

                        if (postConditionFound)
                        {
                            HandleError(originalMethod, 1013, "Precondition found after postcondition.", currentSourceContext);
                            return false;
                        }

                        validations.Add(ro);

                        var req = new RequiresPlain(be, FindExceptionThrown.Find(exception));
                        req.IsFromValidation = true;
                        req.ILOffset = ro.ILOffset;
                        req.SourceContext = ro.SourceContext;

                        Preconditions.Add(req);
                    }
                    else
                    {
                        if (contractNodes.IsContractMethod(calledMethod))
                        {
                            // Treat calls to contract methods

                            if (endContractFound)
                            {
                                HandleError(originalMethod, 1012, "Contract call found after prior EndContractBlock.", s.SourceContext);
                                break;
                            }

                            if (contractNodes.IsEndContract(calledMethod))
                            {
                                endContractFound = true;
                                continue;
                            }

                            MethodCall mc = ((ExpressionStatement) s).Expression as MethodCall;
                            Expression arg = mc.Operands[0];
                            arg.SourceContext = s.SourceContext;
                            MethodContractElement mce;
                            currentSourceContext = s.SourceContext;
                            Expression condition;

                            if (beginning == i && seginning == j)
                            {
                                // Deal with the simple case: the reader decompiled the call into a single statement
                                condition = arg;
                            }
                            else
                            {
                                b.Statements[j] = new ExpressionStatement(arg);

                                // construct a clump from
                                // methodBody.Statements[beginning].Statements[seginning] to
                                // methodBody.Statements[i].Statements[j]
                                currentClump = new Block(HelperMethods.ExtractClump(stmts, beginning, seginning, i, j));
                                if (!currentSourceContext.IsValid)
                                {
                                    // then a good source context has not been found yet. Grovel around in the clump
                                    // to see if there is a better one
                                    SourceContext sctx;
                                    if (HelperMethods.FindContext(currentClump, currentSourceContext, out sctx))
                                        currentSourceContext = sctx;
                                }

                                if (!CheckClump(originalMethod, gatherLocals, currentSourceContext, currentClump))
                                    return false;

                                BlockExpression be = new BlockExpression(currentClump);
                                condition = be;
                            }

                            condition.SourceContext = currentSourceContext;
                            if (contractNodes.IsPlainPrecondition(calledMethod))
                            {
                                var req = new RequiresPlain(condition);
                                contractNodes.IsRequiresWithException(calledMethod, out req.ExceptionType);

                                mce = req;
                            }
                            else if (this.contractNodes.IsPostcondition(calledMethod))
                            {
                                mce = new EnsuresNormal(condition);
                            }
                            else if (contractNodes.IsExceptionalPostcondition(calledMethod))
                            {
                                EnsuresExceptional ee = new EnsuresExceptional(condition);
                                // Extract the type of exception.
                                ee.Type = calledMethod.TemplateArguments[0];
                                mce = ee;
                            }
                            else
                            {
                                throw new InvalidOperationException("Cannot recognize contract method");
                            }

                            mce.SourceContext = currentSourceContext;
                            mce.ILOffset = mc.ILOffset;
                            if (1 < mc.Operands.Count)
                            {
                                var candidate = SanitizeUserMessage(method, mc.Operands[1], currentSourceContext);
                                mce.UserMessage = candidate;
                            }
                            if (2 < mc.Operands.Count)
                            {
                                Literal lit = mc.Operands[2] as Literal;
                                if (lit != null)
                                {
                                    mce.SourceConditionText = lit;
                                }
                            }

                            // determine Model status

                            mce.UsesModels = CodeInspector.UsesModel(mce.Assertion, this.contractNodes);

                            // Check context rules

                            switch (mce.NodeType)
                            {
                                case NodeType.RequiresPlain:
                                    if (postConditionFound)
                                    {
                                        this.HandleError(originalMethod, 1014, "Precondition found after postcondition.", currentSourceContext);
                                        return false;
                                    }
                                    if (mce.UsesModels)
                                    {
                                        this.HandleError(originalMethod, 1073, "Preconditions may not refer to model members.", currentSourceContext);
                                        return false;
                                    }

                                    var rp = (RequiresPlain) mce;

                                    Preconditions.Add(rp);
                                    validations.Add(rp); // also add to the internal validation list
                                    break;

                                // TODO: check visibility of post conditions based on visibility of possible implementation
                                case NodeType.EnsuresNormal:
                                case NodeType.EnsuresExceptional:
                                    Ensures ensures = (Ensures) mce;
                                    if (mce.UsesModels)
                                    {
                                        if (this.IncludeModels)
                                        {
                                            modelPostconditions.Add(ensures);
                                        }
                                    }
                                    else
                                    {
                                        Postconditions.Add(ensures);
                                    }
                                    postConditionFound = true;
                                    break;
                            }
                        }
                        else if (ContractNodes.IsValidatorMethod(calledMethod))
                        {
                            // Treat calls to Contract validators

                            if (endContractFound)
                            {
                                this.HandleError(originalMethod, 1012,
                                    "Contract call found after prior EndContractBlock.", s.SourceContext);
                                break;
                            }

                            MethodCall mc = ((ExpressionStatement) s).Expression as MethodCall;
                            var memberBinding = (MemberBinding) mc.Callee;

                            currentSourceContext = s.SourceContext;
                            Statement validation;
                            Block validationPrefix;
                            if (beginning == i && seginning == j)
                            {
                                // Deal with the simple case: the reader decompiled the call into a single statement
                                validation = s;
                                validationPrefix = null;
                            }
                            else
                            {
                                // The clump may contain multiple statements ending in the validator call.
                                //   to extract the code as Requires<E>, we need to keep the statements preceeding
                                //   the validator call, as they may contain local initialization etc. These should go
                                //   into the first Requires<E> that the validator expands to. This way, if there are
                                //   no Requires<E> expanded from the validator, then the statements can be omitted.
                                //   At the same time, the statements won't be duplicated when validations are emitted.
                                //
                                //   If the validator call contains any pops, then the extraction must fail saying it
                                //   is too complicated.

                                // must null out statement with call before extract clump
                                b.Statements[j] = null; // we have a copy in mc, s
                                validationPrefix = new Block(HelperMethods.ExtractClump(stmts, beginning, seginning, i, j));

                                if (!currentSourceContext.IsValid)
                                {
                                    // then a good source context has not been found yet. Grovel around in the clump
                                    // to see if there is a better one
                                    SourceContext sctx;
                                    if (HelperMethods.FindContext(validationPrefix, currentSourceContext, out sctx))
                                        currentSourceContext = sctx;
                                }

                                if (CountPopExpressions.Count(mc) > 0)
                                {
                                    this.HandleError(method, 1071,
                                        "Arguments to contract validator call are too complicated. Please simplify.",
                                        currentSourceContext);
                                    return false;
                                }

                                if (!CheckClump(originalMethod, gatherLocals, currentSourceContext, validationPrefix))
                                    return false;

                                validation = new Block(new StatementList(validationPrefix, s));
                                validation.SourceContext = currentSourceContext;
                            }
                            var ro = new RequiresOtherwise(null, new BlockExpression(new Block(new StatementList(validation))));

                            validations.Add(ro);
                            CopyValidatorContracts(
                                method, calledMethod, memberBinding.TargetObject, mc.Operands,
                                Preconditions, currentSourceContext, validationPrefix);
                        }
                        else if (ContractNodes.IsAbbreviatorMethod(calledMethod))
                        {
                            // Treat calls to Contract abbreviators

                            if (endContractFound)
                            {
                                this.HandleError(originalMethod, 1012, "Contract call found after prior EndContractBlock.", s.SourceContext);
                                break;
                            }

                            MethodCall mc = ((ExpressionStatement) s).Expression as MethodCall;
                            var memberBinding = (MemberBinding) mc.Callee;
                            currentSourceContext = s.SourceContext;
                            if (beginning == i && seginning == j)
                            {
                                // Deal with the simple case: the reader decompiled the call into a single statement

                                // nothing to do. All is in the call and its arguments
                            }
                            else
                            {
                                // The clump may contain multiple statements ending in the abbreviator call.
                                // We need to keep the statements preceeding the abbreviator call and add them to the 
                                // contract initializer block. The reason we cannot add them to the first expansion contract
                                // of the abbreviator is that the abbreviator may give rise to closure initialization which will
                                // be hoisted into the closure initializer block. This closure initializer may refer to the
                                // locals initialized by the present statement sequence, so it must precede it. 
                                //
                                //   If the abbreviator call contains any pops, then the extraction must fail saying it
                                //   is too complicated.
                                // grab prefix of clump minus last call statement.

                                // must null out current call statement before we extract clump (ow. it stays in body)
                                b.Statements[j] = null;
                                currentClump = new Block(HelperMethods.ExtractClump(stmts, beginning, seginning, i, j));

                                if (!currentSourceContext.IsValid)
                                {
                                    // then a good source context has not been found yet. Grovel around in the clump
                                    // to see if there is a better one
                                    SourceContext sctx;
                                    if (HelperMethods.FindContext(currentClump, currentSourceContext, out sctx))
                                        currentSourceContext = sctx;
                                }

                                if (CountPopExpressions.Count(mc) > 0)
                                {
                                    this.HandleError(method, 1070,
                                        "Arguments to contract abbreviator call are too complicated. Please simplify.",
                                        currentSourceContext);
                                    return false;
                                }

                                if (!CheckClump(originalMethod, gatherLocals, currentSourceContext, currentClump))
                                    return false;

                                if (HelperMethods.IsNonTrivial(currentClump))
                                {
                                    contractInitializer.Statements.Add(currentClump);
                                }
                            }

                            CopyAbbreviatorContracts(method, calledMethod, memberBinding.TargetObject, mc.Operands,
                                Preconditions, Postconditions, currentSourceContext, validations, contractInitializer);
                        }
                        else
                        {
                            // important to continue here and accumulate blocks/statements for next contract!
                            if (i == beginning && j == seginning && s.NodeType == NodeType.Nop)
                            {
                                // nop following contract is often associated with previous code, so skip it
                                seginning = j + 1;
                            }

                            continue;
                        }
                    }

                    // Re-initialize current state after contract has been found

                    beginning = i;
                    seginning = j + 1;

                    //seginning = HelperMethods.FindNextRealStatement(((Block)stmts[i]).Statements, j + 1);
                    if (seginning < 0) seginning = 0;
                    
                    //b = (Block)stmts[i]; // IMPORTANT! Need this to keep "b" in sync
                }
            }

            if (this.verbose)
            {
                Console.WriteLine("\tNumber of Preconditions: " + Preconditions.Count);
                Console.WriteLine("\tNumber of Postconditions: " + Postconditions.Count);
            }

            return true;
        }
Example #2
0
 public virtual Expression VisitBlockExpression(BlockExpression blockExpression)
 {
     if (blockExpression == null) return null;
     blockExpression.Block = this.VisitBlock(blockExpression.Block);
     return blockExpression;
 }
        private void ExtractIndividualInvariants(TypeNode type, InvariantList result, Method invariantMethod)
        {
            if (invariantMethod == null || invariantMethod.Body == null || invariantMethod.Body.Statements == null ||
                invariantMethod.Body.Statements.Count == 0)
            {
                return;
            }

            Block invariantMethodBody = invariantMethod.Body;
            int n = invariantMethodBody.Statements.Count;

            int beginning = 0;

            while (beginning < invariantMethodBody.Statements.Count &&
                   invariantMethodBody.Statements[beginning] is PreambleBlock)
            {
                beginning++;
            }

            for (int i = beginning; i < n; i++)
            {
                Block b = (Block) invariantMethodBody.Statements[i];
                int seginning = 0;
                for (int j = 0, m = b.Statements == null ? 0 : b.Statements.Count; j < m; j++)
                {
                    ExpressionStatement s = b.Statements[j] as ExpressionStatement;
                    if (s == null) continue;

                    Literal invariantName;
                    Literal sourceText;
                    Expression invariantCondition = this.contractNodes.IsInvariant(s, out invariantName, out sourceText);
                    if (invariantCondition == null)
                    {
                        Method called = HelperMethods.IsMethodCall(s);
                        if (called != null)
                        {
                            if (HelperMethods.IsVoidType(called.ReturnType))
                            {
                                this.CallErrorFound(new Error(1045,
                                    "Invariant methods must be a sequence of calls to Contract.Invariant(...)",
                                    s.SourceContext));
                                return;
                            }
                        }

                        continue;
                    }

                    // construct a clump from
                    // invariantMethodBody.Statements[beginning].Statements[seginning] to
                    // invariantMethodBody.Statements[i].Statements[j]
                    Block currentClump = new Block(HelperMethods.ExtractClump(invariantMethodBody.Statements, beginning, seginning, i, j));

                    BlockExpression be = new BlockExpression(currentClump, SystemTypes.Void);
                    Invariant inv = new Invariant(type, be, invariantMethod.Name.Name);
                    inv.UserMessage = invariantName;
                    inv.SourceConditionText = sourceText;

                    SourceContext sctx;
                    if (HelperMethods.FindContext(currentClump, s.SourceContext, out sctx))
                    {
                        inv.SourceContext = sctx;
                        inv.Condition.SourceContext = sctx;
                    }

                    inv.ILOffset = s.ILOffset;
                    inv.UsesModels = CodeInspector.UsesModel(inv.Condition, this.contractNodes);
                    if (inv.UsesModels)
                    {
                        this.HandleError(invariantMethod, 1072, "Invariants cannot refer to model members.", sctx);
                    }
                    else
                    {
                        result.Add(inv);
                    }

                    // Re-initialize current state

                    beginning = i;
                    seginning = j + 1;
                    b = (Block) invariantMethodBody.Statements[i]; // IMPORTANT! Need this to keep "b" in sync
                }
            }
        }
Example #4
0
 public override Expression VisitBlockExpression(BlockExpression blockExpression)
 {
     if (blockExpression == null) return null;
     return base.VisitBlockExpression((BlockExpression)blockExpression.Clone());
 }
Example #5
0
    private Method MakeRequiresWithExceptionMethod(string name)
    {
      Parameter conditionParameter = new Parameter(Identifier.For("condition"), SystemTypes.Boolean);
      Parameter messageParameter = new Parameter(Identifier.For("msg"), SystemTypes.String);
      Parameter conditionTextParameter = new Parameter(Identifier.For("conditionTxt"), SystemTypes.String);
      MethodClassParameter typeArg = new MethodClassParameter();
      ParameterList pl = new ParameterList(conditionParameter, messageParameter, conditionTextParameter);

      Block body = new Block(new StatementList());
      Method m = new Method(this.RuntimeContractType, null, Identifier.For(name), pl, SystemTypes.Void, body);
      m.Flags = MethodFlags.Assembly | MethodFlags.Static;
      m.Attributes = new AttributeList();
      m.TemplateParameters = new TypeNodeList(typeArg);
      m.IsGeneric = true;
      this.RuntimeContractType.Members.Add(m);

      typeArg.Name = Identifier.For("TException");
      typeArg.DeclaringMember = m;
      typeArg.BaseClass = SystemTypes.Exception;
      typeArg.ParameterListIndex = 0;
      typeArg.DeclaringModule = this.RuntimeContractType.DeclaringModule;

      Block returnBlock = new Block(new StatementList(new Return()));

      Block b = new Block(new StatementList());
      b.Statements.Add(new Branch(conditionParameter, returnBlock));
      //
      // Generate the following
      //

      // // message == null means: yes we handled it. Otherwise it is the localized failure message
      // var message = RaiseFailureEvent(ContractFailureKind.Precondition, userMessage, conditionString, null);
      // #if assertOnFailure
      // if (message != null) {
      //   Assert(false, message);
      // }
      // #endif

      var messageLocal = new Local(Identifier.For("msg"), SystemTypes.String);
      
      ExpressionList elist = new ExpressionList();
      elist.Add(this.PreconditionKind);
      elist.Add(messageParameter);
      elist.Add(conditionTextParameter);
      elist.Add(Literal.Null);
      b.Statements.Add(new AssignmentStatement(messageLocal, new MethodCall(new MemberBinding(null, this.RaiseFailureEventMethod), elist)));

      if (this.AssertOnFailure)
      {
        var assertMethod = GetSystemDiagnosticsAssertMethod();
        if (assertMethod != null)
        {
          var skipAssert = new Block();
          b.Statements.Add(new Branch(new UnaryExpression(messageLocal, NodeType.LogicalNot), skipAssert));
          // emit assert call
          ExpressionList assertelist = new ExpressionList();
          assertelist.Add(Literal.False);
          assertelist.Add(messageLocal);
          b.Statements.Add(new ExpressionStatement(new MethodCall(new MemberBinding(null, assertMethod), assertelist)));
          b.Statements.Add(skipAssert);
        }
      }
      // // construct exception
      // Exception obj = null;
      // ConstructorInfo ci = typeof(TException).GetConstructor(new[] { typeof(string), typeof(string) });
      // if (ci != null)
      // {
      //   if (reflection.firstArgName == "paramName") {
      //     exceptionObject = ci.Invoke(new[] { userMessage, message }) as Exception;
      //   }
      //   else {
      //     exceptionObject = ci.Invoke(new[] { message, userMessage }) as Exception;
      //   }
      // }
      // else {
      //   ci = typeof(TException).GetConstructor(new[] { typeof(string) });
      //   if (ci != null)
      //   {
      //     exceptionObject = ci.Invoke(new[] { message }) as Exception;
      //   }
      // }
      var exceptionLocal = new Local(Identifier.For("obj"), SystemTypes.Exception);
      b.Statements.Add(new AssignmentStatement(exceptionLocal, Literal.Null));
      var constructorInfoType = TypeNode.GetTypeNode(typeof(System.Reflection.ConstructorInfo));
      Contract.Assume(constructorInfoType != null);
      var methodBaseType = TypeNode.GetTypeNode(typeof(System.Reflection.MethodBase));
      Contract.Assume(methodBaseType != null);
      var constructorLocal = new Local(Identifier.For("ci"), constructorInfoType);
      Contract.Assume(SystemTypes.Type != null);
      var getConstructorMethod = SystemTypes.Type.GetMethod(Identifier.For("GetConstructor"), SystemTypes.Type.GetArrayType(1));
      var typeofExceptionArg = GetTypeFromHandleExpression(typeArg);
      var typeofString = GetTypeFromHandleExpression(SystemTypes.String);
      var typeArrayLocal = new Local(Identifier.For("typeArray"), SystemTypes.Type.GetArrayType(1));
      var typeArray2 = new ConstructArray();
      typeArray2.ElementType = SystemTypes.Type;
      typeArray2.Rank = 1;
      typeArray2.Operands = new ExpressionList(Literal.Int32Two);
      var typeArrayInit2 = new Block(new StatementList());
      typeArrayInit2.Statements.Add(new AssignmentStatement(typeArrayLocal, typeArray2));
      typeArrayInit2.Statements.Add(new AssignmentStatement(new Indexer(typeArrayLocal, new ExpressionList(Literal.Int32Zero), SystemTypes.Type), typeofString));
      typeArrayInit2.Statements.Add(new AssignmentStatement(new Indexer(typeArrayLocal, new ExpressionList(Literal.Int32One), SystemTypes.Type), typeofString));
      typeArrayInit2.Statements.Add(new ExpressionStatement(typeArrayLocal));
      var typeArrayExpression2 = new BlockExpression(typeArrayInit2);
      b.Statements.Add(new AssignmentStatement(constructorLocal, new MethodCall(new MemberBinding(typeofExceptionArg, getConstructorMethod), new ExpressionList(typeArrayExpression2))));
      var elseBlock = new Block();
      b.Statements.Add(new Branch(new UnaryExpression(constructorLocal, NodeType.LogicalNot), elseBlock));
      var endifBlock2 = new Block();

      var invokeMethod = constructorInfoType.GetMethod(Identifier.For("Invoke"), SystemTypes.Object.GetArrayType(1));
      var argArray2 = new ConstructArray();
      argArray2.ElementType = SystemTypes.Object;
      argArray2.Rank = 1;
      argArray2.Operands = new ExpressionList(Literal.Int32Two);
      var argArrayLocal = new Local(Identifier.For("argArray"), SystemTypes.Object.GetArrayType(1));

      var parameterInfoType = TypeNode.GetTypeNode(typeof(System.Reflection.ParameterInfo));
      Contract.Assume(parameterInfoType != null);
      var parametersMethod = methodBaseType.GetMethod(Identifier.For("GetParameters"));
      var get_NameMethod = parameterInfoType.GetMethod(Identifier.For("get_Name"));
      var string_op_EqualityMethod = SystemTypes.String.GetMethod(Identifier.For("op_Equality"), SystemTypes.String, SystemTypes.String);
      var elseArgMsgBlock = new Block();
      var endIfArgMsgBlock = new Block();
      b.Statements.Add(new Branch(new UnaryExpression(new MethodCall(new MemberBinding(null, string_op_EqualityMethod), new ExpressionList(new MethodCall(new MemberBinding(new Indexer(new MethodCall(new MemberBinding(constructorLocal, parametersMethod), new ExpressionList(), NodeType.Callvirt), new ExpressionList(Literal.Int32Zero), parameterInfoType), get_NameMethod), new ExpressionList(), NodeType.Callvirt), new Literal("paramName", SystemTypes.String))), NodeType.LogicalNot), elseArgMsgBlock));

      var argArrayInit2 = new Block(new StatementList());
      argArrayInit2.Statements.Add(new AssignmentStatement(argArrayLocal, argArray2));
      argArrayInit2.Statements.Add(new AssignmentStatement(new Indexer(argArrayLocal, new ExpressionList(Literal.Int32Zero), SystemTypes.Object), messageParameter));
      argArrayInit2.Statements.Add(new AssignmentStatement(new Indexer(argArrayLocal, new ExpressionList(Literal.Int32One), SystemTypes.Object), messageLocal));
      argArrayInit2.Statements.Add(new ExpressionStatement(argArrayLocal));
      var argArrayExpression2 = new BlockExpression(argArrayInit2);
      b.Statements.Add(new AssignmentStatement(exceptionLocal, new BinaryExpression(new MethodCall(new MemberBinding(constructorLocal, invokeMethod), new ExpressionList(argArrayExpression2)), new Literal(SystemTypes.Exception), NodeType.Isinst)));
      b.Statements.Add(new Branch(null, endIfArgMsgBlock));
 
      b.Statements.Add(elseArgMsgBlock);
      var argArrayInit2_1 = new Block(new StatementList());
      argArrayInit2_1.Statements.Add(new AssignmentStatement(argArrayLocal, argArray2));
      argArrayInit2_1.Statements.Add(new AssignmentStatement(new Indexer(argArrayLocal, new ExpressionList(Literal.Int32Zero), SystemTypes.Object), messageLocal));
      argArrayInit2_1.Statements.Add(new AssignmentStatement(new Indexer(argArrayLocal, new ExpressionList(Literal.Int32One), SystemTypes.Object), messageParameter));
      argArrayInit2_1.Statements.Add(new ExpressionStatement(argArrayLocal));
      var argArrayExpression2_1 = new BlockExpression(argArrayInit2_1);
      b.Statements.Add(new AssignmentStatement(exceptionLocal, new BinaryExpression(new MethodCall(new MemberBinding(constructorLocal, invokeMethod), new ExpressionList(argArrayExpression2_1)), new Literal(SystemTypes.Exception), NodeType.Isinst)));

      b.Statements.Add(endIfArgMsgBlock);

      b.Statements.Add(new Branch(null, endifBlock2));

      b.Statements.Add(elseBlock);
      var typeArray1 = new ConstructArray();
      typeArray1.ElementType = SystemTypes.Type;
      typeArray1.Rank = 1;
      typeArray1.Operands = new ExpressionList(Literal.Int32One);
      var typeArrayInit1 = new Block(new StatementList());
      typeArrayInit1.Statements.Add(new AssignmentStatement(typeArrayLocal, typeArray1));
      typeArrayInit1.Statements.Add(new AssignmentStatement(new Indexer(typeArrayLocal, new ExpressionList(Literal.Int32Zero), SystemTypes.Type), typeofString));
      typeArrayInit1.Statements.Add(new ExpressionStatement(typeArrayLocal));
      var typeArrayExpression1 = new BlockExpression(typeArrayInit1);
      b.Statements.Add(new AssignmentStatement(constructorLocal, new MethodCall(new MemberBinding(typeofExceptionArg, getConstructorMethod), new ExpressionList(typeArrayExpression1))));

      b.Statements.Add(new Branch(new UnaryExpression(constructorLocal, NodeType.LogicalNot), endifBlock2));
      var argArray1 = new ConstructArray();
      argArray1.ElementType = SystemTypes.Object;
      argArray1.Rank = 1;
      argArray1.Operands = new ExpressionList(Literal.Int32One);
      var argArrayInit1 = new Block(new StatementList());
      argArrayInit1.Statements.Add(new AssignmentStatement(argArrayLocal, argArray1));
      argArrayInit1.Statements.Add(new AssignmentStatement(new Indexer(argArrayLocal, new ExpressionList(Literal.Int32Zero), SystemTypes.Object), messageLocal));
      argArrayInit1.Statements.Add(new ExpressionStatement(argArrayLocal));
      var argArrayExpression1 = new BlockExpression(argArrayInit1);
      b.Statements.Add(new AssignmentStatement(exceptionLocal, new BinaryExpression(new MethodCall(new MemberBinding(constructorLocal, invokeMethod), new ExpressionList(argArrayExpression1)), new Literal(SystemTypes.Exception), NodeType.Isinst)));

      b.Statements.Add(endifBlock2);

      // // throw it
      // if (exceptionObject == null)
      // {
      //   throw new ArgumentException(displayMessage, message);
      // }
      // else
      // {
      //   throw exceptionObject;
      // }
      var thenBlock3 = new Block();

      b.Statements.Add(new Branch(exceptionLocal, thenBlock3));
      b.Statements.Add(new Throw(new Construct(new MemberBinding(null, SystemTypes.ArgumentException.GetConstructor(SystemTypes.String, SystemTypes.String)), new ExpressionList(messageLocal, messageParameter))));
      b.Statements.Add(thenBlock3);
      b.Statements.Add(new Throw(exceptionLocal));
      b.Statements.Add(returnBlock);
      Contract.Assume(body.Statements != null);
      body.Statements.Add(b);

      Member constructor = null;
      AttributeNode attribute = null;

      #region Add [DebuggerNonUserCodeAttribute]
      if (this.HideFromDebugger) {
        TypeNode debuggerNonUserCode = SystemTypes.SystemAssembly.GetType(Identifier.For("System.Diagnostics"), Identifier.For("DebuggerNonUserCodeAttribute"));
        if (debuggerNonUserCode != null)
        {
            constructor = debuggerNonUserCode.GetConstructor();
            attribute = new AttributeNode(new MemberBinding(null, constructor), null, AttributeTargets.Method);
            m.Attributes.Add(attribute);
        }
      }
      #endregion Add [DebuggerNonUserCodeAttribute]

      TypeNode reliabilityContract = SystemTypes.SystemAssembly.GetType(Identifier.For("System.Runtime.ConstrainedExecution"), Identifier.For("ReliabilityContractAttribute"));
      TypeNode consistency = SystemTypes.SystemAssembly.GetType(Identifier.For("System.Runtime.ConstrainedExecution"), Identifier.For("Consistency"));
      TypeNode cer = SystemTypes.SystemAssembly.GetType(Identifier.For("System.Runtime.ConstrainedExecution"), Identifier.For("Cer"));
      if (reliabilityContract != null && consistency != null && cer != null)
      {
          constructor = reliabilityContract.GetConstructor(consistency, cer);
          if (constructor != null)
          {
              attribute = new AttributeNode(
                new MemberBinding(null, constructor),
                new ExpressionList(
                  new Literal(System.Runtime.ConstrainedExecution.Consistency.WillNotCorruptState, consistency),
                  new Literal(System.Runtime.ConstrainedExecution.Cer.MayFail, cer)),
                  AttributeTargets.Method
                  );
              m.Attributes.Add(attribute);
          }
      }
      return m;
    }
Example #6
0
    //TODO: get rid of stateAfterBrace
    private Expression ParseBlockExpression(ScannerState stateAfterBrace, object sctx, TokenSet followers){
      bool savedSawReturnOrYield = this.sawReturnOrYield;
      this.sawReturnOrYield = false;
      Block block = new Block();
      block.Checked = this.insideCheckedBlock;
      block.IsUnsafe = this.inUnsafeCode;
      block.SuppressCheck = this.insideUncheckedBlock;
      SourceContext ctx = (SourceContext)sctx;
      ctx.EndPos = this.scanner.CurrentSourceContext.EndPos;
      Debug.Assert(this.currentToken == Token.LeftBrace);
//      this.GetNextToken();
      block.SourceContext = ctx;
      block.Statements = new StatementList(new ExpressionStatement(ParseComprehension(followers)));
//      block.Statements = this.ParseStatementsWithOptionalExpression(followers|Token.RightBrace);
      if (this.arrayInitializerOpeningContext != null && block.Statements == null && this.currentToken == Token.RightBrace){
        this.GetNextToken();
        this.sawReturnOrYield = savedSawReturnOrYield;
        return null;
      }
      block.SourceContext.EndPos = this.scanner.CurrentSourceContext.EndPos;
      this.scanner.state = stateAfterBrace;
//      this.ParseBracket(ctx, Token.RightBrace, followers, Error.ExpectedRightBrace);
      Expression result = null;
      if (sawReturnOrYield)
        result = new AnonymousNestedFunction(new ParameterList(0), block);
      else
        result = new BlockExpression(block);
      result.SourceContext = ctx;
      this.sawReturnOrYield = savedSawReturnOrYield;
      return result;
    }
Example #7
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;
    }
Example #8
0
		public override Expression VisitBlockExpression(BlockExpression blockExpression)
		{
			// recursively flatten the block(s)
			this.FlattenBlock(blockExpression.Block);

			// the code generated from the blocks leaves the expression value on the evaluation stack
			// So we return a pop expression here.

      return Pop(blockExpression.Type);
		}
Example #9
0
 public override Expression VisitBlockExpression(BlockExpression blockExpression) {
   Block block = blockExpression.Block;
   if (block == null) return blockExpression;
   StatementList sl = block.Statements;
   if (sl == null) return blockExpression;
   if (sl.Count == 2 && this.Eliminate(sl[0])) {
     // the entire expression turns into the expression of the expression statement at sl[1]
     ExpressionStatement es = (ExpressionStatement)sl[1];
     WarnIfExplicit(sl[0] as ExpressionStatement);
     return VisitExpression(es.Expression);
   }
   if (sl.Count == 3 && this.Eliminate(sl[1])) {
     // the entire expression turns into the Source of the assignment at sl[0]
     AssignmentStatement asg = (AssignmentStatement)sl[0];
     WarnIfExplicit(sl[1] as ExpressionStatement);
     return VisitExpression(asg.Source);
   }
   return base.VisitBlockExpression(blockExpression);
 }
Example #10
0
 public override Expression VisitBlockExpression(BlockExpression blockExpression)
 {
     throw new NotImplementedException("Node type not yet supported");
 }
 public EventingVisitor(Action<BlockExpression> visitBlockExpression) { VisitedBlockExpression += visitBlockExpression; } public event Action<BlockExpression> VisitedBlockExpression; public override Expression VisitBlockExpression(BlockExpression blockExpression) { if (VisitedBlockExpression != null) VisitedBlockExpression(blockExpression); return base.VisitBlockExpression(blockExpression); }
        private Expression ExtractOldExpression(MethodCall call)
        {
            var cand = call.Operands[0];

            if (this.currentSL != null)
            {
                var locs = FindLocals.Get(cand);
                if (locs.Count > 0)
                {
                    // find the instructions that set these locals
                    var assignments = new List<Statement>();
                    for (int i = this.currentSLindex - 1; i >= 0; i--)
                    {
                        var a = this.currentSL[i] as AssignmentStatement;
                        if (a == null) continue;

                        var loc = a.Target as Local;
                        if (loc == null) continue;

                        if (locs.Contains(loc))
                        {
                            assignments.Add(a);
                            this.currentSL[i] = null;
                            locs.Remove(loc);
                        }

                        if (locs.Count == 0) break;
                    }
                    assignments.Reverse();

                    var be = new StatementList();
                    assignments.ForEach(astmt => be.Add(astmt));

                    be.Add(new ExpressionStatement(cand));
                    var sc = cand.SourceContext;

                    cand = new BlockExpression(new Block(be));
                    cand.SourceContext = sc;

                    if (locs.Count > 0)
                    {
                        // warn that we couldn't extract the local
                    }
                }
            }

            return cand;
        }