Commit 12c9d753 authored by Matthew Dempsky's avatar Matthew Dempsky

cmd/compile: refactor generic AST walking code

racewalk's "foreach" function applies a function to all of a Node's
immediate children, but with a non-idiomatic signature.

This CL reworks it to recursively iterate over the entire subtree
rooted at Node and provides a way to short-circuit iteration.

Passes toolstash -cmp for std cmd with -race.

Change-Id: I738b73953d608709802c97945b7e0f4e4940d3f4
Reviewed-on: https://go-review.googlesource.com/71911
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarRobert Griesemer <gri@golang.org>
parent 5313d3f2
......@@ -452,9 +452,15 @@ func callinstr(np **Node, init *Nodes, wr int, skip int) bool {
// that has got a pointer inside. Whether it points to
// the heap or not is impossible to know at compile time
if class == PAUTOHEAP || class == PEXTERN || b.Op == OINDEX || b.Op == ODOTPTR || b.Op == OIND {
hascalls := 0
foreach(n, hascallspred, &hascalls)
if hascalls != 0 {
hasCalls := false
inspect(n, func(n *Node) bool {
switch n.Op {
case OCALL, OCALLFUNC, OCALLMETH, OCALLINTER:
hasCalls = true
}
return !hasCalls
})
if hasCalls {
n = detachexpr(n, init)
*np = n
}
......@@ -542,34 +548,6 @@ func detachexpr(n *Node, init *Nodes) *Node {
return ind
}
func foreachnode(n *Node, f func(*Node, interface{}), c interface{}) {
if n != nil {
f(n, c)
}
}
func foreachlist(l Nodes, f func(*Node, interface{}), c interface{}) {
for _, n := range l.Slice() {
foreachnode(n, f, c)
}
}
func foreach(n *Node, f func(*Node, interface{}), c interface{}) {
foreachlist(n.Ninit, f, c)
foreachnode(n.Left, f, c)
foreachnode(n.Right, f, c)
foreachlist(n.List, f, c)
foreachlist(n.Nbody, f, c)
foreachlist(n.Rlist, f, c)
}
func hascallspred(n *Node, c interface{}) {
switch n.Op {
case OCALL, OCALLFUNC, OCALLMETH, OCALLINTER:
(*c.(*int))++
}
}
// appendinit is like addinit in subr.go
// but appends rather than prepends.
func appendinit(np **Node, init Nodes) {
......
......@@ -744,3 +744,23 @@ func (n *Nodes) AppendNodes(n2 *Nodes) {
}
n2.slice = nil
}
// inspect invokes f on each node in an AST in depth-first order.
// If f(n) returns false, inspect skips visiting n's children.
func inspect(n *Node, f func(*Node) bool) {
if n == nil || !f(n) {
return
}
inspectList(n.Ninit, f)
inspect(n.Left, f)
inspect(n.Right, f)
inspectList(n.List, f)
inspectList(n.Nbody, f)
inspectList(n.Rlist, f)
}
func inspectList(l Nodes, f func(*Node) bool) {
for _, n := range l.Slice() {
inspect(n, f)
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment