コード例 #1
0
        private bool FullyHandlesItsInput(BoundPatternSwitchStatement node)
        {
            // If the switch is complete (for example, because it has a default label),
            // just return true.
            if (node.IsComplete)
            {
                return(true);
            }

            // We also check for completeness based on value. Other cases were handled in the construction of the decision tree.
            if (node.Expression.ConstantValue == null)
            {
                return(false);
            }

            foreach (var section in node.SwitchSections)
            {
                foreach (var label in section.SwitchLabels)
                {
                    if (label.Guard != null && label.Guard.ConstantValue != ConstantValue.True)
                    {
                        continue;
                    }

                    if (label.Pattern.Kind == BoundKind.ConstantPattern &&
                        ((BoundConstantPattern)label.Pattern).ConstantValue == node.Expression.ConstantValue)
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
コード例 #2
0
        private void VisitPatternSwitchBlock(BoundPatternSwitchStatement node)
        {
            var afterSwitchState = UnreachableState();
            var switchSections   = node.SwitchSections;
            var iLastSection     = (switchSections.Length - 1);

            // simulate the dispatch (setting pattern variables and jumping to labels) using the decision tree
            VisitDecisionTree(node.DecisionTree);

            // we always consider the default label reachable for flow analysis purposes.
            if (node.DefaultLabel != null)
            {
                _pendingBranches.Add(new PendingBranch(node.DefaultLabel, this.State));
            }

            // visit switch sections
            for (var iSection = 0; iSection <= iLastSection; iSection++)
            {
                VisitPatternSwitchSection(switchSections[iSection], node.Expression, iSection == iLastSection);
                // Even though it is illegal for the end of a switch section to be reachable, in erroneous
                // code it may be reachable.  We treat that as an implicit break (branch to afterSwitchState).
                IntersectWith(ref afterSwitchState, ref this.State);
            }

            SetState(afterSwitchState);
        }
コード例 #3
0
        public override BoundNode VisitPatternSwitchStatement(BoundPatternSwitchStatement node)
        {
            // The pattern switch statement has computed a state machine, and gathered diagnostics
            // related to subsumption. We report those here.
            Diagnostics.AddRange(node.DecisionTreeDiagnostics);

            return(base.VisitPatternSwitchStatement(node));
        }
コード例 #4
0
 public PatternSwitchLocalRewriter(LocalRewriter localRewriter, BoundPatternSwitchStatement node)
 {
     this.LocalRewriter = localRewriter;
     this._factory = localRewriter._factory;
     foreach (var section in node.SwitchSections)
     {
         SwitchSections.Add(section, ArrayBuilder<BoundStatement>.GetInstance());
     }
 }
コード例 #5
0
        private void VisitPatternSwitchBlock(BoundPatternSwitchStatement node)
        {
            var initialState     = this.State;
            var afterSwitchState = UnreachableState();
            var switchSections   = node.SwitchSections;
            var iLastSection     = (switchSections.Length - 1);

            // simulate the dispatch (setting pattern variables and jumping to labels) to
            // all reachable switch labels
            foreach (var section in switchSections)
            {
                foreach (var label in section.SwitchLabels)
                {
                    if (label.IsReachable && label != node.DefaultLabel)
                    {
                        SetState(initialState.Clone());
                        // assign pattern variables
                        VisitPattern(null, label.Pattern);
                        SetState(StateWhenTrue);
                        if (label.Guard != null)
                        {
                            VisitCondition(label.Guard);
                            SetState(StateWhenTrue);
                        }

                        _pendingBranches.Add(new PendingBranch(label, this.State));
                    }
                }
            }

            // we always consider the default label reachable for flow analysis purposes
            // unless there was a single case that would match every input.
            if (node.DefaultLabel != null)
            {
                if (node.SomeLabelAlwaysMatches)
                {
                    SetUnreachable();
                }
                else
                {
                    SetState(initialState.Clone());
                }

                _pendingBranches.Add(new PendingBranch(node.DefaultLabel, this.State));
            }

            // visit switch sections
            for (var iSection = 0; iSection <= iLastSection; iSection++)
            {
                VisitPatternSwitchSection(switchSections[iSection], node.Expression, iSection == iLastSection);
                // Even though it is illegal for the end of a switch section to be reachable, in erroneous
                // code it may be reachable.  We treat that as an implicit break (branch to afterSwitchState).
                IntersectWith(ref afterSwitchState, ref this.State);
            }

            SetState(afterSwitchState);
        }
コード例 #6
0
 public PatternSwitchLocalRewriter(LocalRewriter localRewriter, BoundPatternSwitchStatement node)
 {
     this.LocalRewriter = localRewriter;
     this._factory      = localRewriter._factory;
     foreach (var section in node.SwitchSections)
     {
         SwitchSections.Add(section, ArrayBuilder <BoundStatement> .GetInstance());
     }
 }
コード例 #7
0
        public override BoundNode VisitPatternSwitchStatement(BoundPatternSwitchStatement node)
        {
            _factory.Syntax = node.Syntax;
            var pslr       = new PatternSwitchLocalRewriter(this, node);
            var expression = VisitExpression(node.Expression);

            // EnC: We need to insert a hidden sequence point to handle function remapping in case
            // the containing method is edited while methods invoked in the expression are being executed.
            if (!node.WasCompilerGenerated && this.Instrument)
            {
                expression = _instrumenter.InstrumentSwitchStatementExpression(node, expression, _factory);
            }

            var result = ArrayBuilder <BoundStatement> .GetInstance();

            // output the decision tree part
            pslr.LowerDecisionTree(expression, node.DecisionTree, result);

            // if the endpoint is reachable, we exit the switch
            if (!node.DecisionTree.MatchIsComplete)
            {
                result.Add(_factory.Goto(node.BreakLabel));
            }
            // at this point the end of result is unreachable.

            // output the sections of code
            foreach (var section in node.SwitchSections)
            {
                // Start with the part of the decision tree that is in scope of the section variables.
                // Its endpoint is not reachable (it jumps back into the decision tree code).
                var sectionBuilder = pslr.SwitchSections[section];

                // Add labels corresponding to the labels of the switch section.
                foreach (var label in section.SwitchLabels)
                {
                    sectionBuilder.Add(_factory.Label(label.Label));
                }

                // Add the translated body of the switch section
                sectionBuilder.AddRange(VisitList(section.Statements));
                sectionBuilder.Add(_factory.Goto(node.BreakLabel));
                result.Add(_factory.Block(section.Locals, sectionBuilder.ToImmutableAndFree()));
                // at this point the end of result is unreachable.
            }

            result.Add(_factory.Label(node.BreakLabel));
            BoundStatement translatedSwitch = _factory.Block(pslr.DeclaredTemps.ToImmutableArray().Concat(node.InnerLocals), node.InnerLocalFunctions, result.ToImmutableAndFree());

            // Only add instrumentation (such as a sequence point) if the node is not compiler-generated.
            if (!node.WasCompilerGenerated && this.Instrument)
            {
                translatedSwitch = _instrumenter.InstrumentPatternSwitchStatement(node, translatedSwitch);
            }

            return(translatedSwitch);
        }
コード例 #8
0
        // Rewriting for pattern-matching switch statements.
        public override BoundNode VisitPatternSwitchStatement(BoundPatternSwitchStatement node)
        {
            var statements = ArrayBuilder <BoundStatement> .GetInstance();

            // copy the original switch expression into a temp
            BoundAssignmentOperator initialStore;
            var switchExpressionTemp = _factory.StoreToTemp(VisitExpression(node.Expression), out initialStore, syntaxOpt: node.Expression.Syntax);

            statements.Add(_factory.ExpressionStatement(initialStore));

            // save the default label, if and when we find it.
            LabelSymbol defaultLabel = null;

            foreach (var section in node.PatternSwitchSections)
            {
                BoundExpression sectionCondition = _factory.Literal(false);
                bool            isDefaultSection = false;
                foreach (var label in section.PatternSwitchLabels)
                {
                    if (label.Syntax.Kind() == SyntaxKind.DefaultSwitchLabel)
                    {
                        // The default label was handled in initial tail, above
                        Debug.Assert(label.Pattern.Kind == BoundKind.WildcardPattern && label.Guard == null);
                        isDefaultSection = true;
                        defaultLabel     = _factory.GenerateLabel("default");
                        continue;
                    }

                    var labelCondition = LowerPattern(label.Pattern, switchExpressionTemp);
                    if (label.Guard != null)
                    {
                        labelCondition = _factory.LogicalAnd(labelCondition, VisitExpression(label.Guard));
                    }

                    sectionCondition = _factory.LogicalOr(sectionCondition, labelCondition);
                }

                var sectionBuilder = ArrayBuilder <BoundStatement> .GetInstance();

                if (isDefaultSection)
                {
                    sectionBuilder.Add(_factory.Label(defaultLabel));
                }
                sectionBuilder.AddRange(VisitList(section.Statements));
                sectionBuilder.Add(_factory.Goto(node.BreakLabel));
                statements.Add(_factory.If(sectionCondition, section.Locals, _factory.Block(sectionBuilder.ToImmutableAndFree())));
            }

            if (defaultLabel != null)
            {
                statements.Add(_factory.Goto(defaultLabel));
            }

            statements.Add(_factory.Label(node.BreakLabel));
            return(_factory.Block(node.InnerLocals.Add(switchExpressionTemp.LocalSymbol), node.InnerLocalFunctions, statements.ToImmutableAndFree()));
        }
コード例 #9
0
        public override BoundNode VisitPatternSwitchStatement(BoundPatternSwitchStatement node)
        {
            // visit switch header
            LocalState breakState = VisitPatternSwitchHeader(node);

            // visit switch block
            VisitPatternSwitchBlock(node);
            IntersectWith(ref breakState, ref this.State);
            ResolveBreaks(breakState, node.BreakLabel);
            return(null);
        }
コード例 #10
0
ファイル: DecisionTree.cs プロジェクト: kusl/roslyn-1
 public DecisionTreeComputer(
     Symbol enclosingSymbol,
     DiagnosticBag diagnostics,
     BoundPatternSwitchStatement switchStatement,
     Conversions conversions)
 {
     this._enclosingSymbol = enclosingSymbol;
     this._diagnostics     = diagnostics;
     this._switchStatement = switchStatement;
     this._conversions     = conversions;
 }
コード例 #11
0
 private PatternSwitchLocalRewriter(LocalRewriter localRewriter, BoundPatternSwitchStatement node)
     : base(localRewriter._factory.CurrentMethod, (SwitchStatementSyntax)node.Syntax, localRewriter._factory.Compilation.Conversions)
 {
     this._localRewriter  = localRewriter;
     this._factory        = localRewriter._factory;
     this._factory.Syntax = node.Syntax;
     foreach (var section in node.SwitchSections)
     {
         _switchSections.Add(section.Syntax, ArrayBuilder <BoundStatement> .GetInstance());
     }
 }
コード例 #12
0
        // Rewriting for pattern-matching switch statements.
        public override BoundNode VisitPatternSwitchStatement(BoundPatternSwitchStatement node)
        {
            var statements = ArrayBuilder<BoundStatement>.GetInstance();

            // copy the original switch expression into a temp
            BoundAssignmentOperator initialStore;
            var switchExpressionTemp = _factory.StoreToTemp(VisitExpression(node.Expression), out initialStore, syntaxOpt: node.Expression.Syntax);
            statements.Add(_factory.ExpressionStatement(initialStore));

            // save the default label, if and when we find it.
            LabelSymbol defaultLabel = null;

            foreach (var section in node.PatternSwitchSections)
            {
                BoundExpression sectionCondition = _factory.Literal(false);
                bool isDefaultSection = false;
                foreach (var label in section.PatternSwitchLabels)
                {
                    if (label.Syntax.Kind() == SyntaxKind.DefaultSwitchLabel)
                    {
                        // The default label was handled in initial tail, above
                        Debug.Assert(label.Pattern.Kind == BoundKind.WildcardPattern && label.Guard == null);
                        isDefaultSection = true;
                        defaultLabel = _factory.GenerateLabel("default");
                        continue;
                    }

                    var labelCondition = LowerPattern(label.Pattern, switchExpressionTemp);
                    if (label.Guard != null)
                    {
                        labelCondition = _factory.LogicalAnd(labelCondition, VisitExpression(label.Guard));
                    }

                    sectionCondition = _factory.LogicalOr(sectionCondition, labelCondition);
                }

                var sectionBuilder = ArrayBuilder<BoundStatement>.GetInstance();
                if (isDefaultSection)
                {
                    sectionBuilder.Add(_factory.Label(defaultLabel));
                }
                sectionBuilder.AddRange(VisitList(section.Statements));
                sectionBuilder.Add(_factory.Goto(node.BreakLabel));
                statements.Add(_factory.If(sectionCondition, section.Locals, _factory.Block(sectionBuilder.ToImmutableAndFree())));
            }

            if (defaultLabel != null)
            {
                statements.Add(_factory.Goto(defaultLabel));
            }

            statements.Add(_factory.Label(node.BreakLabel));
            return _factory.Block(node.InnerLocals.Add(switchExpressionTemp.LocalSymbol), node.InnerLocalFunctions, statements.ToImmutableAndFree());
        }
コード例 #13
0
 private PatternSwitchLocalRewriter(LocalRewriter localRewriter, BoundPatternSwitchStatement node)
     : base(localRewriter._factory.CurrentMethod, localRewriter._factory.Compilation.Conversions)
 {
     this._localRewriter = localRewriter;
     this._factory = localRewriter._factory;
     this._factory.Syntax = node.Syntax;
     foreach (var section in node.SwitchSections)
     {
         _switchSections.Add((SyntaxNode)section.Syntax, ArrayBuilder<BoundStatement>.GetInstance());
     }
 }
コード例 #14
0
        public override BoundStatement InstrumentPatternSwitchStatement(BoundPatternSwitchStatement original, BoundStatement rewritten)
        {
            SwitchStatementSyntax switchSyntax = (SwitchStatementSyntax)original.Syntax;
            TextSpan switchSequencePointSpan   = TextSpan.FromBounds(
                switchSyntax.SwitchKeyword.SpanStart,
                switchSyntax.CloseParenToken.Span.End);

            return(new BoundSequencePointWithSpan(
                       syntax: switchSyntax,
                       statementOpt: base.InstrumentPatternSwitchStatement(original, rewritten),
                       span: switchSequencePointSpan,
                       hasErrors: false));
        }
コード例 #15
0
        public override BoundNode VisitPatternSwitchStatement(BoundPatternSwitchStatement node)
        {
            _factory.Syntax = node.Syntax;
            var pslr = new PatternSwitchLocalRewriter(this, node);
            var expression = VisitExpression(node.Expression);
            var result = ArrayBuilder<BoundStatement>.GetInstance();

            // output the decision tree part
            pslr.LowerDecisionTree(expression, node.DecisionTree, result);

            // if the endpoint is reachable, we exit the switch
            if (!node.DecisionTree.MatchIsComplete)
            {
                result.Add(_factory.Goto(node.BreakLabel));
            }
            // at this point the end of result is unreachable.

            // output the sections of code
            foreach (var section in node.SwitchSections)
            {
                // Start with the part of the decision tree that is in scope of the section variables.
                // Its endpoint is not reachable (it jumps back into the decision tree code).
                var sectionBuilder = pslr.SwitchSections[section];

                // Add labels corresponding to the labels of the switch section.
                foreach (var label in section.SwitchLabels)
                {
                    sectionBuilder.Add(_factory.Label(label.Label));
                }

                // Add the translated body of the switch section
                sectionBuilder.AddRange(VisitList(section.Statements));
                sectionBuilder.Add(_factory.Goto(node.BreakLabel));
                result.Add(_factory.Block(section.Locals, sectionBuilder.ToImmutableAndFree()));
                // at this point the end of result is unreachable.
            }

            result.Add(_factory.Label(node.BreakLabel));
            BoundStatement translatedSwitch = _factory.Block(pslr.DeclaredTemps.ToImmutableArray().Concat(node.InnerLocals), node.InnerLocalFunctions, result.ToImmutableAndFree());

            // Create the sequence point if generating debug info and
            // node is not compiler generated
            if (this.Instrument && !node.WasCompilerGenerated)
            {
                translatedSwitch = _instrumenter.InstrumentBoundPatternSwitchStatement(node, translatedSwitch);
            }

            return translatedSwitch;
        }
コード例 #16
0
        public override BoundNode VisitPatternSwitchStatement(BoundPatternSwitchStatement node)
        {
            _factory.Syntax = node.Syntax;
            var pslr       = new PatternSwitchLocalRewriter(this, node);
            var expression = VisitExpression(node.Expression);
            var result     = ArrayBuilder <BoundStatement> .GetInstance();

            // output the decision tree part
            pslr.LowerDecisionTree(expression, node.DecisionTree, result);

            // if the endpoint is reachable, we exit the switch
            if (!node.DecisionTree.MatchIsComplete)
            {
                result.Add(_factory.Goto(node.BreakLabel));
            }
            // at this point the end of result is unreachable.

            // output the sections of code
            foreach (var section in node.SwitchSections)
            {
                // Start with the part of the decision tree that is in scope of the section variables.
                // Its endpoint is not reachable (it jumps back into the decision tree code).
                var sectionBuilder = pslr.SwitchSections[section];

                // Add labels corresponding to the labels of the switch section.
                foreach (var label in section.SwitchLabels)
                {
                    sectionBuilder.Add(_factory.Label(label.Label));
                }

                // Add the translated body of the switch section
                sectionBuilder.AddRange(VisitList(section.Statements));
                sectionBuilder.Add(_factory.Goto(node.BreakLabel));
                result.Add(_factory.Block(section.Locals, sectionBuilder.ToImmutableAndFree()));
                // at this point the end of result is unreachable.
            }

            result.Add(_factory.Label(node.BreakLabel));
            BoundStatement translatedSwitch = _factory.Block(pslr.DeclaredTemps.ToImmutableArray().Concat(node.InnerLocals), node.InnerLocalFunctions, result.ToImmutableAndFree());

            // Create the sequence point if generating debug info and
            // node is not compiler generated
            if (this.Instrument && !node.WasCompilerGenerated)
            {
                translatedSwitch = _instrumenter.InstrumentBoundPatternSwitchStatement(node, translatedSwitch);
            }

            return(translatedSwitch);
        }
コード例 #17
0
        /// <summary>
        /// Visit the switch expression, and return the initial break state.
        /// </summary>
        private LocalState VisitPatternSwitchHeader(BoundPatternSwitchStatement node)
        {
            // visit switch expression
            VisitRvalue(node.Expression);

            // return the exit state to use if no pattern matches
            if (FullyHandlesItsInput(node.DecisionTree))
            {
                return(UnreachableState());
            }
            else
            {
                return(this.State);
            }
        }
コード例 #18
0
        private void VisitPatternSwitchBlock(BoundPatternSwitchStatement node)
        {
            var afterSwitchState = UnreachableState();
            var switchSections   = node.PatternSwitchSections;
            var iLastSection     = (switchSections.Length - 1);
            var dispatchState    = this.State.Clone();

            // visit switch sections
            for (var iSection = 0; iSection <= iLastSection; iSection++)
            {
                SetState(dispatchState.Clone());
                VisitPatternSwitchSection(switchSections[iSection], node.Expression, iSection == iLastSection);
                // Even though it is illegal for the end of a switch section to be reachable, in erroneous
                // code it may be reachable.  We treat that as an implicit break (branch to afterSwitchState).
                IntersectWith(ref afterSwitchState, ref this.State);
            }

            SetState(afterSwitchState);
        }
コード例 #19
0
            private DecisionTree LowerToDecisionTree(
                BoundExpression loweredExpression,
                BoundPatternSwitchStatement node)
            {
                var loweredDecisionTree = DecisionTree.Create(loweredExpression, loweredExpression.Type, _enclosingSymbol);
                BoundPatternSwitchLabel defaultLabel = null;
                SyntaxNode defaultSection            = null;

                foreach (var section in node.SwitchSections)
                {
                    var sectionSyntax = (SyntaxNode)section.Syntax;
                    foreach (var label in section.SwitchLabels)
                    {
                        var loweredLabel = LowerSwitchLabel(label);
                        if (loweredLabel.Syntax.Kind() == SyntaxKind.DefaultSwitchLabel)
                        {
                            if (defaultLabel != null)
                            {
                                // duplicate switch label will have been reported during initial binding.
                            }
                            else
                            {
                                defaultLabel   = loweredLabel;
                                defaultSection = sectionSyntax;
                            }
                        }
                        else
                        {
                            Syntax = label.Syntax;
                            AddToDecisionTree(loweredDecisionTree, sectionSyntax, loweredLabel);
                        }
                    }
                }

                if (defaultLabel != null)
                {
                    Add(loweredDecisionTree, (e, t) => new DecisionTree.Guarded(loweredExpression, loweredExpression.Type, default(ImmutableArray <KeyValuePair <BoundExpression, BoundExpression> >), defaultSection, null, defaultLabel));
                }

                // We discard use-site diagnostics, as they have been reported during initial binding.
                _useSiteDiagnostics.Clear();
                return(loweredDecisionTree);
            }
コード例 #20
0
            private DecisionTree LowerToDecisionTree(
                BoundExpression loweredExpression,
                BoundPatternSwitchStatement node)
            {
                var loweredDecisionTree = CreateEmptyDecisionTree(loweredExpression);
                BoundPatternSwitchLabel defaultLabel = null;
                SyntaxNode defaultSection            = null;

                foreach (var section in node.SwitchSections)
                {
                    var sectionSyntax = section.Syntax;
                    foreach (var label in section.SwitchLabels)
                    {
                        var loweredLabel = LowerSwitchLabel(label);
                        if (loweredLabel.Syntax.Kind() == SyntaxKind.DefaultSwitchLabel)
                        {
                            if (defaultLabel != null)
                            {
                                // duplicate switch label will have been reported during initial binding.
                            }
                            else
                            {
                                defaultLabel   = loweredLabel;
                                defaultSection = sectionSyntax;
                            }
                        }
                        else
                        {
                            AddToDecisionTree(loweredDecisionTree, sectionSyntax, loweredLabel);
                        }
                    }
                }

                if (defaultLabel != null && !loweredDecisionTree.MatchIsComplete)
                {
                    Add(loweredDecisionTree, (e, t) => new DecisionTree.Guarded(
                            expression: loweredExpression,
                            type: loweredExpression.Type,
                            bindings: default,
コード例 #21
0
        /// <summary>
        /// Visit the switch expression, and return the initial break state.
        /// </summary>
        private LocalState VisitPatternSwitchHeader(BoundPatternSwitchStatement node)
        {
            // decide if the switch has the moral equivalent of a default label.
            bool hasDefaultLabel = false;

            foreach (var section in node.PatternSwitchSections)
            {
                foreach (var boundPatternSwitchLabel in section.PatternSwitchLabels)
                {
                    if (boundPatternSwitchLabel.Guard != null && !IsConstantTrue(boundPatternSwitchLabel.Guard))
                    {
                        continue;
                    }

                    if (boundPatternSwitchLabel.Pattern.Kind == BoundKind.WildcardPattern ||
                        boundPatternSwitchLabel.Pattern.Kind == BoundKind.DeclarationPattern && ((BoundDeclarationPattern)boundPatternSwitchLabel.Pattern).IsVar)
                    {
                        hasDefaultLabel = true;
                        goto foundDefaultLabel;
                    }
                }
            }
            foundDefaultLabel :;

            // visit switch expression
            VisitRvalue(node.Expression);

            // return the state to use if no pattern matches
            if (hasDefaultLabel)
            {
                return(UnreachableState());
            }
            else
            {
                return(this.State);
            }
        }
コード例 #22
0
ファイル: DebugInfoInjector.cs プロジェクト: xeronith/roslyn
        public override BoundStatement InstrumentBoundPatternSwitchStatement(BoundPatternSwitchStatement original, BoundStatement rewritten)
        {
            SwitchStatementSyntax switchSyntax = (SwitchStatementSyntax)original.Syntax;
            TextSpan switchSequencePointSpan = TextSpan.FromBounds(
                switchSyntax.SwitchKeyword.SpanStart,
                switchSyntax.CloseParenToken.Span.End);

            return new BoundSequencePointWithSpan(
                syntax: switchSyntax,
                statementOpt: base.InstrumentBoundPatternSwitchStatement(original, rewritten),
                span: switchSequencePointSpan,
                hasErrors: false);
        }
コード例 #23
0
            private BoundStatement MakeLoweredForm(BoundPatternSwitchStatement node)
            {
                var expression = _localRewriter.VisitExpression(node.Expression);
                var result     = ArrayBuilder <BoundStatement> .GetInstance();

                // EnC: We need to insert a hidden sequence point to handle function remapping in case
                // the containing method is edited while methods invoked in the expression are being executed.
                if (!node.WasCompilerGenerated && _localRewriter.Instrument)
                {
                    var instrumentedExpression = _localRewriter._instrumenter.InstrumentSwitchStatementExpression(node, expression, _factory);
                    if (expression.ConstantValue == null)
                    {
                        expression = instrumentedExpression;
                    }
                    else
                    {
                        // If the expression is a constant, we leave it alone (the decision tree lowering code needs
                        // to see that constant). But we add an additional leading statement with the instrumented expression.
                        result.Add(_factory.ExpressionStatement(instrumentedExpression));
                    }
                }

                // output the decision tree part
                LowerPatternSwitch(expression, node, result);

                // if the endpoint is reachable, we exit the switch
                if (!node.IsComplete)
                {
                    result.Add(_factory.Goto(node.BreakLabel));
                }
                // at this point the end of result is unreachable.

                _declaredTemps.AddRange(node.InnerLocals);

                // output the sections of code
                foreach (var section in node.SwitchSections)
                {
                    // Lifetime of these locals is expanded to the entire switch body.
                    _declaredTemps.AddRange(section.Locals);

                    // Start with the part of the decision tree that is in scope of the section variables.
                    // Its endpoint is not reachable (it jumps back into the decision tree code).
                    var sectionSyntax  = (SyntaxNode)section.Syntax;
                    var sectionBuilder = _switchSections[sectionSyntax];

                    // Add labels corresponding to the labels of the switch section.
                    foreach (var label in section.SwitchLabels)
                    {
                        sectionBuilder.Add(_factory.Label(label.Label));
                    }

                    // Add the translated body of the switch section
                    sectionBuilder.AddRange(_localRewriter.VisitList(section.Statements));

                    sectionBuilder.Add(_factory.Goto(node.BreakLabel));

                    ImmutableArray <BoundStatement> statements = sectionBuilder.ToImmutableAndFree();
                    if (section.Locals.IsEmpty)
                    {
                        result.Add(_factory.StatementList(statements));
                    }
                    else
                    {
                        result.Add(new BoundScope(section.Syntax, section.Locals, statements));
                    }
                    // at this point the end of result is unreachable.
                }

                result.Add(_factory.Label(node.BreakLabel));

                BoundStatement translatedSwitch = _factory.Block(_declaredTemps.ToImmutableArray(), node.InnerLocalFunctions, result.ToImmutableAndFree());

                // Only add instrumentation (such as a sequence point) if the node is not compiler-generated.
                if (!node.WasCompilerGenerated && _localRewriter.Instrument)
                {
                    translatedSwitch = _localRewriter._instrumenter.InstrumentPatternSwitchStatement(node, translatedSwitch);
                }

                return(translatedSwitch);
            }
コード例 #24
0
 internal static BoundStatement MakeLoweredForm(LocalRewriter localRewriter, BoundPatternSwitchStatement node)
 {
     return(new PatternSwitchLocalRewriter(localRewriter, node).MakeLoweredForm(node));
 }
コード例 #25
0
 public override BoundStatement InstrumentPatternSwitchStatement(BoundPatternSwitchStatement original, BoundStatement rewritten)
 {
     return AddDynamicAnalysis(original, base.InstrumentPatternSwitchStatement(original, rewritten));
 }
コード例 #26
0
 public override BoundNode VisitPatternSwitchStatement(BoundPatternSwitchStatement node)
 {
     return PatternSwitchLocalRewriter.MakeLoweredForm(this, node);
 }
コード例 #27
0
            private BoundStatement MakeLoweredForm(BoundPatternSwitchStatement node)
            {
                var expression = _localRewriter.VisitExpression(node.Expression);
                var result     = ArrayBuilder <BoundStatement> .GetInstance();

                // if the expression is "too complex", we copy it to a temp.
                LocalSymbol initialTemp = null;

                if (expression.ConstantValue == null)
                {
                    initialTemp = _factory.SynthesizedLocal(expression.Type, expression.Syntax);
                    result.Add(_factory.Assignment(_factory.Local(initialTemp), expression));
                    expression = _factory.Local(initialTemp);
                }

                // EnC: We need to insert a hidden sequence point to handle function remapping in case
                // the containing method is edited while methods invoked in the expression are being executed.
                if (!node.WasCompilerGenerated && _localRewriter.Instrument)
                {
                    expression = _localRewriter._instrumenter.InstrumentSwitchStatementExpression(node, expression, _factory);
                }

                // output the decision tree part
                LowerPatternSwitch(expression, node, result);

                // if the endpoint is reachable, we exit the switch
                if (!node.IsComplete)
                {
                    result.Add(_factory.Goto(node.BreakLabel));
                }
                // at this point the end of result is unreachable.

                // output the sections of code
                foreach (var section in node.SwitchSections)
                {
                    // Start with the part of the decision tree that is in scope of the section variables.
                    // Its endpoint is not reachable (it jumps back into the decision tree code).
                    var sectionSyntax  = (SyntaxNode)section.Syntax;
                    var sectionBuilder = _switchSections[sectionSyntax];

                    // Add labels corresponding to the labels of the switch section.
                    foreach (var label in section.SwitchLabels)
                    {
                        sectionBuilder.Add(_factory.Label(label.Label));
                    }

                    // Add the translated body of the switch section
                    sectionBuilder.AddRange(_localRewriter.VisitList(section.Statements));
                    sectionBuilder.Add(_factory.Goto(node.BreakLabel));
                    result.Add(_factory.Block(section.Locals, sectionBuilder.ToImmutableAndFree()));
                    // at this point the end of result is unreachable.
                }

                result.Add(_factory.Label(node.BreakLabel));
                _declaredTemps.AddOptional(initialTemp);
                _declaredTemps.AddRange(node.InnerLocals);
                BoundStatement translatedSwitch = _factory.Block(_declaredTemps.ToImmutableArray(), node.InnerLocalFunctions, result.ToImmutableAndFree());

                // Only add instrumentation (such as a sequence point) if the node is not compiler-generated.
                if (!node.WasCompilerGenerated && _localRewriter.Instrument)
                {
                    translatedSwitch = _localRewriter._instrumenter.InstrumentPatternSwitchStatement(node, translatedSwitch);
                }

                return(translatedSwitch);
            }
コード例 #28
0
 public virtual BoundStatement InstrumentPatternSwitchStatement(BoundPatternSwitchStatement original, BoundStatement rewritten)
 {
     Debug.Assert(original.Syntax.Kind() == SyntaxKind.SwitchStatement);
     return(InstrumentStatement(original, rewritten));
 }
コード例 #29
0
 /// <summary>
 /// Lower the given pattern switch statement into a decision tree and then to a sequence of statements into the given statement builder.
 /// </summary>
 private void LowerPatternSwitch(BoundExpression loweredExpression, BoundPatternSwitchStatement node, ArrayBuilder<BoundStatement> loweredDecisionTree)
 {
     var decisionTree = LowerToDecisionTree(loweredExpression, node);
     LowerDecisionTree(loweredExpression, decisionTree, loweredDecisionTree);
 }
コード例 #30
0
 public override BoundStatement InstrumentPatternSwitchStatement(BoundPatternSwitchStatement original, BoundStatement rewritten)
 {
     return(AddDynamicAnalysis(original, base.InstrumentPatternSwitchStatement(original, rewritten)));
 }
コード例 #31
0
 public override BoundStatement InstrumentBoundPatternSwitchStatement(BoundPatternSwitchStatement original, BoundStatement rewritten)
 {
     return Previous.InstrumentBoundPatternSwitchStatement(original, rewritten);
 }
コード例 #32
0
            private DecisionTree LowerToDecisionTree(
                BoundExpression loweredExpression,
                BoundPatternSwitchStatement node)
            {
                var loweredDecisionTree = DecisionTree.Create(loweredExpression, loweredExpression.Type, _enclosingSymbol);
                BoundPatternSwitchLabel defaultLabel = null;
                SyntaxNode defaultSection = null;
                foreach (var section in node.SwitchSections)
                {
                    var sectionSyntax = (SyntaxNode)section.Syntax;
                    foreach (var label in section.SwitchLabels)
                    {
                        var loweredLabel = LowerSwitchLabel(label);
                        if (loweredLabel.Syntax.Kind() == SyntaxKind.DefaultSwitchLabel)
                        {
                            if (defaultLabel != null)
                            {
                                // duplicate switch label will have been reported during initial binding.
                            }
                            else
                            {
                                defaultLabel = loweredLabel;
                                defaultSection = sectionSyntax;
                            }
                        }
                        else
                        {
                            Syntax = label.Syntax;
                            AddToDecisionTree(loweredDecisionTree, sectionSyntax, loweredLabel);
                        }
                    }
                }

                if (defaultLabel != null)
                {
                    Add(loweredDecisionTree, (e, t) => new DecisionTree.Guarded(loweredExpression, loweredExpression.Type, default(ImmutableArray<KeyValuePair<BoundExpression, BoundExpression>>), defaultSection, null, defaultLabel));
                }

                // We discard use-site diagnostics, as they have been reported during initial binding.
                _useSiteDiagnostics.Clear();
                return loweredDecisionTree;
            }
コード例 #33
0
 public override BoundNode VisitPatternSwitchStatement(BoundPatternSwitchStatement node)
 {
     return(base.VisitPatternSwitchStatement(node));
 }
コード例 #34
0
            /// <summary>
            /// Lower the given pattern switch statement into a decision tree and then to a sequence of statements into the given statement builder.
            /// </summary>
            private void LowerPatternSwitch(BoundExpression loweredExpression, BoundPatternSwitchStatement node, ArrayBuilder <BoundStatement> loweredDecisionTree)
            {
                var decisionTree = LowerToDecisionTree(loweredExpression, node);

                LowerDecisionTree(loweredExpression, decisionTree, loweredDecisionTree);
            }
コード例 #35
0
ファイル: Instrumenter.cs プロジェクト: genlu/roslyn
 public virtual BoundStatement InstrumentPatternSwitchStatement(BoundPatternSwitchStatement original, BoundStatement rewritten)
 {
     Debug.Assert(original.Syntax.Kind() == SyntaxKind.SwitchStatement);
     return InstrumentStatement(original, rewritten);
 }
コード例 #36
0
 public override BoundNode VisitPatternSwitchStatement(BoundPatternSwitchStatement node)
 {
     return(PatternSwitchLocalRewriter.MakeLoweredForm(this, node));
 }
コード例 #37
0
            private BoundStatement MakeLoweredForm(BoundPatternSwitchStatement node)
            {
                var expression = _localRewriter.VisitExpression(node.Expression);
                var result = ArrayBuilder<BoundStatement>.GetInstance();

                // if the expression is "too complex", we copy it to a temp.
                LocalSymbol initialTemp = null;
                if (expression.ConstantValue == null)
                {
                    initialTemp = _factory.SynthesizedLocal(expression.Type, expression.Syntax);
                    result.Add(_factory.Assignment(_factory.Local(initialTemp), expression));
                    expression = _factory.Local(initialTemp);
                }

                // EnC: We need to insert a hidden sequence point to handle function remapping in case 
                // the containing method is edited while methods invoked in the expression are being executed.
                if (!node.WasCompilerGenerated && _localRewriter.Instrument)
                {
                    expression = _localRewriter._instrumenter.InstrumentSwitchStatementExpression(node, expression, _factory);
                }

                // output the decision tree part
                LowerPatternSwitch(expression, node, result);

                // if the endpoint is reachable, we exit the switch
                if (!node.IsComplete)
                {
                    result.Add(_factory.Goto(node.BreakLabel));
                }
                // at this point the end of result is unreachable.

                // output the sections of code
                foreach (var section in node.SwitchSections)
                {
                    // Start with the part of the decision tree that is in scope of the section variables.
                    // Its endpoint is not reachable (it jumps back into the decision tree code).
                    var sectionSyntax = (SyntaxNode)section.Syntax;
                    var sectionBuilder = _switchSections[sectionSyntax];

                    // Add labels corresponding to the labels of the switch section.
                    foreach (var label in section.SwitchLabels)
                    {
                        sectionBuilder.Add(_factory.Label(label.Label));
                    }

                    // Add the translated body of the switch section
                    sectionBuilder.AddRange(_localRewriter.VisitList(section.Statements));
                    sectionBuilder.Add(_factory.Goto(node.BreakLabel));
                    result.Add(_factory.Block(section.Locals, sectionBuilder.ToImmutableAndFree()));
                    // at this point the end of result is unreachable.
                }

                result.Add(_factory.Label(node.BreakLabel));
                _declaredTemps.AddOptional(initialTemp);
                _declaredTemps.AddRange(node.InnerLocals);
                BoundStatement translatedSwitch = _factory.Block(_declaredTemps.ToImmutableArray(), node.InnerLocalFunctions, result.ToImmutableAndFree());

                // Only add instrumentation (such as a sequence point) if the node is not compiler-generated.
                if (!node.WasCompilerGenerated && _localRewriter.Instrument)
                {
                    translatedSwitch = _localRewriter._instrumenter.InstrumentPatternSwitchStatement(node, translatedSwitch);
                }

                return translatedSwitch;
            }
コード例 #38
0
 internal static BoundStatement MakeLoweredForm(LocalRewriter localRewriter, BoundPatternSwitchStatement node)
 {
     return new PatternSwitchLocalRewriter(localRewriter, node).MakeLoweredForm(node);
 }
コード例 #39
0
 public override BoundStatement InstrumentPatternSwitchStatement(BoundPatternSwitchStatement original, BoundStatement rewritten)
 {
     return(Previous.InstrumentPatternSwitchStatement(original, rewritten));
 }
コード例 #40
0
ファイル: DecisionTree.cs プロジェクト: tvsonar/roslyn
 public DecisionTreeComputer(
     Symbol enclosingSymbol,
     DiagnosticBag diagnostics,
     BoundPatternSwitchStatement switchStatement,
     Conversions conversions)
 {
     this._enclosingSymbol = enclosingSymbol;
     this._diagnostics = diagnostics;
     this._switchStatement = switchStatement;
     this._conversions = conversions;
 }