You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
164 lines
2.5 KiB
164 lines
2.5 KiB
// Copyright 2017 The Bazel Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package syntax
|
|
|
|
// Walk traverses a syntax tree in depth-first order.
|
|
// It starts by calling f(n); n must not be nil.
|
|
// If f returns true, Walk calls itself
|
|
// recursively for each non-nil child of n.
|
|
// Walk then calls f(nil).
|
|
func Walk(n Node, f func(Node) bool) {
|
|
if n == nil {
|
|
panic("nil")
|
|
}
|
|
if !f(n) {
|
|
return
|
|
}
|
|
|
|
// TODO(adonovan): opt: order cases using profile data.
|
|
switch n := n.(type) {
|
|
case *File:
|
|
walkStmts(n.Stmts, f)
|
|
|
|
case *ExprStmt:
|
|
Walk(n.X, f)
|
|
|
|
case *BranchStmt:
|
|
// no-op
|
|
|
|
case *IfStmt:
|
|
Walk(n.Cond, f)
|
|
walkStmts(n.True, f)
|
|
walkStmts(n.False, f)
|
|
|
|
case *AssignStmt:
|
|
Walk(n.LHS, f)
|
|
Walk(n.RHS, f)
|
|
|
|
case *DefStmt:
|
|
Walk(n.Name, f)
|
|
for _, param := range n.Params {
|
|
Walk(param, f)
|
|
}
|
|
walkStmts(n.Body, f)
|
|
|
|
case *ForStmt:
|
|
Walk(n.Vars, f)
|
|
Walk(n.X, f)
|
|
walkStmts(n.Body, f)
|
|
|
|
case *ReturnStmt:
|
|
if n.Result != nil {
|
|
Walk(n.Result, f)
|
|
}
|
|
|
|
case *LoadStmt:
|
|
Walk(n.Module, f)
|
|
for _, from := range n.From {
|
|
Walk(from, f)
|
|
}
|
|
for _, to := range n.To {
|
|
Walk(to, f)
|
|
}
|
|
|
|
case *Ident, *Literal:
|
|
// no-op
|
|
|
|
case *ListExpr:
|
|
for _, x := range n.List {
|
|
Walk(x, f)
|
|
}
|
|
|
|
case *ParenExpr:
|
|
Walk(n.X, f)
|
|
|
|
case *CondExpr:
|
|
Walk(n.Cond, f)
|
|
Walk(n.True, f)
|
|
Walk(n.False, f)
|
|
|
|
case *IndexExpr:
|
|
Walk(n.X, f)
|
|
Walk(n.Y, f)
|
|
|
|
case *DictEntry:
|
|
Walk(n.Key, f)
|
|
Walk(n.Value, f)
|
|
|
|
case *SliceExpr:
|
|
Walk(n.X, f)
|
|
if n.Lo != nil {
|
|
Walk(n.Lo, f)
|
|
}
|
|
if n.Hi != nil {
|
|
Walk(n.Hi, f)
|
|
}
|
|
if n.Step != nil {
|
|
Walk(n.Step, f)
|
|
}
|
|
|
|
case *Comprehension:
|
|
Walk(n.Body, f)
|
|
for _, clause := range n.Clauses {
|
|
Walk(clause, f)
|
|
}
|
|
|
|
case *IfClause:
|
|
Walk(n.Cond, f)
|
|
|
|
case *ForClause:
|
|
Walk(n.Vars, f)
|
|
Walk(n.X, f)
|
|
|
|
case *TupleExpr:
|
|
for _, x := range n.List {
|
|
Walk(x, f)
|
|
}
|
|
|
|
case *DictExpr:
|
|
for _, entry := range n.List {
|
|
entry := entry.(*DictEntry)
|
|
Walk(entry.Key, f)
|
|
Walk(entry.Value, f)
|
|
}
|
|
|
|
case *UnaryExpr:
|
|
if n.X != nil {
|
|
Walk(n.X, f)
|
|
}
|
|
|
|
case *BinaryExpr:
|
|
Walk(n.X, f)
|
|
Walk(n.Y, f)
|
|
|
|
case *DotExpr:
|
|
Walk(n.X, f)
|
|
Walk(n.Name, f)
|
|
|
|
case *CallExpr:
|
|
Walk(n.Fn, f)
|
|
for _, arg := range n.Args {
|
|
Walk(arg, f)
|
|
}
|
|
|
|
case *LambdaExpr:
|
|
for _, param := range n.Params {
|
|
Walk(param, f)
|
|
}
|
|
Walk(n.Body, f)
|
|
|
|
default:
|
|
panic(n)
|
|
}
|
|
|
|
f(nil)
|
|
}
|
|
|
|
func walkStmts(stmts []Stmt, f func(Node) bool) {
|
|
for _, stmt := range stmts {
|
|
Walk(stmt, f)
|
|
}
|
|
}
|