blueprint_starlark_syntax/syntax/
uniplate.rs

1/*
2 * Copyright 2019 The Starlark in Rust Authors.
3 * Copyright (c) Facebook, Inc. and its affiliates.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 *     https://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18// These are more readable for formulaic code like Uniplate
19#![allow(clippy::many_single_char_names)]
20// Sometimes we need |x| f(x) to do type/lifetime conversion, sometimes we don't.
21// Most consistent to use the closure everywhere.
22#![allow(clippy::redundant_closure)]
23
24use crate::syntax::ast::AssignP;
25use crate::syntax::ast::AssignTargetP;
26use crate::syntax::ast::AstAssignIdentP;
27use crate::syntax::ast::AstExprP;
28use crate::syntax::ast::AstIdentP;
29use crate::syntax::ast::AstPayload;
30use crate::syntax::ast::AstStmtP;
31use crate::syntax::ast::AstTypeExprP;
32use crate::syntax::ast::ClauseP;
33use crate::syntax::ast::DefP;
34use crate::syntax::ast::ExprP;
35use crate::syntax::ast::ForClauseP;
36use crate::syntax::ast::ForP;
37use crate::syntax::ast::LambdaP;
38use crate::syntax::ast::MatchP;
39use crate::syntax::ast::ParameterP;
40use crate::syntax::ast::StmtP;
41use crate::syntax::ast::StructP;
42use crate::syntax::ast::TypeExprP;
43
44pub enum Visit<'a, P: AstPayload> {
45    Stmt(&'a AstStmtP<P>),
46    Expr(&'a AstExprP<P>),
47}
48
49pub enum VisitMut<'a, P: AstPayload> {
50    Stmt(&'a mut AstStmtP<P>),
51    Expr(&'a mut AstExprP<P>),
52}
53
54impl<'a, P: AstPayload> Visit<'a, P> {
55    pub fn visit_children(&self, mut f: impl FnMut(Visit<'a, P>)) {
56        match self {
57            Self::Stmt(x) => x.visit_children(f),
58            Self::Expr(x) => x.visit_expr(|x| f(Visit::Expr(x))),
59        }
60    }
61
62    pub fn visit_children_err<E>(
63        &self,
64        mut f: impl FnMut(Visit<'a, P>) -> Result<(), E>,
65    ) -> Result<(), E> {
66        match self {
67            Self::Stmt(x) => x.visit_children_err(f),
68            Self::Expr(x) => x.visit_expr_err(|x| f(Visit::Expr(x))),
69        }
70    }
71}
72
73impl<P: AstPayload> DefP<P> {
74    fn visit_children<'a>(&'a self, mut f: impl FnMut(Visit<'a, P>)) {
75        let DefP {
76            name: _,
77            params,
78            return_type,
79            body,
80            payload: _,
81        } = self;
82        params
83            .iter()
84            .for_each(|x| x.visit_expr(|x| f(Visit::Expr(x))));
85        return_type
86            .iter()
87            .for_each(|x| x.visit_expr(|x| f(Visit::Expr(x))));
88        f(Visit::Stmt(body));
89    }
90
91    pub fn visit_children_err<'a, E>(
92        &'a self,
93        mut f: impl FnMut(Visit<'a, P>) -> Result<(), E>,
94    ) -> Result<(), E> {
95        let mut result = Ok(());
96        self.visit_children(|x| {
97            if result.is_ok() {
98                result = f(x);
99            }
100        });
101        result
102    }
103}
104
105impl<P: AstPayload> StmtP<P> {
106    pub fn visit_children<'a>(&'a self, mut f: impl FnMut(Visit<'a, P>)) {
107        match self {
108            StmtP::Statements(xs) => xs.iter().for_each(|x| f(Visit::Stmt(x))),
109            StmtP::If(condition, then_block) => {
110                f(Visit::Expr(condition));
111                f(Visit::Stmt(then_block));
112            }
113            StmtP::IfElse(condition, then_block_else_block) => {
114                let (then_block, else_block) = &**then_block_else_block;
115                f(Visit::Expr(condition));
116                f(Visit::Stmt(then_block));
117                f(Visit::Stmt(else_block));
118            }
119            StmtP::Def(def) => def.visit_children(f),
120            StmtP::For(ForP { var, over, body }) => {
121                var.visit_expr(|x| f(Visit::Expr(x)));
122                f(Visit::Expr(over));
123                f(Visit::Stmt(body));
124            }
125            // Nothing else contains nested statements
126            StmtP::Break => {}
127            StmtP::Continue => {}
128            StmtP::Pass => {}
129            StmtP::Return(ret) => {
130                ret.iter().for_each(|x| f(Visit::Expr(x)));
131            }
132            StmtP::Yield(ret) => {
133                ret.iter().for_each(|x| f(Visit::Expr(x)));
134            }
135            StmtP::Expression(e) => f(Visit::Expr(e)),
136            StmtP::Assign(AssignP { lhs, ty, rhs }) => {
137                lhs.visit_expr(|x| f(Visit::Expr(x)));
138                ty.iter().for_each(|x| x.visit_expr(|x| f(Visit::Expr(x))));
139                f(Visit::Expr(rhs));
140            }
141            StmtP::AssignModify(lhs, _, rhs) => {
142                lhs.visit_expr(|x| f(Visit::Expr(x)));
143                f(Visit::Expr(rhs));
144            }
145            StmtP::Load(..) => {}
146            StmtP::Struct(StructP { name: _, fields }) => {
147                for field in fields {
148                    field.node.typ.visit_expr(|x| f(Visit::Expr(x)));
149                    if let Some(default) = &field.node.default {
150                        f(Visit::Expr(default));
151                    }
152                }
153            }
154            StmtP::Match(MatchP { subject, cases }) => {
155                f(Visit::Expr(subject));
156                for case in cases {
157                    f(Visit::Expr(&case.node.pattern));
158                    if let Some(guard) = &case.node.guard {
159                        f(Visit::Expr(guard));
160                    }
161                    f(Visit::Stmt(&case.node.body));
162                }
163            }
164        }
165    }
166
167    pub fn visit_children_mut<'a>(&'a mut self, mut f: impl FnMut(VisitMut<'a, P>)) {
168        match self {
169            StmtP::Statements(xs) => xs.iter_mut().for_each(|x| f(VisitMut::Stmt(x))),
170            StmtP::If(condition, then_block) => {
171                f(VisitMut::Expr(condition));
172                f(VisitMut::Stmt(then_block));
173            }
174            StmtP::IfElse(condition, then_block_else_block) => {
175                let (then_block, else_block) = &mut **then_block_else_block;
176                f(VisitMut::Expr(condition));
177                f(VisitMut::Stmt(then_block));
178                f(VisitMut::Stmt(else_block));
179            }
180            StmtP::Def(DefP {
181                name: _,
182                params,
183                return_type,
184                body,
185                payload: _,
186            }) => {
187                params
188                    .iter_mut()
189                    .for_each(|x| x.visit_expr_mut(|x| f(VisitMut::Expr(x))));
190                return_type
191                    .iter_mut()
192                    .for_each(|x| x.visit_expr_mut(|x| f(VisitMut::Expr(x))));
193                f(VisitMut::Stmt(body));
194            }
195            StmtP::For(ForP { var, over, body }) => {
196                var.visit_expr_mut(|x| f(VisitMut::Expr(x)));
197                f(VisitMut::Expr(over));
198                f(VisitMut::Stmt(body));
199            }
200            // Nothing else contains nested statements
201            StmtP::Break => {}
202            StmtP::Continue => {}
203            StmtP::Pass => {}
204            StmtP::Return(ret) => {
205                ret.iter_mut().for_each(|x| f(VisitMut::Expr(x)));
206            }
207            StmtP::Yield(ret) => {
208                ret.iter_mut().for_each(|x| f(VisitMut::Expr(x)));
209            }
210            StmtP::Expression(e) => f(VisitMut::Expr(e)),
211            StmtP::Assign(AssignP { lhs, ty, rhs }) => {
212                lhs.visit_expr_mut(|x| f(VisitMut::Expr(x)));
213                ty.iter_mut()
214                    .for_each(|x| x.visit_expr_mut(|x| f(VisitMut::Expr(x))));
215                f(VisitMut::Expr(rhs));
216            }
217            StmtP::AssignModify(lhs, _, rhs) => {
218                lhs.visit_expr_mut(|x| f(VisitMut::Expr(x)));
219                f(VisitMut::Expr(rhs));
220            }
221            StmtP::Load(..) => {}
222            StmtP::Struct(StructP { name: _, fields }) => {
223                for field in fields {
224                    field.node.typ.visit_expr_mut(|x| f(VisitMut::Expr(x)));
225                    if let Some(default) = &mut field.node.default {
226                        f(VisitMut::Expr(default));
227                    }
228                }
229            }
230            StmtP::Match(MatchP { subject, cases }) => {
231                f(VisitMut::Expr(subject));
232                for case in cases {
233                    f(VisitMut::Expr(&mut case.node.pattern));
234                    if let Some(guard) = &mut case.node.guard {
235                        f(VisitMut::Expr(guard));
236                    }
237                    f(VisitMut::Stmt(&mut case.node.body));
238                }
239            }
240        }
241    }
242
243    pub fn visit_children_err<'a, E>(
244        &'a self,
245        mut f: impl FnMut(Visit<'a, P>) -> Result<(), E>,
246    ) -> Result<(), E> {
247        let mut result = Ok(());
248        self.visit_children(|x| {
249            if result.is_ok() {
250                result = f(x);
251            }
252        });
253        result
254    }
255
256    pub fn visit_children_err_mut<'a, E>(
257        &'a mut self,
258        mut f: impl FnMut(VisitMut<'a, P>) -> Result<(), E>,
259    ) -> Result<(), E> {
260        let mut result = Ok(());
261        self.visit_children_mut(|x| {
262            if result.is_ok() {
263                result = f(x);
264            }
265        });
266        result
267    }
268
269    pub fn visit_stmt<'a>(&'a self, mut f: impl FnMut(&'a AstStmtP<P>)) {
270        self.visit_children(|x| match x {
271            Visit::Stmt(x) => f(x),
272            Visit::Expr(_) => {} // Nothing to do
273        })
274    }
275
276    pub fn visit_stmt_mut<'a>(&'a mut self, mut f: impl FnMut(&'a mut AstStmtP<P>)) {
277        self.visit_children_mut(|x| match x {
278            VisitMut::Stmt(x) => f(x),
279            VisitMut::Expr(_) => {} // Nothing to do
280        })
281    }
282
283    pub fn visit_expr<'a>(&'a self, mut f: impl FnMut(&'a AstExprP<P>)) {
284        // Note the &mut impl on f, it's subtle, see
285        // https://stackoverflow.com/questions/54613966/error-reached-the-recursion-limit-while-instantiating-funcclosure
286        fn pick<'a, P: AstPayload>(x: Visit<'a, P>, f: &mut impl FnMut(&'a AstExprP<P>)) {
287            match x {
288                Visit::Stmt(x) => x.visit_children(|x| pick(x, f)),
289                Visit::Expr(x) => f(x),
290            }
291        }
292        self.visit_children(|x| pick(x, &mut f))
293    }
294
295    pub fn visit_expr_mut<'a>(&'a mut self, mut f: impl FnMut(&'a mut AstExprP<P>)) {
296        // Note the &mut impl on f, it's subtle, see
297        // https://stackoverflow.com/questions/54613966/error-reached-the-recursion-limit-while-instantiating-funcclosure
298        fn pick<'a, P: AstPayload>(x: VisitMut<'a, P>, f: &mut impl FnMut(&'a mut AstExprP<P>)) {
299            match x {
300                VisitMut::Stmt(x) => x.visit_children_mut(|x| pick(x, f)),
301                VisitMut::Expr(x) => f(x),
302            }
303        }
304        self.visit_children_mut(|x| pick(x, &mut f))
305    }
306
307    pub fn visit_expr_result<'a, E>(
308        &'a self,
309        mut f: impl FnMut(&'a AstExprP<P>) -> Result<(), E>,
310    ) -> Result<(), E> {
311        let mut result = Ok(());
312        self.visit_expr(|x| {
313            if result.is_ok() {
314                result = f(x);
315            }
316        });
317        result
318    }
319
320    pub fn visit_stmt_result<E>(
321        &self,
322        mut f: impl FnMut(&AstStmtP<P>) -> Result<(), E>,
323    ) -> Result<(), E> {
324        let mut result = Ok(());
325        let f2 = |x: &AstStmtP<P>| {
326            if result.is_ok() {
327                result = f(x);
328            }
329        };
330        self.visit_stmt(f2);
331        result
332    }
333
334    /// Visit all type expressions in this statement and its children.
335    pub fn visit_type_expr_err_mut<E>(
336        &mut self,
337        f: &mut impl FnMut(&mut AstTypeExprP<P>) -> Result<(), E>,
338    ) -> Result<(), E> {
339        match self {
340            StmtP::Def(def) => {
341                for param in &mut def.params {
342                    if let (_, Some(ty), _) = param.split_mut() {
343                        f(ty)?;
344                    }
345                }
346                if let Some(ty) = &mut def.return_type {
347                    f(ty)?;
348                }
349            }
350            StmtP::Assign(assign) => {
351                if let Some(ty) = &mut assign.ty {
352                    f(ty)?;
353                }
354            }
355            StmtP::Struct(s) => {
356                for field in &mut s.fields {
357                    f(&mut field.node.typ)?;
358                }
359            }
360            _ => {}
361        }
362        self.visit_children_err_mut(|visit| match visit {
363            VisitMut::Stmt(stmt) => stmt.visit_type_expr_err_mut(f),
364            VisitMut::Expr(expr) => expr.visit_type_expr_err_mut(f),
365        })
366    }
367
368    /// Visit all identifiers in read position recursively.
369    pub fn visit_ident<E>(
370        &self,
371        mut f: impl FnMut(&AstIdentP<P>) -> Result<(), E>,
372    ) -> Result<(), E> {
373        self.visit_expr_result(|expr| expr.visit_ident(&mut f))
374    }
375}
376
377impl<P: AstPayload> ParameterP<P> {
378    // Split a parameter into name, type, default value
379    pub fn split(
380        &self,
381    ) -> (
382        Option<&AstAssignIdentP<P>>,
383        Option<&AstTypeExprP<P>>,
384        Option<&AstExprP<P>>,
385    ) {
386        match self {
387            ParameterP::Normal(a, b, None) | ParameterP::Args(a, b) | ParameterP::KwArgs(a, b) => {
388                (Some(a), b.as_ref().map(|x| &**x), None)
389            }
390            ParameterP::Normal(a, b, Some(c)) => (Some(a), b.as_ref().map(|x| &**x), Some(&**c)),
391            ParameterP::NoArgs | ParameterP::Slash => (None, None, None),
392        }
393    }
394
395    // Split a parameter into name, type, default value
396    pub fn split_mut(
397        &mut self,
398    ) -> (
399        Option<&mut AstAssignIdentP<P>>,
400        Option<&mut AstTypeExprP<P>>,
401        Option<&mut AstExprP<P>>,
402    ) {
403        match self {
404            ParameterP::Normal(a, b, None) | ParameterP::Args(a, b) | ParameterP::KwArgs(a, b) => {
405                (Some(a), b.as_mut().map(|x| &mut **x), None)
406            }
407            ParameterP::Normal(a, b, Some(c)) => {
408                (Some(a), b.as_mut().map(|x| &mut **x), Some(&mut **c))
409            }
410            ParameterP::NoArgs | ParameterP::Slash => (None, None, None),
411        }
412    }
413
414    pub fn visit_expr<'a>(&'a self, mut f: impl FnMut(&'a AstExprP<P>)) {
415        let (_, typ, def) = self.split();
416        typ.iter().for_each(|x| x.visit_expr(&mut f));
417        def.iter().for_each(|x| f(x));
418    }
419
420    pub fn visit_expr_mut<'a>(&'a mut self, mut f: impl FnMut(&'a mut AstExprP<P>)) {
421        let (_, typ, def) = self.split_mut();
422        if let Some(typ) = typ {
423            typ.visit_expr_mut(&mut f);
424        }
425        if let Some(def) = def {
426            f(def);
427        }
428    }
429}
430
431impl<P: AstPayload> ExprP<P> {
432    pub fn visit_expr<'a>(&'a self, mut f: impl FnMut(&'a AstExprP<P>)) {
433        match self {
434            ExprP::Tuple(xs) => xs.iter().for_each(|x| f(x)),
435            ExprP::Dot(x, _) => f(x),
436            ExprP::Call(a, b) => {
437                f(a);
438                b.args.iter().for_each(|x| f(x.expr()));
439            }
440            ExprP::Index(a_b) => {
441                let (a, b) = &**a_b;
442                f(a);
443                f(b);
444            }
445            ExprP::Index2(a_i0_i1) => {
446                let (a, i0, i1) = &**a_i0_i1;
447                f(a);
448                f(i0);
449                f(i1);
450            }
451            ExprP::Slice(a, b, c, d) => {
452                f(a);
453                b.iter().for_each(|x| f(x));
454                c.iter().for_each(|x| f(x));
455                d.iter().for_each(|x| f(x));
456            }
457            ExprP::Identifier(..) => {}
458            ExprP::Lambda(LambdaP {
459                params,
460                body,
461                payload: _,
462            }) => {
463                params.iter().for_each(|x| x.visit_expr(|x| f(x)));
464                f(body);
465            }
466            ExprP::Literal(_) => {}
467            ExprP::Not(x) => f(x),
468            ExprP::Minus(x) => f(x),
469            ExprP::Plus(x) => f(x),
470            ExprP::BitNot(x) => f(x),
471            ExprP::Op(x, _, y) => {
472                f(x);
473                f(y);
474            }
475            ExprP::If(a_b_c) => {
476                let (a, b, c) = &**a_b_c;
477                f(a);
478                f(b);
479                f(c);
480            }
481            ExprP::List(x) => x.iter().for_each(|x| f(x)),
482            ExprP::Dict(x) => x.iter().for_each(|(x, y)| {
483                f(x);
484                f(y);
485            }),
486            ExprP::Set(x) => x.iter().for_each(|x| f(x)),
487            ExprP::ListComprehension(x, for_, y) => {
488                for_.visit_expr(|x| f(x));
489                y.iter().for_each(|x| x.visit_expr(|x| f(x)));
490                f(x);
491            }
492            ExprP::SetComprehension(x, for_, y) => {
493                for_.visit_expr(|x| f(x));
494                y.iter().for_each(|x| x.visit_expr(|x| f(x)));
495                f(x);
496            }
497            ExprP::DictComprehension(x, for_, y) => {
498                for_.visit_expr(|x| f(x));
499                y.iter().for_each(|x| x.visit_expr(|x| f(x)));
500                f(&x.0);
501                f(&x.1);
502            }
503            ExprP::FString(fstring) => {
504                for expr in &fstring.expressions {
505                    f(expr);
506                }
507            }
508        }
509    }
510
511    /// Visit children expressions.
512    pub fn visit_expr_err<'a, E>(
513        &'a self,
514        mut f: impl FnMut(&'a AstExprP<P>) -> Result<(), E>,
515    ) -> Result<(), E> {
516        let mut ok = Ok(());
517        self.visit_expr(|x| {
518            if ok.is_ok() {
519                ok = f(x);
520            }
521        });
522        ok
523    }
524
525    pub fn visit_expr_err_mut<'a, E>(
526        &'a mut self,
527        mut f: impl FnMut(&'a mut AstExprP<P>) -> Result<(), E>,
528    ) -> Result<(), E> {
529        let mut ok = Ok(());
530        self.visit_expr_mut(|x| {
531            if ok.is_ok() {
532                ok = f(x);
533            }
534        });
535        ok
536    }
537
538    pub fn visit_expr_mut<'a>(&'a mut self, mut f: impl FnMut(&'a mut AstExprP<P>)) {
539        match self {
540            ExprP::Tuple(xs) => xs.iter_mut().for_each(|x| f(x)),
541            ExprP::Dot(x, _) => f(x),
542            ExprP::Call(a, b) => {
543                f(a);
544                b.args.iter_mut().for_each(|x| f(x.expr_mut()));
545            }
546            ExprP::Index(a_b) => {
547                let (a, b) = &mut **a_b;
548                f(a);
549                f(b);
550            }
551            ExprP::Index2(a_i0_i1) => {
552                let (a, i0, i1) = &mut **a_i0_i1;
553                f(a);
554                f(i0);
555                f(i1);
556            }
557            ExprP::Slice(a, b, c, d) => {
558                f(a);
559                b.iter_mut().for_each(|x| f(x));
560                c.iter_mut().for_each(|x| f(x));
561                d.iter_mut().for_each(|x| f(x));
562            }
563            ExprP::Identifier(..) => {}
564            ExprP::Lambda(LambdaP {
565                params,
566                body,
567                payload: _,
568            }) => {
569                params.iter_mut().for_each(|x| x.visit_expr_mut(|x| f(x)));
570                f(body);
571            }
572            ExprP::Literal(_) => {}
573            ExprP::Not(x) => f(x),
574            ExprP::Minus(x) => f(x),
575            ExprP::Plus(x) => f(x),
576            ExprP::BitNot(x) => f(x),
577            ExprP::Op(x, _, y) => {
578                f(x);
579                f(y);
580            }
581            ExprP::If(a_b_c) => {
582                let (a, b, c) = &mut **a_b_c;
583                f(a);
584                f(b);
585                f(c);
586            }
587            ExprP::List(x) => x.iter_mut().for_each(|x| f(x)),
588            ExprP::Dict(x) => x.iter_mut().for_each(|(x, y)| {
589                f(x);
590                f(y);
591            }),
592            ExprP::Set(x) => x.iter_mut().for_each(|x| f(x)),
593            ExprP::ListComprehension(x, for_, y) => {
594                for_.visit_expr_mut(|x| f(x));
595                y.iter_mut().for_each(|x| x.visit_expr_mut(|x| f(x)));
596                f(x);
597            }
598            ExprP::SetComprehension(x, for_, y) => {
599                for_.visit_expr_mut(|x| f(x));
600                y.iter_mut().for_each(|x| x.visit_expr_mut(|x| f(x)));
601                f(x);
602            }
603            ExprP::DictComprehension(x, for_, y) => {
604                for_.visit_expr_mut(|x| f(x));
605                y.iter_mut().for_each(|x| x.visit_expr_mut(|x| f(x)));
606                f(&mut x.0);
607                f(&mut x.1);
608            }
609            ExprP::FString(fstring) => {
610                for expr in &mut fstring.expressions {
611                    f(expr);
612                }
613            }
614        }
615    }
616
617    fn visit_type_expr_err_mut<E>(
618        &mut self,
619        f: &mut impl FnMut(&mut AstTypeExprP<P>) -> Result<(), E>,
620    ) -> Result<(), E> {
621        if let ExprP::Lambda(lambda) = self {
622            for param in &mut lambda.params {
623                if let (_, Some(ty), _) = param.split_mut() {
624                    f(ty)?;
625                }
626            }
627        }
628        self.visit_expr_err_mut(|expr| expr.visit_type_expr_err_mut(f))
629    }
630
631    /// Visit all identifiers in read position recursively.
632    fn visit_ident<E>(&self, f: &mut impl FnMut(&AstIdentP<P>) -> Result<(), E>) -> Result<(), E> {
633        if let ExprP::Identifier(ident) = self {
634            f(ident)?;
635        }
636        self.visit_expr_err(|expr| expr.visit_ident(f))
637    }
638}
639
640impl<P: AstPayload> TypeExprP<P> {
641    fn visit_expr<'a>(&'a self, mut f: impl FnMut(&'a AstExprP<P>)) {
642        f(&self.expr)
643    }
644
645    fn visit_expr_mut<'a>(&'a mut self, mut f: impl FnMut(&'a mut AstExprP<P>)) {
646        f(&mut self.expr)
647    }
648}
649
650impl<P: AstPayload> AssignTargetP<P> {
651    pub fn visit_expr<'a>(&'a self, mut f: impl FnMut(&'a AstExprP<P>)) {
652        fn recurse<'a, P: AstPayload>(
653            x: &'a AssignTargetP<P>,
654            f: &mut impl FnMut(&'a AstExprP<P>),
655        ) {
656            match x {
657                AssignTargetP::Tuple(xs) => xs.iter().for_each(|x| recurse(x, f)),
658                AssignTargetP::Dot(a, _) => f(a),
659                AssignTargetP::Index(a_b) => {
660                    let (a, b) = &**a_b;
661                    f(a);
662                    f(b);
663                }
664                AssignTargetP::Identifier(..) => {}
665            }
666        }
667        recurse(self, &mut f)
668    }
669
670    pub fn visit_expr_mut<'a>(&'a mut self, mut f: impl FnMut(&'a mut AstExprP<P>)) {
671        fn recurse<'a, P: AstPayload>(
672            x: &'a mut AssignTargetP<P>,
673            f: &mut impl FnMut(&'a mut AstExprP<P>),
674        ) {
675            match x {
676                AssignTargetP::Tuple(xs) => xs.iter_mut().for_each(|x| recurse(&mut *x, f)),
677                AssignTargetP::Dot(a, _) => f(a),
678                AssignTargetP::Index(a_b) => {
679                    let (a, b) = &mut **a_b;
680                    f(a);
681                    f(b);
682                }
683                AssignTargetP::Identifier(..) => {}
684            }
685        }
686        recurse(self, &mut f)
687    }
688
689    /// Assuming this expression was on the left-hand-side of an assignment,
690    /// visit all the names that are bound by this assignment.
691    /// Note that assignments like `x[i] = n` don't bind any names.
692    pub fn visit_lvalue<'a>(&'a self, mut f: impl FnMut(&'a AstAssignIdentP<P>)) {
693        fn recurse<'a, P: AstPayload>(
694            x: &'a AssignTargetP<P>,
695            f: &mut impl FnMut(&'a AstAssignIdentP<P>),
696        ) {
697            match x {
698                AssignTargetP::Identifier(x) => f(x),
699                AssignTargetP::Tuple(xs) => xs.iter().for_each(|x| recurse(x, f)),
700                _ => {}
701            }
702        }
703        recurse(self, &mut f)
704    }
705
706    pub fn visit_lvalue_mut<'a>(&'a mut self, mut f: impl FnMut(&'a mut AstAssignIdentP<P>)) {
707        fn recurse<'a, P: AstPayload>(
708            x: &'a mut AssignTargetP<P>,
709            f: &mut impl FnMut(&'a mut AstAssignIdentP<P>),
710        ) {
711            match x {
712                AssignTargetP::Identifier(x) => f(x),
713                AssignTargetP::Tuple(xs) => xs.iter_mut().for_each(|x| recurse(x, f)),
714                _ => {}
715            }
716        }
717        recurse(self, &mut f)
718    }
719}
720
721impl<P: AstPayload> ForClauseP<P> {
722    pub fn visit_expr<'a>(&'a self, mut f: impl FnMut(&'a AstExprP<P>)) {
723        self.var.visit_expr(&mut f);
724        f(&self.over);
725    }
726
727    pub fn visit_expr_mut<'a>(&'a mut self, mut f: impl FnMut(&'a mut AstExprP<P>)) {
728        self.var.visit_expr_mut(&mut f);
729        f(&mut self.over);
730    }
731}
732
733impl<P: AstPayload> ClauseP<P> {
734    pub fn visit_expr<'a>(&'a self, mut f: impl FnMut(&'a AstExprP<P>)) {
735        match self {
736            ClauseP::For(x) => x.visit_expr(f),
737            ClauseP::If(x) => f(x),
738        }
739    }
740
741    pub fn visit_expr_mut<'a>(&'a mut self, mut f: impl FnMut(&'a mut AstExprP<P>)) {
742        match self {
743            ClauseP::For(x) => x.visit_expr_mut(f),
744            ClauseP::If(x) => f(x),
745        }
746    }
747}