File: Lowering\LocalRewriter\LocalRewriter_DoStatement.cs
Web Access
Project: src\src\Compilers\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.csproj (Microsoft.CodeAnalysis.CSharp)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System.Diagnostics;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
using System.Collections.Immutable;
 
namespace Microsoft.CodeAnalysis.CSharp
{
    internal sealed partial class LocalRewriter
    {
        public override BoundNode VisitDoStatement(BoundDoStatement node)
        {
            Debug.Assert(node != null);
 
            var rewrittenCondition = VisitExpression(node.Condition);
            var rewrittenBody = VisitStatement(node.Body);
            Debug.Assert(rewrittenBody is { });
            var startLabel = new GeneratedLabelSymbol("start");
 
            var syntax = node.Syntax;
 
            // 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 condition are being executed.
            if (!node.WasCompilerGenerated && this.Instrument)
            {
                rewrittenCondition = Instrumenter.InstrumentDoStatementCondition(node, rewrittenCondition, _factory);
            }
 
            BoundStatement ifConditionGotoStart = new BoundConditionalGoto(syntax, rewrittenCondition, true, startLabel);
 
            if (!node.WasCompilerGenerated && this.Instrument)
            {
                ifConditionGotoStart = Instrumenter.InstrumentDoStatementConditionalGotoStart(node, ifConditionGotoStart);
            }
 
            // do
            //   body
            // while (condition);
            //
            // becomes
            //
            // start: 
            // {
            //   body
            //   continue:
            //   sequence point
            //   GotoIfTrue condition start;
            // }
            // break:
 
            if (node.Locals.IsEmpty)
            {
                return BoundStatementList.Synthesized(syntax, node.HasErrors,
                    new BoundLabelStatement(syntax, startLabel),
                    rewrittenBody,
                    new BoundLabelStatement(syntax, node.ContinueLabel),
                    ifConditionGotoStart,
                    new BoundLabelStatement(syntax, node.BreakLabel));
            }
 
            return BoundStatementList.Synthesized(syntax, node.HasErrors,
                new BoundLabelStatement(syntax, startLabel),
                new BoundBlock(syntax,
                               node.Locals,
                               ImmutableArray.Create<BoundStatement>(rewrittenBody,
                                                                     new BoundLabelStatement(syntax, node.ContinueLabel),
                                                                     ifConditionGotoStart)),
                new BoundLabelStatement(syntax, node.BreakLabel));
        }
    }
}