Documentation article

Traversal explained

Traversal centralizes tree-walking so generators and analyzers can stay focused on their own logic.

Concepts7 min

Traversal is the reusable mechanism for walking Shape IR consistently, regardless of whether you are generating output, collecting diagnostics, or adding analysis later.

Once Shape IR is the contract, traversal becomes the leverage point that prevents duplicated tree-walking logic across the codebase.

Audience
Learners
Difficulty
Intermediate
Last updated
July 27, 2026
Shape IR
Review the underlying shared representation first.
Custom generators
See where traversal feeds output-specific logic in a future generator.

Why traversal matters

Without a shared traversal layer, every parser, generator, and analyzer ends up re-implementing slightly different recursion rules.

That duplication usually hides subtle inconsistencies. A common traversal model reduces those inconsistencies and makes extension work more predictable.

What a good traversal layer provides

These rules make traversal useful across both current generators and future higher-level tooling.

  • Walk nodes in a deterministic order.
  • Pass context that downstream consumers can extend.
  • Keep visiting logic separate from rendering or analysis side effects.

One walker, many uses

The exact APIs can evolve, but the important part is that one traversal contract can serve many downstream behaviors.

A simplified traversal sketch

ts
function visitShape(shape: Shape, visitor: Visitor) {
  visitor.enter?.(shape);

  if (shape.kind === "array") {
    visitShape(shape.element, visitor);
  }

  if (shape.kind === "object") {
    for (const field of Object.values(shape.fields)) {
      visitShape(field, visitor);
    }
  }

  visitor.exit?.(shape);
}