public override void VisitDoWhile(BoundDoWhile node)
            {
                // Rules for do/while:
                // * _branch stays default branch (we always take the do);
                // * Target for break/continue;
                // * Test is only executed when the default branch reaches the end
                //   or a continue was executed.

                var block = new Block(_branch, FindLabel(node), true, true, null);

                PushBlock(block);

                _branch = block.Branch.Fork();

                Visit(node.Body);

                bool wasKilled = _branch.IsKilled;

                if (!_branch.IsKilled || block.ContinueTaken)
                {
                    // We need to restore the branch because if the branch is
                    // killed, but we have a continue, the test is still done on
                    // the branch.
                    _branch.IsKilled = false;

                    Visit(node.Test);
                }

                if (!wasKilled)
                    block.JoinBranch(_branch);

                PopBlock(block);
            }
Beispiel #2
0
 public virtual void VisitDoWhile(BoundDoWhile node)
 {
     DefaultVisit(node);
 }
Beispiel #3
0
        private void EmitDoWhile(BoundDoWhile node)
        {
            // Create the break and continue targets and push them onto the stack.

            var breakTarget = IL.DefineLabel(GetLabel(node));
            _scope.BreakTargets.Push(breakTarget);
            var continueTarget = IL.DefineLabel(GetLabel(node));
            _scope.ContinueTargets.Push(continueTarget);

            // Mark the start of the loop.

            var startTarget = IL.DefineLabel();
            IL.MarkLabel(startTarget);

            // Emit the body.

            EmitStatement(node.Body);

            // Begin the test.

            IL.MarkLabel(continueTarget);

            // If the test succeeds, we go again.

            EmitTest(node.Test, startTarget);

            // Mark the end of the loop.

            IL.MarkLabel(breakTarget);

            // Pop the break and continue targets to make the previous ones
            // available.

            _scope.BreakTargets.Pop();
            _scope.ContinueTargets.Pop();
        }