Ejemplo n.º 1
0
            public override void VisitFor(BoundFor node)
            {
                // Rules for for:
                // * _branch stays default when IsTrue(Test); otherwise _branch
                //   becomes a fork;
                // * Target for break/continue;
                // * Increment is only executed when the default branch reaches
                //   the end or a continue was executed.

                // Initialization and test are executed on the current branch.
                Visit(node.Initialization);
                Visit(node.Test);

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

                _branch = block.Branch.Fork();

                PushBlock(block);

                Visit(node.Body);

                bool wasKilled = _branch.IsKilled;

                // Only visit the increment when then default branch flows there
                // or a continue was executed.
                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.Increment);
                }

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

                // Create an extra empty branch when the test wasn't unconditional.
                if (node.Test != null && ToBoolean(node.Test) != true)
                    block.JoinBranch(block.Branch.Fork());

                PopBlock(block);
            }
Ejemplo n.º 2
0
 public virtual void VisitFor(BoundFor node)
 {
     DefaultVisit(node);
 }
Ejemplo n.º 3
0
        private void EmitFor(BoundFor node)
        {
            // Push the break and continue targets 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 start of our block, we perform any initialization.

            if (node.Initialization != null)
                EmitStatement(node.Initialization);

            // If we have a test, we perform the test at the start of every
            // iteration.

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

            if (node.Test != null)
                EmitTest(node.Test, breakTarget.Label, true);

            // Add the body.

            EmitStatement(node.Body);

            // Increment is done at the end.

            IL.MarkLabel(continueTarget);

            if (node.Increment != null)
                EmitStatement(node.Increment);

            // Jump back to the start of the loop.

            IL.Emit(OpCodes.Br, startTarget);

            // Mark the end of the loop.

            IL.MarkLabel(breakTarget);

            // Remove the break and continue targets to make the previous ones
            // visible.

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