public bool Iterate(Interpreter ii, RepeaterBlueprint bp) { if (Finished) { ii.PopRepeater(); return false; } // Queue the next iteration on the current state ii.CurrentState.AddPreBlueprint(bp); // Push separator if applicable if (!IsLast && _attribs.Separator != null && _attribs.Separator.Any()) { var sepState = Interpreter.State.CreateDerivedDistinct( ii.CurrentState.Reader.Source, _attribs.Separator, ii, ii.CurrentState.Output); // Make sure that the repeater is not available to the separator pattern sepState.AddPreBlueprint(new RepeaterStackBlueprint(ii, this, RepeaterStackAction.Pop)); sepState.AddPostBlueprint(new RepeaterStackBlueprint(ii, this, RepeaterStackAction.Push)); ii.PushState(sepState); } // Push postfix if applicable if (_attribs.After != null && _attribs.After.Any()) { ii.PushState(Interpreter.State.CreateDerivedDistinct( ii.CurrentState.Reader.Source, _attribs.After, ii, ii.CurrentState.Output)); } // Push next item var itemState = Interpreter.State.CreateDerivedDistinct(ii.CurrentState.Reader.Source, _items[_attribs.Sync != null ? _attribs.Sync.NextItem(_items.Length) : ii.RNG.Next(_items.Length)], ii, ii.CurrentState.Output); // Add a blueprint that iterates the repeater just before reading the item. This makes sure that tags like [first] can run before this happens. itemState.AddPostBlueprint(new FunctionBlueprint(ii, _ => { Next(); return false; })); ii.PushState(itemState); // Push prefix if applicable if (_attribs.Before != null && _attribs.Before.Any()) { ii.PushState(Interpreter.State.CreateDerivedDistinct( ii.CurrentState.Reader.Source, _attribs.Before, ii, ii.CurrentState.Output)); } return true; }