text: #!/usr/bin/python
  """
  visitor.py
  """
  
  from asdl import asdl_ as asdl
  
  
  class AsdlVisitor:
    """Base class for visitors.
  
    TODO:
    - It might be useful to separate this into VisitChildren() / generic_visit()
      like Python's ast.NodeVisitor  does.
    - Also remove self.f and self.Emit.  Those can go in self.output?
    - Move to common location, since gen_python uses it as well.
    """
    def __init__(self, f):
      self.f = f
      self.current_depth = 0  # the current number of indent levels
  
    def Indent(self):
      self.current_depth += 1
  
    def Dedent(self):
      self.current_depth -= 1
  
    def Emit(self, s, depth=-1, reflow=True):
      if depth == -1:
        depth = self.current_depth
      for line in FormatLines(s, depth, reflow=reflow):
        self.f.write(line)
  
    def VisitModule(self, mod):
      for dfn in mod.dfns:
        self.VisitType(dfn)
      self.EmitFooter()
  
    def VisitType(self, typ, depth=0):
      if isinstance(typ.value, asdl.Sum):
        self.VisitSum(typ.value, typ.name, depth)
      elif isinstance(typ.value, asdl.Product):
        self.VisitProduct(typ.value, typ.name, depth)
      else:
        raise AssertionError(typ)
  
    def VisitSum(self, sum, name, depth):
      if asdl.is_simple(sum):
        self.VisitSimpleSum(sum, name, depth)
      else:
        self.VisitCompoundSum(sum, name, depth)
  
    # Optionally overridden.
    def VisitProduct(self, value, name, depth):
      pass
    def VisitSimpleSum(self, value, name, depth):
      pass
    def VisitCompoundSum(self, value, name, depth):
      pass
    def EmitFooter(self):
      pass
  
  
  TABSIZE = 2
  MAX_COL = 80
  
  # Copied from asdl_c.py
  
  def _ReflowLines(s, depth):
    """Reflow the line s indented depth tabs.
  
    Return a sequence of lines where no line extends beyond MAX_COL when properly
    indented.  The first line is properly indented based exclusively on depth *
    TABSIZE.  All following lines -- these are the reflowed lines generated by
    this function -- start at the same column as the first character beyond the
    opening { in the first line.
    """
    size = MAX_COL - depth * TABSIZE
    if len(s) < size:
      return [s]
  
    lines = []
    cur = s
    padding = ""
    while len(cur) > size:
      i = cur.rfind(' ', 0, size)
      # XXX this should be fixed for real
      if i == -1 and 'GeneratorExp' in cur:
        i = size + 3
      assert i != -1, "Impossible line %d to reflow: %r" % (size, s)
      lines.append(padding + cur[:i])
      if len(lines) == 1:
        # find new size based on brace
        j = cur.find('{', 0, i)
        if j >= 0:
          j += 2  # account for the brace and the space after it
          size -= j
          padding = " " * j
        else:
          j = cur.find('(', 0, i)
          if j >= 0:
            j += 1  # account for the paren (no space after it)
            size -= j
            padding = " " * j
      cur = cur[i + 1:]
    else:
      lines.append(padding + cur)
    return lines
  
  
  def FormatLines(s, depth, reflow=True):
    """Make the generated code readable.
  
    Args:
      depth: controls indentation
      reflow: line wrapping.
    """
    if reflow:
      lines = _ReflowLines(s, depth)
    else:
      lines = [s]
  
    result = []
    for line in lines:
      line = (" " * TABSIZE * depth) + line + "\n"
      result.append(line)
    return result
  