The flow of a depth-first traversal is as follows:
For expressions that are atomic, i.e. are either atomic values, pairlists,
symbols, or primitives, the corresponding callback is called with the
expression. The callbacks are called with the expression, expr, the
environment of the function we are traversing, env, the parameters of that
function, params, information collected top-down in topdown, warning
flags through the wflags parameter, and any additional user-provided
arguments through .... If the callbacks are used in a rewrite traversal,
see depth_first_rewrite_function(), they must return an expression. This
expression will be inserted as a substitute of the expr argument in the
function being rewritten. If the callback is part of an analysis, see
depth_first_analyse_function(), then it can return any data; what it
returns will be provided to the callbacks on the enclosing expression via the
bottomup parameter.
For call expressions, the topdown callback is invoked before the call is
traversed. It is provided with the same arguments as the other callbacks and
in addition a thunk skip that it can use to prevent the depth-first
traversal to explore the call further. Whatever the topdown callback
returns will be provided to the call callback via the argument topdown it
it is called (i.e. if the topdown callback doesn't invoke skip).
After the topdown callback is executed, if it doesn't call skip, the
call callback is called on the expression. It is called with the same
arguments as the other callbacks, and must return an expression if part of a
rewrite traversal or any collected information if part of an analysis
traversal.