1
16
17 package build
18
19
20
21 type StopTraversalError struct{}
22
23 func (m *StopTraversalError) Error() string {
24 return "Stop traversal"
25 }
26
27
28
29
30
31
32
33 func Walk(v Expr, f func(x Expr, stk []Expr)) {
34 var stack []Expr
35 walk1(&v, &stack, func(x *Expr, stk []Expr) (Expr, error) {
36 f(*x, stk)
37 return nil, nil
38 })
39 }
40
41
42 func WalkPointers(v Expr, f func(x *Expr, stk []Expr)) {
43 var stack []Expr
44 walk1(&v, &stack, func(x *Expr, stk []Expr) (Expr, error) {
45 f(x, stk)
46 return nil, nil
47 })
48 }
49
50
51 func WalkInterruptable(v Expr, f func(x Expr, stk []Expr) error) {
52 var stack []Expr
53 walk1(&v, &stack, func(x *Expr, stk []Expr) (Expr, error) {
54 err := f(*x, stk)
55 return nil, err
56 })
57 }
58
59
60
61
62
63
64
65
66 func Edit(v Expr, f func(x Expr, stk []Expr) Expr) Expr {
67 var stack []Expr
68 return walk1(&v, &stack, func(x *Expr, stk []Expr) (Expr, error) {
69 return f(*x, stk), nil
70 })
71 }
72
73
74
75 func EditChildren(v Expr, f func(x Expr, stk []Expr) Expr) {
76 stack := []Expr{v}
77 WalkOnce(v, func(x *Expr) {
78 walk1(x, &stack, func(x *Expr, stk []Expr) (Expr, error) {
79 return f(*x, stk), nil
80 })
81 })
82 }
83
84
85 func walk1(v *Expr, stack *[]Expr, f func(x *Expr, stk []Expr) (Expr, error)) Expr {
86 if v == nil || *v == nil {
87 return nil
88 }
89
90 res, err := f(v, *stack)
91 if res != nil {
92 *v = res
93 }
94 if err != nil {
95 if _, ok := err.(*StopTraversalError); ok {
96
97 return nil
98 }
99 }
100 *stack = append(*stack, *v)
101
102 WalkOnce(*v, func(x *Expr) {
103 walk1(x, stack, f)
104 })
105
106 *stack = (*stack)[:len(*stack)-1]
107 return *v
108 }
109
110
111 func WalkOnce(v Expr, f func(x *Expr)) {
112 switch v := v.(type) {
113 case *File:
114 for i := range v.Stmt {
115 f(&v.Stmt[i])
116 }
117 case *DotExpr:
118 f(&v.X)
119 case *IndexExpr:
120 f(&v.X)
121 f(&v.Y)
122 case *KeyValueExpr:
123 f(&v.Key)
124 f(&v.Value)
125 case *SliceExpr:
126 f(&v.X)
127 if v.From != nil {
128 f(&v.From)
129 }
130 if v.To != nil {
131 f(&v.To)
132 }
133 if v.Step != nil {
134 f(&v.Step)
135 }
136 case *ParenExpr:
137 f(&v.X)
138 case *UnaryExpr:
139 f(&v.X)
140 case *BinaryExpr:
141 f(&v.X)
142 f(&v.Y)
143 case *AssignExpr:
144 f(&v.LHS)
145 f(&v.RHS)
146 case *LambdaExpr:
147 for i := range v.Params {
148 f(&v.Params[i])
149 }
150 for i := range v.Body {
151 f(&v.Body[i])
152 }
153 case *CallExpr:
154 f(&v.X)
155 for i := range v.List {
156 f(&v.List[i])
157 }
158 case *ListExpr:
159 for i := range v.List {
160 f(&v.List[i])
161 }
162 case *SetExpr:
163 for i := range v.List {
164 f(&v.List[i])
165 }
166 case *TupleExpr:
167 for i := range v.List {
168 f(&v.List[i])
169 }
170 case *DictExpr:
171 for i := range v.List {
172 e := Expr(v.List[i])
173 f(&e)
174 }
175 case *Comprehension:
176 f(&v.Body)
177 for _, c := range v.Clauses {
178 f(&c)
179 }
180 case *IfClause:
181 f(&v.Cond)
182 case *ForClause:
183 f(&v.Vars)
184 f(&v.X)
185 case *ConditionalExpr:
186 f(&v.Then)
187 f(&v.Test)
188 f(&v.Else)
189 case *LoadStmt:
190 module := (Expr)(v.Module)
191 f(&module)
192 v.Module = module.(*StringExpr)
193 for i := range v.From {
194 from := (Expr)(v.From[i])
195 f(&from)
196 v.From[i] = from.(*Ident)
197 to := (Expr)(v.To[i])
198 f(&to)
199 v.To[i] = to.(*Ident)
200 }
201 case *DefStmt:
202 for i := range v.Params {
203 f(&v.Params[i])
204 }
205 for i := range v.Body {
206 f(&v.Body[i])
207 }
208 case *IfStmt:
209 f(&v.Cond)
210 for i := range v.True {
211 f(&v.True[i])
212 }
213 for i := range v.False {
214 f(&v.False[i])
215 }
216 case *ForStmt:
217 f(&v.Vars)
218 f(&v.X)
219 for i := range v.Body {
220 f(&v.Body[i])
221 }
222 case *ReturnStmt:
223 if v.Result != nil {
224 f(&v.Result)
225 }
226 }
227 }
228
229
230 func walkStatements(v Expr, stack *[]Expr, f func(x Expr, stk []Expr) error) {
231 if v == nil {
232 return
233 }
234
235 err := f(v, *stack)
236 if err != nil {
237 if _, ok := err.(*StopTraversalError); ok {
238 return
239 }
240 }
241
242 *stack = append(*stack, v)
243
244 traverse := func(x Expr) {
245 walkStatements(x, stack, f)
246 }
247
248 switch expr := v.(type) {
249 case *File:
250 for _, s := range expr.Stmt {
251 traverse(s)
252 }
253 case *DefStmt:
254 for _, s := range expr.Body {
255 traverse(s)
256 }
257 case *IfStmt:
258 for _, s := range expr.True {
259 traverse(s)
260 }
261 for _, s := range expr.False {
262 traverse(s)
263 }
264 case *ForStmt:
265 for _, s := range expr.Body {
266 traverse(s)
267 }
268 }
269
270 *stack = (*stack)[:len(*stack)-1]
271 }
272
273
274 func WalkStatements(v Expr, f func(x Expr, stk []Expr) error) {
275 var stack []Expr
276 walkStatements(v, &stack, f)
277 }
278
View as plain text