docs: def ast_value(val, scope, return_name=False):
      '''Recursively parse out an AST value.  This makes no attempt to load
      modules or reconstruct functions on purpose.  We do not want to
      inadvertently call destructive code.
      '''
      # :TODO: refactor the hell out of this
      try:
          if isinstance(val, (ast.Assign, ast.Delete)):
              if hasattr(val, 'value'):
                  value = ast_value(val.value, scope)
              else:
                  value = None
              for t in val.targets:
                  name = ast_value(t, scope, return_name=True)
                  if isinstance(t.ctx, ast.Del):
                      if name in scope:
                          scope.pop(name)
                  elif isinstance(t.ctx, ast.Store):
                      scope[name] = value
              return
          elif isinstance(val, ast.Expr) and isinstance(val.value, ast.Name):
              return ast_value(val.value)
  
          if isinstance(val, ast.Name):
              if isinstance(val.ctx, ast.Load):
                  if val.id == 'None':
                      return None
                  elif val.id == 'True':
                      return True
                  elif val.id == 'False':
                      return False
  
                  if val.id in scope:
                      return scope[val.id]
  
                  if return_name:
                      return val.id
              elif isinstance(val.ctx, ast.Store):
                  if return_name:
                      return val.id
              return None
  
          if isinstance(val, ast.Subscript):
              toslice = ast_value(val.value, scope)
              theslice = ast_value(val.slice, scope)
              return toslice[theslice]
          elif isinstance(val, ast.Index):
              return ast_value(val.value, scope)
          elif isinstance(val, ast.Slice):
              lower = ast_value(val.lower)
              upper = ast_value(val.upper)
              step = ast_value(val.step)
              return slice(lower, upper, step)
  
          if isinstance(val, list):
              return [ast_value(x, scope) for x in val]
          elif isinstance(val, tuple):
              return tuple(ast_value(x, scope) for x in val)
  
          if isinstance(val, ast.Attribute):
              name = ast_value(val.value, scope, return_name=True)
              if isinstance(val.ctx, ast.Load):
                  return '.'.join((name, val.attr))
              if return_name:
                  return name
          elif isinstance(val, ast.keyword):
              return {val.arg: ast_value(val.value, scope)}
          elif isinstance(val, ast.List):
              return [ast_value(x, scope) for x in val.elts]
          elif isinstance(val, ast.Tuple):
              return tuple(ast_value(x, scope) for x in val.elts)
          elif isinstance(val, ast.Dict):
              return dict(zip([ast_value(x, scope) for x in val.keys],
                              [ast_value(x, scope) for x in val.values]))
          elif isinstance(val, ast.Num):
              return val.n
          elif isinstance(val, ast.Str):
              return val.s
          elif hasattr(ast, 'Bytes') and isinstance(val, ast.Bytes):
              return bytes(val.s)
      except Exception:
          # Don't care, just return None
          pass
  
      return None