The bug has been squashed. The problem was in the loop element; during the upgrade of them to properly deal with yield-blocks I made a mistake in how the predicate is processed. It was doing:
while( predicate && I'm not supposed to yield control ){ do stuff();}
The problem was with the foreach loop, which reduces to while( itr.MoveNext()){...}. So when the loop element checked, it ran MoveNext before doing the yield check, causing the duplication behavior. A simple reversal of the conditions and the code below gives 01234 as it should.
I also fixed a bug where a yield at the end of a block caused the block to return rather than yield. Ended up being a problem during the restart; the 'end of statements' condition wasn't distinguishing between a restart there and reaching there due to simply running out of statements.
Tomorrow should be the matter of turning take(int, collection) into take int from collection