def traverse(tx, pre=None, post=None, state=None):
    """
    Traverse a tree.

    Allows pre-, post-, or full-order traversal. If given, `pre` and
    `post` should be functions or callable objects accepting two
    arguments: a TExpr node and a state object. If the state is used,
    `pre` and `post` should return a new state object.
    """
    if pre is not None:
        state = pre(tx, state)
    for c in tx.children():
        state = traverse(c, pre, post, state)
    if post is not None:
        state = post(tx, state)
    return state