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); }
public virtual void VisitDoWhile(BoundDoWhile node) { DefaultVisit(node); }
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(); }