# `Ichor.Toolkit.TermWalk`
[🔗](https://github.com/joetjen/ichor_runtime/blob/v0.2.0/lib/ichor/toolkit/term_walk.ex#L1)

Generic recursion over any `Ichor.Backtrack.Term` implementation --
extracted from a pattern independently duplicated inside
`Ichor.Toolkit.TypeScheme` itself: `resolve_deep/3` and the private
`substitute/3` shared the identical "apply a transform, then (if the
result is compound) deconstruct, recurse into every argument with the
same transform, and reconstruct" recursive skeleton, differing only in
what the transform itself does at each step (chase a variable's
binding one level, or substitute a specific variable for a fresh one);
`free_vars/3` is the same recursive shape again, but folding into an
accumulator instead of rebuilding a term.

Neither function here knows anything about bindings, substitutions, or
types -- only what `variable?/1`, `compound?/1`, `deconstruct/1`, and
(for `rewrite/3`) `reconstruct/2` say about a given `term_module`, the
same boundary `Ichor.Backtrack.Bindings.unify/4` already draws.

# `fold`

```elixir
@spec fold(module(), term(), acc, (term(), acc -&gt; acc)) :: acc when acc: term()
```

Folds over `term` and every subterm reachable through `compound?/1`/
`deconstruct/1`, visiting a node before its children (order doesn't
matter for a commutative `combine`, e.g. collecting a set of variable
ids -- `Ichor.Toolkit.TypeScheme.free_vars/3`'s own use).

# `rewrite`

```elixir
@spec rewrite(module(), term(), (term() -&gt; term())) :: term()
```

Applies `transform` to `term`, then -- if the *result* is compound --
deconstructs it and recurses into every argument with the same
`transform`, reconstructing afterward. `transform` is applied exactly
once per node, on the way down, never re-applied to a freshly
reconstructed compound -- correct for a transform that only ever acts
on non-compound nodes (resolving or substituting a variable; a
compound term is rebuilt from its already-transformed arguments, never
itself examined), which is the only shape `resolve_deep/3`/`substitute/3`
ever needed. Not a general bottom-up rewrite pass (e.g. constant
folding, which needs to re-examine a parent after its children
change) -- `transform` never sees a node built by this same call.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
