/lang/walk.go
https://code.google.com/p/tangent-bot/ · Go · 242 lines · 199 code · 14 blank · 29 comment · 40 complexity · 45529cb13cca2b869e69f4b7c61bdc7b MD5 · raw file
- package lang
- import (
- "fmt"
- )
- type WalkFn func(n Node)
- func (t *Tree) Walk(fn WalkFn) {
- walkGroup(t.Root, fn)
- }
- func walkGroup(grp *GroupNode, fn WalkFn) {
- for _, v := range grp.Nodes {
- switch v.Type() {
- case NodeGroup:
- fn(v.(*GroupNode))
- walkGroup(v.(*GroupNode), fn)
- //this is a dirty, dirty hack
- fn(nil)
- default:
- fn(v)
- }
- //fmt.Printf("At %d\n", p.level)
- }
- }
- const print_spacer = ". "
- type printer struct {
- level int
- }
- var p printer
- func prettyPrint(msg string) {
- for i := 0; i < p.level; i++ {
- fmt.Print(print_spacer)
- }
- fmt.Print(msg)
- }
- func prettyPrintln(msg string) {
- prettyPrint(msg + "\n")
- }
- func pretty(n Node) {
- if n == nil {
- p.level--
- return
- }
- switch n.Type() {
- case NodeGroup:
- prettyPrintln("NODEGROUP")
- p.level++
- case NodeVarDef:
- prettyPrint("VARDEF(")
- fmt.Print(n.(*VarDefNode).Ident)
- fmt.Println(")")
- p.level++
- pretty(n.(*VarDefNode).Val)
- p.level--
- case NodeIdent:
- prettyPrint("IDENT: ")
- fmt.Println(n.(*IdentNode).Ident)
- case NodeBool:
- prettyPrint("BOOL: ")
- fmt.Println(n.(*BoolNode).Val)
- case NodeNumber:
- prettyPrint("NUMBER: ")
- fmt.Println(n.(*NumberNode).Text)
- case NodeStr:
- prettyPrint("STR: ")
- fmt.Printf("%q\n", n.(*StrNode).Val)
- case NodeRStr:
- prettyPrint("RSTR: ")
- fmt.Printf("'%s'\n", n.(*RStrNode).Val)
- case NodeArgList:
- walkGroup(n.(*ArgListNode).Args, pretty)
- /*prettyPrintln("ARGLIST")
- p.level++
- /*for _, k := range n.(*ArgListNode).Args {
- pretty(k)
- }*/
- //p.level--
- case NodeDefun:
- //fmt.Printf("DBG: %d\n", p.level)
- prettyPrint("DEFUN: ")
- fmt.Println(n.(*DefunNode).Name)
- p.level++ //XXX why
- //pretty(n.(*DefunNode).Args)
- pretty(n.(*DefunNode).Args)
- walkGroup(n.(*DefunNode).Args, pretty)
- pretty(nil)
- /*p.level += 2
- for _, l := range n.(*DefunNode).Args.Nodes {
- pretty(l)
- }*/
- //p.level--
- pretty(n.(*DefunNode).Body)
- walkGroup(n.(*DefunNode).Body, pretty)
- pretty(nil)
- //XXX whyp.level--
- p.level--
- case NodeReturn:
- prettyPrintln("RETURN")
- //fmt.Printf("Return starts at %d\n", p.level)
- p.level++
- gn, ok := n.(*ReturnNode).Val.(*GroupNode)
- if ok {
- pretty(gn)
- walkGroup(gn, pretty)
- pretty(nil)
- } else if n.(*ReturnNode).Val != nil {
- pretty(n.(*ReturnNode).Val)
- }
- p.level--
- //fmt.Printf("Return ends at %d\n", p.level)
- case NodeBinOp:
- prettyPrint("BINOP: ")
- fmt.Println(n.(*BinOpNode).Op)
- //fmt.Printf("BinOp starts at %d\n", p.level)
- p.level++
- lhg, lok := n.(*BinOpNode).LHS.(*GroupNode)
- if lok {
- pretty(lhg)
- walkGroup(lhg, pretty)
- pretty(nil)
- } else {
- pretty(n.(*BinOpNode).LHS)
- }
- rhg, rok := n.(*BinOpNode).RHS.(*GroupNode)
- if rok {
- pretty(rhg)
- walkGroup(rhg, pretty)
- pretty(nil)
- } else {
- pretty(n.(*BinOpNode).RHS)
- }
- //WTF XXX p.level--
- p.level--
- //fmt.Printf("BinOp ends at %d\n", p.level)
- case NodeCall:
- prettyPrint("CALL(")
- fmt.Print(n.(*CallNode).Target)
- fmt.Println(")")
- p.level++
- //pretty(n.(*CallNode).Args)
- pretty(n.(*CallNode).Args.Args)
- //fmt.Printf("Call starts at %d\n", p.level)
- walkGroup(n.(*CallNode).Args.Args, pretty)
- //fmt.Printf("Call ends at %d\n", p.level)
- pretty(nil)
- /*for _, l := range n.(*CallNode).Args.Nodes {
- pretty(l)
- }
- p.level -= 2*/
- p.level--
- case NodeBranch:
- prettyPrintln("BRANCH")
- p.level++
- gr, ok := n.(*BranchNode).Cond.(*GroupNode)
- if ok {
- pretty(gr)
- walkGroup(gr, pretty)
- pretty(nil)
- } else {
- if n.(*BranchNode).Cond == nil {
- prettyPrintln("NIL")
- } else {
- pretty(n.(*BranchNode).Cond)
- }
- }
- if n.(*BranchNode).True == nil {
- prettyPrintln("NIL")
- } else {
- pretty(n.(*BranchNode).True)
- walkGroup(n.(*BranchNode).True, pretty)
- pretty(nil)
- }
- if n.(*BranchNode).False == nil {
- prettyPrintln("NIL")
- //FIXME (TODO) we could handle this properly
- } else {
- pretty(n.(*BranchNode).False)
- walkGroup(n.(*BranchNode).False, pretty)
- pretty(nil)
- }
- p.level--
- case NodeLoop:
- prettyPrintln("LOOP")
- p.level++
- gr, ok := n.(*LoopNode).Pre.(*GroupNode)
- if ok {
- pretty(gr)
- walkGroup(gr, pretty)
- pretty(nil)
- } else {
- if n.(*LoopNode).Pre == nil {
- prettyPrintln("NIL")
- } else {
- pretty(n.(*LoopNode).Pre)
- }
- }
- gr2, ok2 := n.(*LoopNode).Cond.(*GroupNode)
- if ok2 {
- pretty(gr2)
- walkGroup(gr2, pretty)
- pretty(nil)
- } else {
- if n.(*LoopNode).Cond == nil {
- prettyPrintln("NIL")
- } else {
- pretty(n.(*LoopNode).Cond)
- }
- }
- gr3, ok3 := n.(*LoopNode).Post.(*GroupNode)
- if ok3 {
- pretty(gr3)
- walkGroup(gr3, pretty)
- pretty(nil)
- } else {
- if n.(*LoopNode).Post == nil {
- prettyPrintln("NIL")
- } else {
- pretty(n.(*LoopNode).Post)
- }
- }
- pretty(n.(*LoopNode).Body)
- walkGroup(n.(*LoopNode).Body, pretty)
- pretty(nil)
- p.level--
- }
- }
- func (t *Tree) PrettyPrint() {
- p = printer{level: 0}
- t.Walk(pretty)
- }