///|
/// Walk `root` (see `walk`) with an accumulator: `enter` and `leave` take the
/// current value and return the next one, in walk's callback order. The
/// result is the value after the last callback. The accumulator belongs to
/// the caller; fold does not copy it.
///
/// ```mbt check
/// test {
/// let src = "module Main exposing (..)\n\nadd x y =\n x + y\n"
/// let result = @parser.parse_module(
/// @scanner.SourceText::new(src),
/// @scanner.DefaultScanner::new(),
/// )
/// let root = @syntax.NodeRef::of_result(result).unwrap()
/// // Count the expressions and find the deepest nesting.
/// let (count, _, deepest) = @syntax.fold(
/// root,
/// (0, 0, 0),
/// (acc, n) => {
/// let (count, depth, deepest) = acc
/// let count = count + (if n.category() == "expression" { 1 } else { 0 })
/// let depth = depth + 1
/// let deepest = if depth > deepest { depth } else { deepest }
/// ((count, depth, deepest), Continue)
/// },
/// leave=(acc, _) => (acc.0, acc.1 - 1, acc.2),
/// )
/// inspect(count, content="3")
/// inspect(deepest, content="5")
/// }
/// ```
pub fn[A] fold(
root : NodeRef,
init : A,
enter : (A, NodeRef) -> (A, Control),
leave? : (A, NodeRef) -> A = (a, _) => a,
) -> A {
let mut acc = init
walk(
root,
n => {
let (next, control) = enter(acc, n)
acc = next
control
},
leave=n => acc = leave(acc, n),
)
acc
}