]> Cypherpunks repositories - gostls13.git/commitdiff
go/ast: add Preorder go1.23 iterator
authorAlan Donovan <adonovan@google.com>
Mon, 11 Mar 2024 21:16:44 +0000 (17:16 -0400)
committerGopher Robot <gobot@golang.org>
Wed, 15 May 2024 21:44:50 +0000 (21:44 +0000)
This CL adds a new function Preorder that makes it
easier to iterate over the nodes of a syntax tree.
In particular, break, continue, and return retain
their usual continuations.

Fixes #66339

Change-Id: I438b3c23780c91ed589871ad3b8822d54e8fabc7
Reviewed-on: https://go-review.googlesource.com/c/go/+/570680
Reviewed-by: Robert Findley <rfindley@google.com>
Auto-Submit: Alan Donovan <adonovan@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>

api/next/66339.txt [new file with mode: 0644]
doc/next/6-stdlib/99-minor/go/ast/66339.md [new file with mode: 0644]
src/go/ast/example_test.go
src/go/ast/walk.go

diff --git a/api/next/66339.txt b/api/next/66339.txt
new file mode 100644 (file)
index 0000000..a6b45ad
--- /dev/null
@@ -0,0 +1 @@
+pkg go/ast, func Preorder(Node) iter.Seq[Node] #66339
diff --git a/doc/next/6-stdlib/99-minor/go/ast/66339.md b/doc/next/6-stdlib/99-minor/go/ast/66339.md
new file mode 100644 (file)
index 0000000..0eec51e
--- /dev/null
@@ -0,0 +1,2 @@
+The new [Preorder] function returns a convenient iterator over all the
+nodes of a syntax tree.
index 4ce42fb1536be09f31cd0b4c1b7512abc041f17f..31b32efece993a8f4f19c7137d8d17d3aac8e25a 100644 (file)
@@ -140,6 +140,41 @@ func main() {
        //     61  }
 }
 
+func ExamplePreorder() {
+       src := `
+package p
+
+func f(x, y int) {
+       print(x + y)
+}
+`
+
+       fset := token.NewFileSet()
+       f, err := parser.ParseFile(fset, "", src, 0)
+       if err != nil {
+               panic(err)
+       }
+
+       // Print identifiers in order
+       for n := range ast.Preorder(f) {
+               id, ok := n.(*ast.Ident)
+               if !ok {
+                       continue
+               }
+               fmt.Println(id.Name)
+       }
+
+       // Output:
+       // p
+       // f
+       // x
+       // y
+       // int
+       // print
+       // x
+       // y
+}
+
 // This example illustrates how to remove a variable declaration
 // in a Go program while maintaining correct comment association
 // using an ast.CommentMap.
index 59e6fc174d6eb5f4248a6023acb5b2eeb293b275..0cd604ef1f725ab05882bc35a209042398de8cd8 100644 (file)
@@ -4,7 +4,10 @@
 
 package ast
 
-import "fmt"
+import (
+       "fmt"
+       "iter"
+)
 
 // A Visitor's Visit method is invoked for each node encountered by [Walk].
 // If the result visitor w is not nil, [Walk] visits each of the children
@@ -368,3 +371,20 @@ func (f inspector) Visit(node Node) Visitor {
 func Inspect(node Node, f func(Node) bool) {
        Walk(inspector(f), node)
 }
+
+// Preorder returns an iterator over all the nodes of the syntax tree
+// beneath (and including) the specified root, in depth-first
+// preorder.
+//
+// For greater control over the traversal of each subtree, use [Inspect].
+func Preorder(root Node) iter.Seq[Node] {
+       return func(yield func(Node) bool) {
+               ok := true
+               Inspect(root, func(n Node) bool {
+                       if n != nil && !yield(n) {
+                               ok = false
+                       }
+                       return ok
+               })
+       }
+}