code: def before_after_apply(self, before_fn, after_fn, leaf_fn=None):
          
          stack = [self]
          while stack:
              node = stack.pop()
              if node.is_leaf:
                  if leaf_fn:
                      leaf_fn(node)
                  while node.is_last_child_of_parent:
                      node = node._parent
                      if node:
                          after_fn(node)
                      else:
                          break
              else:
                  before_fn(node)
                  stack.extend([i for i in reversed(node._children)])
docs: Applies the functions to each node in a subtree using an traversal in which
          encountered twice: once right before its descendants, and once right
          after its last descendant