code: def visit(root, visitor, key_map=None):
      visitor_keys = key_map or QUERY_DOCUMENT_KEYS
  
      stack = None
      in_array = isinstance(root, list)
      keys = [root]
      index = -1
      edits = []
      parent = None
      path = []
      ancestors = []
      new_root = root
      leave = visitor.leave
      enter = visitor.enter
      path_pop = path.pop
      ancestors_pop = ancestors.pop
      path_append = path.append
      ancestors_append = ancestors.append
  
      while True:
          index += 1
          is_leaving = index == len(keys)
          is_edited = is_leaving and edits
          if is_leaving:
              key = path_pop() if ancestors else None
              node = parent
              parent = ancestors_pop() if ancestors else None
  
              if is_edited:
                  if in_array:
                      node = list(node)
  
                  else:
                      node = copy(node)
                  edit_offset = 0
                  for edit_key, edit_value in edits:
                      if in_array:
                          edit_key -= edit_offset
  
                      if in_array and edit_value is REMOVE:
                          node.pop(edit_key)
                          edit_offset += 1
  
                      else:
                          if isinstance(node, list):
                              node[edit_key] = edit_value
  
                          else:
                              setattr(node, edit_key, edit_value)
  
              index = stack.index
              keys = stack.keys
              edits = stack.edits
              in_array = stack.in_array
              stack = stack.prev
  
          else:
              if parent:
                  key = index if in_array else keys[index]
                  if isinstance(parent, list):
                      node = parent[key]
  
                  else:
                      node = getattr(parent, key, None)
  
              else:
                  key = None
                  node = new_root
  
              if node is REMOVE or node is None:
                  continue
  
              if parent:
                  path_append(key)
  
          result = None
  
          if not isinstance(node, list):
              assert isinstance(
                  node, ast.Node
              ), "Invalid AST Node: " + repr(node)
  
              if is_leaving:
                  result = leave(node, key, parent, path, ancestors)
  
              else:
                  result = enter(node, key, parent, path, ancestors)
  
              if result is BREAK:
                  break
  
              if result is False:
                  if not is_leaving:
                      path_pop()
                      continue
  
              elif result is not None:
                  edits.append((key, result))
                  if not is_leaving:
                      if isinstance(result, ast.Node):
                          node = result
  
                      else:
                          path_pop()
                          continue
  
          if result is None and is_edited:
              edits.append((key, node))
  
          if not is_leaving:
              stack = Stack(in_array, index, keys, edits, stack)
              in_array = isinstance(node, list)
              keys = (
                  node
                  if in_array
                  else visitor_keys.get(type(node), None) or []
              )
              index = -1
              edits = []
  
              if parent:
                  ancestors_append(parent)
  
              parent = node
  
          if not stack:
              break
  
      if edits:
          new_root = edits[-1][1]
  
      return new_root
  
imports: from copy import copy
  from .None import ast
  from .visitor_meta import QUERY_DOCUMENT_KEYS, VisitorMeta
label_desc: Use image node_id 1 for calling a global function with example usage: visit(root, visitor, key_map) and returns: new_root