예제 #1
0
            public override void VisitWhile(BoundWhile node)
            {
                // Rules for while:
                // * When IsFalse(Test), we don't have any work;
                // * When IsTrue(Test), _branch stays the default;
                // * Otherwise, _branch becomes a fork;
                // * Target for break/continue.

                var result = ToBoolean(node.Test);

                // If Test evaluates to a constant expression false, the while
                // loop is never taken.

                if (result == false)
                    return;

                // The Test is executed on the default branch.

                Visit(node.Test);

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

                PushBlock(block);

                _branch = block.Branch.Fork();

                Visit(node.Body);

                block.JoinBranch(_branch);

                // Create an empty fork to tell the Join algorithm that the
                // Body was an optional branch.

                if (result != true)
                    block.JoinBranch(block.Branch.Fork());

                PopBlock(block);
            }
예제 #2
0
 public virtual void VisitWhile(BoundWhile node)
 {
     DefaultVisit(node);
 }
예제 #3
0
        private void EmitWhile(BoundWhile 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);

            // At the beginning of every iteration, perform the test.

            IL.MarkLabel(continueTarget);

            EmitTest(node.Test, breakTarget.Label, true);

            // Emit the body.

            EmitStatement(node.Body);

            // Go back to the start to perform the test again.

            IL.Emit(OpCodes.Br, continueTarget.Label);

            // After the loop.

            IL.MarkLabel(breakTarget);

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

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