// 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
}
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) {
}
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)
+ }
+}