/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

  1. package lang
  2. import (
  3. "fmt"
  4. )
  5. type WalkFn func(n Node)
  6. func (t *Tree) Walk(fn WalkFn) {
  7. walkGroup(t.Root, fn)
  8. }
  9. func walkGroup(grp *GroupNode, fn WalkFn) {
  10. for _, v := range grp.Nodes {
  11. switch v.Type() {
  12. case NodeGroup:
  13. fn(v.(*GroupNode))
  14. walkGroup(v.(*GroupNode), fn)
  15. //this is a dirty, dirty hack
  16. fn(nil)
  17. default:
  18. fn(v)
  19. }
  20. //fmt.Printf("At %d\n", p.level)
  21. }
  22. }
  23. const print_spacer = ". "
  24. type printer struct {
  25. level int
  26. }
  27. var p printer
  28. func prettyPrint(msg string) {
  29. for i := 0; i < p.level; i++ {
  30. fmt.Print(print_spacer)
  31. }
  32. fmt.Print(msg)
  33. }
  34. func prettyPrintln(msg string) {
  35. prettyPrint(msg + "\n")
  36. }
  37. func pretty(n Node) {
  38. if n == nil {
  39. p.level--
  40. return
  41. }
  42. switch n.Type() {
  43. case NodeGroup:
  44. prettyPrintln("NODEGROUP")
  45. p.level++
  46. case NodeVarDef:
  47. prettyPrint("VARDEF(")
  48. fmt.Print(n.(*VarDefNode).Ident)
  49. fmt.Println(")")
  50. p.level++
  51. pretty(n.(*VarDefNode).Val)
  52. p.level--
  53. case NodeIdent:
  54. prettyPrint("IDENT: ")
  55. fmt.Println(n.(*IdentNode).Ident)
  56. case NodeBool:
  57. prettyPrint("BOOL: ")
  58. fmt.Println(n.(*BoolNode).Val)
  59. case NodeNumber:
  60. prettyPrint("NUMBER: ")
  61. fmt.Println(n.(*NumberNode).Text)
  62. case NodeStr:
  63. prettyPrint("STR: ")
  64. fmt.Printf("%q\n", n.(*StrNode).Val)
  65. case NodeRStr:
  66. prettyPrint("RSTR: ")
  67. fmt.Printf("'%s'\n", n.(*RStrNode).Val)
  68. case NodeArgList:
  69. walkGroup(n.(*ArgListNode).Args, pretty)
  70. /*prettyPrintln("ARGLIST")
  71. p.level++
  72. /*for _, k := range n.(*ArgListNode).Args {
  73. pretty(k)
  74. }*/
  75. //p.level--
  76. case NodeDefun:
  77. //fmt.Printf("DBG: %d\n", p.level)
  78. prettyPrint("DEFUN: ")
  79. fmt.Println(n.(*DefunNode).Name)
  80. p.level++ //XXX why
  81. //pretty(n.(*DefunNode).Args)
  82. pretty(n.(*DefunNode).Args)
  83. walkGroup(n.(*DefunNode).Args, pretty)
  84. pretty(nil)
  85. /*p.level += 2
  86. for _, l := range n.(*DefunNode).Args.Nodes {
  87. pretty(l)
  88. }*/
  89. //p.level--
  90. pretty(n.(*DefunNode).Body)
  91. walkGroup(n.(*DefunNode).Body, pretty)
  92. pretty(nil)
  93. //XXX whyp.level--
  94. p.level--
  95. case NodeReturn:
  96. prettyPrintln("RETURN")
  97. //fmt.Printf("Return starts at %d\n", p.level)
  98. p.level++
  99. gn, ok := n.(*ReturnNode).Val.(*GroupNode)
  100. if ok {
  101. pretty(gn)
  102. walkGroup(gn, pretty)
  103. pretty(nil)
  104. } else if n.(*ReturnNode).Val != nil {
  105. pretty(n.(*ReturnNode).Val)
  106. }
  107. p.level--
  108. //fmt.Printf("Return ends at %d\n", p.level)
  109. case NodeBinOp:
  110. prettyPrint("BINOP: ")
  111. fmt.Println(n.(*BinOpNode).Op)
  112. //fmt.Printf("BinOp starts at %d\n", p.level)
  113. p.level++
  114. lhg, lok := n.(*BinOpNode).LHS.(*GroupNode)
  115. if lok {
  116. pretty(lhg)
  117. walkGroup(lhg, pretty)
  118. pretty(nil)
  119. } else {
  120. pretty(n.(*BinOpNode).LHS)
  121. }
  122. rhg, rok := n.(*BinOpNode).RHS.(*GroupNode)
  123. if rok {
  124. pretty(rhg)
  125. walkGroup(rhg, pretty)
  126. pretty(nil)
  127. } else {
  128. pretty(n.(*BinOpNode).RHS)
  129. }
  130. //WTF XXX p.level--
  131. p.level--
  132. //fmt.Printf("BinOp ends at %d\n", p.level)
  133. case NodeCall:
  134. prettyPrint("CALL(")
  135. fmt.Print(n.(*CallNode).Target)
  136. fmt.Println(")")
  137. p.level++
  138. //pretty(n.(*CallNode).Args)
  139. pretty(n.(*CallNode).Args.Args)
  140. //fmt.Printf("Call starts at %d\n", p.level)
  141. walkGroup(n.(*CallNode).Args.Args, pretty)
  142. //fmt.Printf("Call ends at %d\n", p.level)
  143. pretty(nil)
  144. /*for _, l := range n.(*CallNode).Args.Nodes {
  145. pretty(l)
  146. }
  147. p.level -= 2*/
  148. p.level--
  149. case NodeBranch:
  150. prettyPrintln("BRANCH")
  151. p.level++
  152. gr, ok := n.(*BranchNode).Cond.(*GroupNode)
  153. if ok {
  154. pretty(gr)
  155. walkGroup(gr, pretty)
  156. pretty(nil)
  157. } else {
  158. if n.(*BranchNode).Cond == nil {
  159. prettyPrintln("NIL")
  160. } else {
  161. pretty(n.(*BranchNode).Cond)
  162. }
  163. }
  164. if n.(*BranchNode).True == nil {
  165. prettyPrintln("NIL")
  166. } else {
  167. pretty(n.(*BranchNode).True)
  168. walkGroup(n.(*BranchNode).True, pretty)
  169. pretty(nil)
  170. }
  171. if n.(*BranchNode).False == nil {
  172. prettyPrintln("NIL")
  173. //FIXME (TODO) we could handle this properly
  174. } else {
  175. pretty(n.(*BranchNode).False)
  176. walkGroup(n.(*BranchNode).False, pretty)
  177. pretty(nil)
  178. }
  179. p.level--
  180. case NodeLoop:
  181. prettyPrintln("LOOP")
  182. p.level++
  183. gr, ok := n.(*LoopNode).Pre.(*GroupNode)
  184. if ok {
  185. pretty(gr)
  186. walkGroup(gr, pretty)
  187. pretty(nil)
  188. } else {
  189. if n.(*LoopNode).Pre == nil {
  190. prettyPrintln("NIL")
  191. } else {
  192. pretty(n.(*LoopNode).Pre)
  193. }
  194. }
  195. gr2, ok2 := n.(*LoopNode).Cond.(*GroupNode)
  196. if ok2 {
  197. pretty(gr2)
  198. walkGroup(gr2, pretty)
  199. pretty(nil)
  200. } else {
  201. if n.(*LoopNode).Cond == nil {
  202. prettyPrintln("NIL")
  203. } else {
  204. pretty(n.(*LoopNode).Cond)
  205. }
  206. }
  207. gr3, ok3 := n.(*LoopNode).Post.(*GroupNode)
  208. if ok3 {
  209. pretty(gr3)
  210. walkGroup(gr3, pretty)
  211. pretty(nil)
  212. } else {
  213. if n.(*LoopNode).Post == nil {
  214. prettyPrintln("NIL")
  215. } else {
  216. pretty(n.(*LoopNode).Post)
  217. }
  218. }
  219. pretty(n.(*LoopNode).Body)
  220. walkGroup(n.(*LoopNode).Body, pretty)
  221. pretty(nil)
  222. p.level--
  223. }
  224. }
  225. func (t *Tree) PrettyPrint() {
  226. p = printer{level: 0}
  227. t.Walk(pretty)
  228. }