code: def reverse_ad(node, wrt, preserve_result, check_dims):
    
    if not isinstance(node, gast.FunctionDef):
      raise TypeError
    # Activity analysis
    cfg.forward(node, cfg.Active(wrt))
  
    ad = ReverseAD(wrt, preserve_result, check_dims)
    pri, adj = ad.visit(node)
    mod = gast.Module(body=[pri, adj])
    mod = annotate.find_stacks(mod)
    return mod, ad.required, ad.stack
docs: Perform reverse-mode AD on an AST.
  
    This function analyses the AST to determine which variables are active and
    proceeds by taking the naive derivative. Before returning the primal and
    adjoint it annotates push and pop statements as such.
  
    Args:
      node: A `FunctionDef` AST node.
      wrt: A tuple of argument indices with respect to which we take the
          derivative.
      preserve_result: A boolean indicating whether the generated
          derivative function should also return the original return value.
      check_dims: A boolean indicating whether the seed derivatives should have
          their dimensions checked to match their primal counterpart.
  
  
    Returns:
      mod: A `Module` node containing the naive primal and adjoint of the
          function which can be fed to the `split` and `joint` functions.
      required: A list of tuples of functions and argument indices. These
          functions were called by the function but did not have an adjoint.