1#![allow(clippy::many_single_char_names)]
20#![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 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 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(_) => {} })
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(_) => {} })
281 }
282
283 pub fn visit_expr<'a>(&'a self, mut f: impl FnMut(&'a AstExprP<P>)) {
284 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 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 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 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 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 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 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 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 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}