docs: def walk(node):
    """
    Recursively yield all descendant nodes in the tree starting at ``node`` (including ``node``
    itself), using depth-first pre-order traversal (yieling parents before their children).
  
    This is similar to ``ast.walk()``, but with a different order, and it works for both ``ast`` and
    ``astroid`` trees. Also, as ``iter_children()``, it skips singleton nodes generated by ``ast``.
    """
    iter_children = iter_children_func(node)
    done = set()
    stack = [node]
    while stack:
      current = stack.pop()
      assert current not in done    # protect againt infinite loop in case of a bad tree.
      done.add(current)
  
      yield current
  
      # Insert all children in reverse order (so that first child ends up on top of the stack).
      # This is faster than building a list and reversing it.
      ins = len(stack)
      for c in iter_children(current):
        stack.insert(ins, c)