go.starlark.net@v0.0.0-20231101134539-556fd59b42f6/syntax/walk.go (about)

     1  // Copyright 2017 The Bazel Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package syntax
     6  
     7  // Walk traverses a syntax tree in depth-first order.
     8  // It starts by calling f(n); n must not be nil.
     9  // If f returns true, Walk calls itself
    10  // recursively for each non-nil child of n.
    11  // Walk then calls f(nil).
    12  func Walk(n Node, f func(Node) bool) {
    13  	if n == nil {
    14  		panic("nil")
    15  	}
    16  	if !f(n) {
    17  		return
    18  	}
    19  
    20  	// TODO(adonovan): opt: order cases using profile data.
    21  	switch n := n.(type) {
    22  	case *File:
    23  		walkStmts(n.Stmts, f)
    24  
    25  	case *ExprStmt:
    26  		Walk(n.X, f)
    27  
    28  	case *BranchStmt:
    29  		// no-op
    30  
    31  	case *IfStmt:
    32  		Walk(n.Cond, f)
    33  		walkStmts(n.True, f)
    34  		walkStmts(n.False, f)
    35  
    36  	case *AssignStmt:
    37  		Walk(n.LHS, f)
    38  		Walk(n.RHS, f)
    39  
    40  	case *DefStmt:
    41  		Walk(n.Name, f)
    42  		for _, param := range n.Params {
    43  			Walk(param, f)
    44  		}
    45  		walkStmts(n.Body, f)
    46  
    47  	case *ForStmt:
    48  		Walk(n.Vars, f)
    49  		Walk(n.X, f)
    50  		walkStmts(n.Body, f)
    51  
    52  	case *ReturnStmt:
    53  		if n.Result != nil {
    54  			Walk(n.Result, f)
    55  		}
    56  
    57  	case *LoadStmt:
    58  		Walk(n.Module, f)
    59  		for _, from := range n.From {
    60  			Walk(from, f)
    61  		}
    62  		for _, to := range n.To {
    63  			Walk(to, f)
    64  		}
    65  
    66  	case *Ident, *Literal:
    67  		// no-op
    68  
    69  	case *ListExpr:
    70  		for _, x := range n.List {
    71  			Walk(x, f)
    72  		}
    73  
    74  	case *ParenExpr:
    75  		Walk(n.X, f)
    76  
    77  	case *CondExpr:
    78  		Walk(n.Cond, f)
    79  		Walk(n.True, f)
    80  		Walk(n.False, f)
    81  
    82  	case *IndexExpr:
    83  		Walk(n.X, f)
    84  		Walk(n.Y, f)
    85  
    86  	case *DictEntry:
    87  		Walk(n.Key, f)
    88  		Walk(n.Value, f)
    89  
    90  	case *SliceExpr:
    91  		Walk(n.X, f)
    92  		if n.Lo != nil {
    93  			Walk(n.Lo, f)
    94  		}
    95  		if n.Hi != nil {
    96  			Walk(n.Hi, f)
    97  		}
    98  		if n.Step != nil {
    99  			Walk(n.Step, f)
   100  		}
   101  
   102  	case *Comprehension:
   103  		Walk(n.Body, f)
   104  		for _, clause := range n.Clauses {
   105  			Walk(clause, f)
   106  		}
   107  
   108  	case *IfClause:
   109  		Walk(n.Cond, f)
   110  
   111  	case *ForClause:
   112  		Walk(n.Vars, f)
   113  		Walk(n.X, f)
   114  
   115  	case *TupleExpr:
   116  		for _, x := range n.List {
   117  			Walk(x, f)
   118  		}
   119  
   120  	case *DictExpr:
   121  		for _, entry := range n.List {
   122  			Walk(entry, f)
   123  		}
   124  
   125  	case *UnaryExpr:
   126  		if n.X != nil {
   127  			Walk(n.X, f)
   128  		}
   129  
   130  	case *BinaryExpr:
   131  		Walk(n.X, f)
   132  		Walk(n.Y, f)
   133  
   134  	case *DotExpr:
   135  		Walk(n.X, f)
   136  		Walk(n.Name, f)
   137  
   138  	case *CallExpr:
   139  		Walk(n.Fn, f)
   140  		for _, arg := range n.Args {
   141  			Walk(arg, f)
   142  		}
   143  
   144  	case *LambdaExpr:
   145  		for _, param := range n.Params {
   146  			Walk(param, f)
   147  		}
   148  		Walk(n.Body, f)
   149  
   150  	default:
   151  		panic(n)
   152  	}
   153  
   154  	f(nil)
   155  }
   156  
   157  func walkStmts(stmts []Stmt, f func(Node) bool) {
   158  	for _, stmt := range stmts {
   159  		Walk(stmt, f)
   160  	}
   161  }