Skip to content

Generator: Create Iterator Generator #41

@JerrettDavis

Description

@JerrettDavis

Summary

Add a source generator that produces a complete implementation of the Iterator pattern for consumer-defined collections and traversals, with deterministic ordering and allocation-aware iteration.

The generator lives in PatternKit.Generators and emits self-contained, readable C# with no runtime PatternKit dependency.

Primary goals:

  • Generate iterator types that encapsulate traversal logic.
  • Support both IEnumerator<T> and allocation-light TryMoveNext(out T) shapes.
  • Provide common traversal patterns for composites/trees via user-supplied child selectors.
  • Be deterministic and reflection-free.

Motivation / Problem

C# makes iteration easy, but the pattern matters when:

  • traversal is stateful and must be encapsulated
  • multiple traversal strategies exist (DFS/BFS)
  • consumers should not depend on internal representation
  • allocation costs from iterator state machines should be minimized in hot paths

We want a generator that produces explicit, testable iterator implementations.


Supported Targets (must-have)

The generator must support:

  • partial class / partial struct
  • partial record class / partial record struct

Two primary iterator models must be supported:

  1. State-machine iterator (user defines step function; generator emits iterator type).
  2. Traversal iterator (tree/graph traversal driven by child selector).

Proposed User Experience

A) State-machine iterator (allocation-light)

[Iterator]
public partial struct TokenIterator
{
    [IteratorStep]
    private bool TryStep(ref IteratorState state, out Token item);
}

Generated (representative shape):

public partial struct TokenIterator
{
    public bool TryMoveNext(out Token item);
    public Token Current { get; }

    public Enumerator GetEnumerator();

    public struct Enumerator : IEnumerator<Token>
    {
        public Token Current { get; }
        public bool MoveNext();
        public void Reset();
        public void Dispose();
    }
}

B) Tree traversal iterator (DFS/BFS)

[TraversalIterator]
public static partial class CategoryTraversal
{
    [DepthFirst]
    public static partial IEnumerable<Category> DepthFirst(Category root);

    [BreadthFirst]
    public static partial IEnumerable<Category> BreadthFirst(Category root);

    [TraversalChildren]
    private static IEnumerable<Category> Children(Category node) => node.Children;
}

Generator emits concrete iterator implementations (not compiler-generated iterator state machines) where feasible.


Attributes / Surface Area

Namespace: PatternKit.Generators.Iterator

Core

  • [Iterator] on iterator host

    • bool GenerateEnumerator (default: true)
    • bool GenerateTryMoveNext (default: true)
  • [IteratorStep] on step method

    • expected shape: bool TryStep(ref TState state, out T item)

Traversal model (optional v1, recommended v1 if you want immediate utility):

  • [TraversalIterator] on static partial class
  • [DepthFirst] / [BreadthFirst] on partial methods
  • [TraversalChildren] on a method providing children enumeration

Semantics (must-have)

State-machine iterator

  • Underlying state stored in a generated/private State field.
  • TryMoveNext(out T) calls user step method.
  • IEnumerator<T> wrapper delegates to TryMoveNext.

Determinism:

  • Step evaluation is strictly linear and controlled by TryStep.

Allocation behavior:

  • Prefer struct enumerators.
  • Avoid iterator blocks (yield return) in generated code.

Traversal iterator

  • DFS: pre-order by default; document ordering.

  • BFS: FIFO queue ordering.

  • Cycle handling:

    • v1 default: no cycle detection (document).
    • optional DetectCycles=true config, using HashSet<T> with comparer.

Diagnostics (must-have)

Stable IDs, actionable:

  • PKIT001 Type marked [Iterator] must be partial.
  • PKIT002 No [IteratorStep] method found.
  • PKIT003 Multiple [IteratorStep] methods found.
  • PKIT004 Step method signature invalid.
  • PKIT005 Traversal iterator host must be static partial.
  • PKIT006 Traversal method signature invalid.
  • PKIT007 No [TraversalChildren] provider found.

Generated Code Layout

  • TypeName.Iterator.g.cs
  • TypeName.Traversal.g.cs (if traversal model enabled)

Determinism:

  • stable ordering for emission by fully-qualified symbol name.

Testing Expectations

State-machine model:

  • Happy path: produces expected sequence.
  • Edge: empty sequence.
  • Edge: step throws; exception bubbles.
  • Diagnostics: missing step, duplicate step, invalid signature.

Traversal model:

  • DFS ordering for known tree.
  • BFS ordering for known tree.
  • Optional: cycle detection behavior if enabled.

Acceptance Criteria

  • [Iterator] works for class/struct/record class/record struct.
  • Generates allocation-light TryMoveNext(out T).
  • Generates IEnumerator<T> wrapper (struct enumerator preferred).
  • Deterministic iteration semantics.
  • Diagnostics cover missing/duplicate/invalid step definitions.
  • Tests cover state-machine iteration (and traversal if enabled).

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions