PageRenderTime 114ms CodeModel.GetById 97ms app.highlight 15ms RepoModel.GetById 0ms app.codeStats 1ms

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