visitor.pony

interface Visitor[State: Any #read]
  """
    Used to effect transformations of an AST, using `SyntaxTree.traverse()`.

    AST trees are immutable.  We get a transformed tree by traversing the old
    tree and returning a new one (re-using unmodified nodes as necessary).

    Traversal happens in the following fashion:

    - For a node (starting with the root):
      - Call `visit_pre()` on the visitor with a parent state; this returns an
        intermediate state (if some data needs to be saved for later).
      - Build a list of new node children by calling `traverse()` on each old
        child, passing the the intermediate state.
      - Call `visit_post()` with the intermediate state,
        the list of child states (returned from each child's `visit_post()`),
        the new children, and a map from old to new children.
        `visit_post()` then returns the intermediate state and the new node.
  """

  fun ref visit_pre(
    parent_state: State,
    node: Node,
    path: Path,
    errors: Array[TraverseError] iso)
    : (State, Array[TraverseError] iso^)
    """
      Returns an intermediate state value for use when constructing the new
      node.
    """

  fun ref visit_post(
    node_state: State,
    node: Node,
    path: Path,
    errors: Array[TraverseError] iso,
    child_states: (ReadSeq[State] | None),
    new_children: (NodeSeq | None),
    update_map: (ChildUpdateMap | None))
    : (State, (Node | None), Array[TraverseError] iso^)
    """
      Returns a new node constructed from the "pre" state (the intermediate
      state) that was returned by `visit_pre()`, and the new children.

      Even if no other processing is needed, make sure to clone the node if
      `new_children` and `update_map` exist.
    """