include 'parser/sexp'

walker = object.new

walker.prototype.inner_brat = {
  process my.ast
  my.results.map(:out).join("\n")
}

walker.prototype.process = { node, var = null |
  meth = "proc_#{node.name}"

  null? var
    {
      true? my.has_method?(meth)
        { my.call_method meth, node }
        { my.unhandled node }
    }
    {
      true? my.has_method?(meth)
        { my.call_method meth, node, var }
        { my.unhandled node, var }
    }
}

walker.unhandled = { node |
  throw "No process method for '#{node.name}'"
}

walker.prototype.walk_sexps = { nodes |
  w = my
  nodes.each { n |
    true? sexp?(n)
      { w.process n }
      { true? n.array?
        { n.each { i | w.process i } } }
  }
}

walker.walk = { name, block |
  my.prototype.add_method "proc_#{name}", ->block
}

export walker, :walker