1use super::{Decl, DeclKind, Element, Expr, ExprKind, Name, Pattern, Stmt, StrSeg};
5
6impl Expr {
7 pub fn each_child<'e>(&'e self, mut f: impl FnMut(&'e Expr)) {
10 match &self.kind {
11 ExprKind::Str(segs) => segs.iter().for_each(|s| {
12 if let StrSeg::Expr(e) = s {
13 f(e);
14 }
15 }),
16 ExprKind::Tuple { items, .. } | ExprKind::Macro { args: items, .. } => {
17 items.iter().for_each(f)
18 }
19 ExprKind::Collection(items) => items.iter().for_each(|i| match i {
20 Element::Item(e) | Element::Spread(e) => f(e),
21 Element::Entry(k, v) => {
22 f(k);
23 f(v);
24 }
25 }),
26 ExprKind::New { args, init, .. } => {
27 args.iter().flatten().for_each(|a| f(&a.value));
28 init.iter().for_each(|(_, v)| f(v));
29 }
30 ExprKind::Call { callee, args } => {
31 f(callee);
32 args.iter().for_each(|a| f(&a.value));
33 }
34 ExprKind::Binary { left, right, .. } => {
35 f(left);
36 f(right);
37 }
38 ExprKind::Range { from, to, .. } => {
39 f(from);
40 f(to);
41 }
42 ExprKind::Index { expr, args, .. } => {
43 f(expr);
44 args.iter().for_each(f);
45 }
46 ExprKind::NewArray { sizes, init, .. } => {
47 sizes.iter().for_each(&mut f);
48 init.iter().flatten().for_each(|i| i.each_value(&mut f));
49 }
50 ExprKind::Conditional {
51 cond,
52 then,
53 otherwise,
54 } => {
55 f(cond);
56 f(then);
57 f(otherwise);
58 }
59 ExprKind::Switch { expr, arms } => {
60 f(expr);
61 for arm in arms {
62 arm.guard.iter().for_each(&mut f);
63 f(&arm.value);
64 }
65 }
66 ExprKind::With { expr, inits } => {
67 f(expr);
68 inits.iter().for_each(|(_, v)| f(v));
69 }
70 _ => self.each_wrapped(f),
71 }
72 }
73
74 fn each_wrapped<'e>(&'e self, mut f: impl FnMut(&'e Expr)) {
76 match &self.kind {
77 ExprKind::NameOf(e)
78 | ExprKind::NotNull(e)
79 | ExprKind::Move(e)
80 | ExprKind::Checked { expr: e, .. }
81 | ExprKind::Unary { expr: e, .. }
82 | ExprKind::Cast { expr: e, .. }
83 | ExprKind::Is { expr: e, .. }
84 | ExprKind::As { expr: e, .. }
85 | ExprKind::Has { expr: e, .. }
86 | ExprKind::TypeArgs { expr: e, .. }
87 | ExprKind::Member { expr: e, .. } => f(e),
88 _ => {}
89 }
90 }
91}
92
93impl DeclKind {
94 pub fn members(&self) -> &[Decl] {
97 match self {
98 DeclKind::Namespace {
99 body: Some(body), ..
100 }
101 | DeclKind::Mod { body, .. }
102 | DeclKind::Type { body, .. }
103 | DeclKind::Enum { body, .. }
104 | DeclKind::Content { body, .. }
105 | DeclKind::Component { body, .. }
106 | DeclKind::Extend { body, .. }
107 | DeclKind::Screen { body, .. }
108 | DeclKind::Command { body, .. } => body,
109 _ => &[],
110 }
111 }
112}
113
114impl Pattern {
115 pub fn each_binding<'p>(&'p self, f: &mut impl FnMut(&'p Name)) {
117 match self {
118 Pattern::Let(n) | Pattern::Type { bind: Some(n), .. } => f(n),
119 Pattern::Variant { args: all, .. } | Pattern::Tuple(all) | Pattern::List(all, _) => {
120 all.iter().for_each(|p| p.each_binding(f));
121 }
122 Pattern::Slice(Some(p)) => p.each_binding(f),
123 Pattern::Property { fields, .. } => fields.iter().for_each(|(_, p)| p.each_binding(f)),
124 Pattern::Or(a, b) | Pattern::And(a, b) => {
125 a.each_binding(f);
126 b.each_binding(f);
127 }
128 Pattern::Not(p) => p.each_binding(f),
129 _ => {}
130 }
131 }
132}
133
134impl Stmt {
135 pub fn each_expr(&self, f: &mut dyn FnMut(&Expr)) {
138 match self {
139 Stmt::Function(_) => {}
141 Stmt::Switch { expr, sections } => {
142 f(expr);
143 for s in sections {
144 for (_, guard) in s.labels.iter().flatten() {
145 guard.iter().for_each(&mut *f);
146 }
147 s.body.iter().for_each(|x| x.each_expr(f));
148 }
149 }
150 Stmt::Local { value, .. } => value.iter().for_each(&mut *f),
151 Stmt::Assign { place, value, .. } => {
152 f(place);
153 f(value);
154 }
155 Stmt::If {
156 cond,
157 then,
158 otherwise,
159 } => {
160 f(cond);
161 then.each_expr(f);
162 if let Some(o) = otherwise {
163 o.each_expr(f);
164 }
165 }
166 Stmt::Foreach { iter, body, .. } => {
167 f(iter);
168 body.each_expr(f);
169 }
170 Stmt::For {
171 init,
172 cond,
173 step,
174 body,
175 } => {
176 if let Some(i) = init {
177 i.each_expr(f);
178 }
179 cond.iter().for_each(&mut *f);
180 if let Some(st) = step {
181 st.each_expr(f);
182 }
183 body.each_expr(f);
184 }
185 Stmt::While { cond, body } | Stmt::DoWhile { body, cond } => {
186 f(cond);
187 body.each_expr(f);
188 }
189 Stmt::Block(b) | Stmt::Unsafe(b, _) | Stmt::Checked(b, _) => b.stmts.iter().for_each(|s| s.each_expr(f)),
190 Stmt::Return(v, _) | Stmt::Skip(v, _) | Stmt::Yield(v, _) => v.iter().for_each(&mut *f),
191 Stmt::Lock { target, body, .. } => {
192 f(target);
193 body.each_expr(f);
194 }
195 Stmt::Expr(e) | Stmt::Value(e) => f(e),
196 Stmt::Goto(crate::ast::Goto::Case(e), _) => f(e),
197 Stmt::Break(_) | Stmt::Continue(_) | Stmt::Label(_) | Stmt::Goto(..) => {}
198 }
199 }
200}
201
202impl Stmt {
203 pub fn inner(&self) -> Vec<&Stmt> {
205 match self {
206 Stmt::Block(b) | Stmt::Unsafe(b, _) | Stmt::Checked(b, _) => b.stmts.iter().collect(),
207 Stmt::If {
208 then, otherwise, ..
209 } => std::iter::once(&**then).chain(otherwise.as_deref()).collect(),
210 Stmt::Foreach { body, .. }
211 | Stmt::While { body, .. }
212 | Stmt::DoWhile { body, .. }
213 | Stmt::Lock { body, .. } => vec![&**body],
214 Stmt::For {
215 init, step, body, ..
216 } => init.as_deref().into_iter().chain(step.as_deref()).chain([&**body]).collect(),
217 Stmt::Switch { sections, .. } => sections.iter().flat_map(|s| &s.body).collect(),
218 _ => Vec::new(),
219 }
220 }
221
222 pub fn any_inside(&self, found: &dyn Fn(&Stmt) -> bool, enter: &dyn Fn(&Stmt) -> bool) -> bool {
225 found(self) || (enter(self) && self.inner().iter().any(|s| s.any_inside(found, enter)))
226 }
227
228 pub fn has_labels(&self) -> bool {
230 self.any_inside(&|s| matches!(s, Stmt::Label(_)), &|_| true)
231 }
232
233 pub fn goes_to_case(&self) -> bool {
236 self.any_inside(
237 &|s| matches!(s, Stmt::Goto(super::Goto::Case(_) | super::Goto::Default, _)),
238 &|s| !matches!(s, Stmt::Switch { .. }),
239 )
240 }
241}