1
0
mirror of https://github.com/golang/go synced 2024-11-26 10:18:12 -07:00

[dev.typeparams] cmd/compile/internal/syntax: add Walk node vistor from types2

This moves the Walk visitor from the types2 to the syntax
package. There are no changes but for package name adjustments.
Preparation for a more full-fledged node visitor.

Change-Id: I95217e27ff943ac58a7638fb8d1cd347d0d554b0
Reviewed-on: https://go-review.googlesource.com/c/go/+/282556
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
Robert Griesemer 2021-01-07 17:38:12 -08:00
parent 7903214fcc
commit d017a1b649
2 changed files with 61 additions and 67 deletions

View File

@ -1,18 +1,12 @@
// UNREVIEWED
// Copyright 2012 The Go Authors. All rights reserved. // Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// This file implements syntax tree walking. // This file implements syntax tree walking.
// TODO(gri) A more general API should probably be in
// the syntax package.
package types2 package syntax
import ( import "fmt"
"cmd/compile/internal/syntax"
"fmt"
)
// Walk traverses a syntax in pre-order: It starts by calling f(root); // Walk traverses a syntax in pre-order: It starts by calling f(root);
// root must not be nil. If f returns false (== "continue"), Walk calls // root must not be nil. If f returns false (== "continue"), Walk calls
@ -23,17 +17,17 @@ import (
// field lists such as type T in "a, b, c T"). Such shared nodes are // field lists such as type T in "a, b, c T"). Such shared nodes are
// walked multiple times. // walked multiple times.
// TODO(gri) Revisit this design. It may make sense to walk those nodes // TODO(gri) Revisit this design. It may make sense to walk those nodes
// only once. A place where this matters is TestResolveIdents. // only once. A place where this matters is types2.TestResolveIdents.
func Walk(root syntax.Node, f func(syntax.Node) bool) { func Walk(root Node, f func(Node) bool) {
w := walker{f} w := walker{f}
w.node(root) w.node(root)
} }
type walker struct { type walker struct {
f func(syntax.Node) bool f func(Node) bool
} }
func (w *walker) node(n syntax.Node) { func (w *walker) node(n Node) {
if n == nil { if n == nil {
panic("invalid syntax tree: nil node") panic("invalid syntax tree: nil node")
} }
@ -44,18 +38,18 @@ func (w *walker) node(n syntax.Node) {
switch n := n.(type) { switch n := n.(type) {
// packages // packages
case *syntax.File: case *File:
w.node(n.PkgName) w.node(n.PkgName)
w.declList(n.DeclList) w.declList(n.DeclList)
// declarations // declarations
case *syntax.ImportDecl: case *ImportDecl:
if n.LocalPkgName != nil { if n.LocalPkgName != nil {
w.node(n.LocalPkgName) w.node(n.LocalPkgName)
} }
w.node(n.Path) w.node(n.Path)
case *syntax.ConstDecl: case *ConstDecl:
w.nameList(n.NameList) w.nameList(n.NameList)
if n.Type != nil { if n.Type != nil {
w.node(n.Type) w.node(n.Type)
@ -64,12 +58,12 @@ func (w *walker) node(n syntax.Node) {
w.node(n.Values) w.node(n.Values)
} }
case *syntax.TypeDecl: case *TypeDecl:
w.node(n.Name) w.node(n.Name)
w.fieldList(n.TParamList) w.fieldList(n.TParamList)
w.node(n.Type) w.node(n.Type)
case *syntax.VarDecl: case *VarDecl:
w.nameList(n.NameList) w.nameList(n.NameList)
if n.Type != nil { if n.Type != nil {
w.node(n.Type) w.node(n.Type)
@ -78,7 +72,7 @@ func (w *walker) node(n syntax.Node) {
w.node(n.Values) w.node(n.Values)
} }
case *syntax.FuncDecl: case *FuncDecl:
if n.Recv != nil { if n.Recv != nil {
w.node(n.Recv) w.node(n.Recv)
} }
@ -90,36 +84,36 @@ func (w *walker) node(n syntax.Node) {
} }
// expressions // expressions
case *syntax.BadExpr: // nothing to do case *BadExpr: // nothing to do
case *syntax.Name: case *Name: // nothing to do
case *syntax.BasicLit: // nothing to do case *BasicLit: // nothing to do
case *syntax.CompositeLit: case *CompositeLit:
if n.Type != nil { if n.Type != nil {
w.node(n.Type) w.node(n.Type)
} }
w.exprList(n.ElemList) w.exprList(n.ElemList)
case *syntax.KeyValueExpr: case *KeyValueExpr:
w.node(n.Key) w.node(n.Key)
w.node(n.Value) w.node(n.Value)
case *syntax.FuncLit: case *FuncLit:
w.node(n.Type) w.node(n.Type)
w.node(n.Body) w.node(n.Body)
case *syntax.ParenExpr: case *ParenExpr:
w.node(n.X) w.node(n.X)
case *syntax.SelectorExpr: case *SelectorExpr:
w.node(n.X) w.node(n.X)
w.node(n.Sel) w.node(n.Sel)
case *syntax.IndexExpr: case *IndexExpr:
w.node(n.X) w.node(n.X)
w.node(n.Index) w.node(n.Index)
case *syntax.SliceExpr: case *SliceExpr:
w.node(n.X) w.node(n.X)
for _, x := range n.Index { for _, x := range n.Index {
if x != nil { if x != nil {
@ -127,43 +121,43 @@ func (w *walker) node(n syntax.Node) {
} }
} }
case *syntax.AssertExpr: case *AssertExpr:
w.node(n.X) w.node(n.X)
w.node(n.Type) w.node(n.Type)
case *syntax.TypeSwitchGuard: case *TypeSwitchGuard:
if n.Lhs != nil { if n.Lhs != nil {
w.node(n.Lhs) w.node(n.Lhs)
} }
w.node(n.X) w.node(n.X)
case *syntax.Operation: case *Operation:
w.node(n.X) w.node(n.X)
if n.Y != nil { if n.Y != nil {
w.node(n.Y) w.node(n.Y)
} }
case *syntax.CallExpr: case *CallExpr:
w.node(n.Fun) w.node(n.Fun)
w.exprList(n.ArgList) w.exprList(n.ArgList)
case *syntax.ListExpr: case *ListExpr:
w.exprList(n.ElemList) w.exprList(n.ElemList)
// types // types
case *syntax.ArrayType: case *ArrayType:
if n.Len != nil { if n.Len != nil {
w.node(n.Len) w.node(n.Len)
} }
w.node(n.Elem) w.node(n.Elem)
case *syntax.SliceType: case *SliceType:
w.node(n.Elem) w.node(n.Elem)
case *syntax.DotsType: case *DotsType:
w.node(n.Elem) w.node(n.Elem)
case *syntax.StructType: case *StructType:
w.fieldList(n.FieldList) w.fieldList(n.FieldList)
for _, t := range n.TagList { for _, t := range n.TagList {
if t != nil { if t != nil {
@ -171,65 +165,65 @@ func (w *walker) node(n syntax.Node) {
} }
} }
case *syntax.Field: case *Field:
if n.Name != nil { if n.Name != nil {
w.node(n.Name) w.node(n.Name)
} }
w.node(n.Type) w.node(n.Type)
case *syntax.InterfaceType: case *InterfaceType:
w.fieldList(n.MethodList) w.fieldList(n.MethodList)
case *syntax.FuncType: case *FuncType:
w.fieldList(n.ParamList) w.fieldList(n.ParamList)
w.fieldList(n.ResultList) w.fieldList(n.ResultList)
case *syntax.MapType: case *MapType:
w.node(n.Key) w.node(n.Key)
w.node(n.Value) w.node(n.Value)
case *syntax.ChanType: case *ChanType:
w.node(n.Elem) w.node(n.Elem)
// statements // statements
case *syntax.EmptyStmt: // nothing to do case *EmptyStmt: // nothing to do
case *syntax.LabeledStmt: case *LabeledStmt:
w.node(n.Label) w.node(n.Label)
w.node(n.Stmt) w.node(n.Stmt)
case *syntax.BlockStmt: case *BlockStmt:
w.stmtList(n.List) w.stmtList(n.List)
case *syntax.ExprStmt: case *ExprStmt:
w.node(n.X) w.node(n.X)
case *syntax.SendStmt: case *SendStmt:
w.node(n.Chan) w.node(n.Chan)
w.node(n.Value) w.node(n.Value)
case *syntax.DeclStmt: case *DeclStmt:
w.declList(n.DeclList) w.declList(n.DeclList)
case *syntax.AssignStmt: case *AssignStmt:
w.node(n.Lhs) w.node(n.Lhs)
w.node(n.Rhs) w.node(n.Rhs)
case *syntax.BranchStmt: case *BranchStmt:
if n.Label != nil { if n.Label != nil {
w.node(n.Label) w.node(n.Label)
} }
// Target points to nodes elsewhere in the syntax tree // Target points to nodes elsewhere in the syntax tree
case *syntax.CallStmt: case *CallStmt:
w.node(n.Call) w.node(n.Call)
case *syntax.ReturnStmt: case *ReturnStmt:
if n.Results != nil { if n.Results != nil {
w.node(n.Results) w.node(n.Results)
} }
case *syntax.IfStmt: case *IfStmt:
if n.Init != nil { if n.Init != nil {
w.node(n.Init) w.node(n.Init)
} }
@ -239,7 +233,7 @@ func (w *walker) node(n syntax.Node) {
w.node(n.Else) w.node(n.Else)
} }
case *syntax.ForStmt: case *ForStmt:
if n.Init != nil { if n.Init != nil {
w.node(n.Init) w.node(n.Init)
} }
@ -251,7 +245,7 @@ func (w *walker) node(n syntax.Node) {
} }
w.node(n.Body) w.node(n.Body)
case *syntax.SwitchStmt: case *SwitchStmt:
if n.Init != nil { if n.Init != nil {
w.node(n.Init) w.node(n.Init)
} }
@ -262,25 +256,25 @@ func (w *walker) node(n syntax.Node) {
w.node(s) w.node(s)
} }
case *syntax.SelectStmt: case *SelectStmt:
for _, s := range n.Body { for _, s := range n.Body {
w.node(s) w.node(s)
} }
// helper nodes // helper nodes
case *syntax.RangeClause: case *RangeClause:
if n.Lhs != nil { if n.Lhs != nil {
w.node(n.Lhs) w.node(n.Lhs)
} }
w.node(n.X) w.node(n.X)
case *syntax.CaseClause: case *CaseClause:
if n.Cases != nil { if n.Cases != nil {
w.node(n.Cases) w.node(n.Cases)
} }
w.stmtList(n.Body) w.stmtList(n.Body)
case *syntax.CommClause: case *CommClause:
if n.Comm != nil { if n.Comm != nil {
w.node(n.Comm) w.node(n.Comm)
} }
@ -291,31 +285,31 @@ func (w *walker) node(n syntax.Node) {
} }
} }
func (w *walker) declList(list []syntax.Decl) { func (w *walker) declList(list []Decl) {
for _, n := range list { for _, n := range list {
w.node(n) w.node(n)
} }
} }
func (w *walker) exprList(list []syntax.Expr) { func (w *walker) exprList(list []Expr) {
for _, n := range list { for _, n := range list {
w.node(n) w.node(n)
} }
} }
func (w *walker) stmtList(list []syntax.Stmt) { func (w *walker) stmtList(list []Stmt) {
for _, n := range list { for _, n := range list {
w.node(n) w.node(n)
} }
} }
func (w *walker) nameList(list []*syntax.Name) { func (w *walker) nameList(list []*Name) {
for _, n := range list { for _, n := range list {
w.node(n) w.node(n)
} }
} }
func (w *walker) fieldList(list []*syntax.Field) { func (w *walker) fieldList(list []*Field) {
for _, n := range list { for _, n := range list {
w.node(n) w.node(n)
} }

View File

@ -144,7 +144,7 @@ func TestResolveIdents(t *testing.T) {
// check that qualified identifiers are resolved // check that qualified identifiers are resolved
for _, f := range files { for _, f := range files {
Walk(f, func(n syntax.Node) bool { syntax.Walk(f, func(n syntax.Node) bool {
if s, ok := n.(*syntax.SelectorExpr); ok { if s, ok := n.(*syntax.SelectorExpr); ok {
if x, ok := s.X.(*syntax.Name); ok { if x, ok := s.X.(*syntax.Name); ok {
obj := uses[x] obj := uses[x]
@ -172,13 +172,13 @@ func TestResolveIdents(t *testing.T) {
// Check that each identifier in the source is found in uses or defs or both. // Check that each identifier in the source is found in uses or defs or both.
// We need the foundUses/Defs maps (rather then just deleting the found objects // We need the foundUses/Defs maps (rather then just deleting the found objects
// from the uses and defs maps) because Walk traverses shared nodes multiple // from the uses and defs maps) because syntax.Walk traverses shared nodes multiple
// times (e.g. types in field lists such as "a, b, c int"). // times (e.g. types in field lists such as "a, b, c int").
foundUses := make(map[*syntax.Name]bool) foundUses := make(map[*syntax.Name]bool)
foundDefs := make(map[*syntax.Name]bool) foundDefs := make(map[*syntax.Name]bool)
var both []string var both []string
for _, f := range files { for _, f := range files {
Walk(f, func(n syntax.Node) bool { syntax.Walk(f, func(n syntax.Node) bool {
if x, ok := n.(*syntax.Name); ok { if x, ok := n.(*syntax.Name); ok {
var objects int var objects int
if _, found := uses[x]; found { if _, found := uses[x]; found {