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