purescript_corefn/
walk.rs1use {Alternative, Bind, Decl, Expression};
2
3pub fn expression(
4 expr: &Expression,
5 pre: &mut impl FnMut(&Expression),
6 post: &mut impl FnMut(&Expression),
7) {
8 macro_rules! f {
9 ($a:expr) => {
10 expression($a, pre, post);
11 };
12 }
13 use Expression::*;
14 pre(expr);
15 match expr {
16 Abs { body, .. } => f!(body),
17 Accessor { expression, .. } => f!(expression),
18 App {
19 abstraction,
20 argument,
21 ..
22 } => {
23 f!(abstraction);
24 f!(argument);
25 }
26 Case {
27 alternatives,
28 expressions,
29 ..
30 } => {
31 for alternative in alternatives {
32 match alternative {
33 Alternative::Guarded { expressions, .. } => {
34 for expression in expressions {
35 f!(&expression.guard);
36 f!(&expression.expression);
37 }
38 }
39 Alternative::Unguarded { expression, .. } => {
40 f!(expression);
41 }
42 }
43 }
44 for expression in expressions {
45 f!(expression);
46 }
47 }
48 Constructor { .. } => {}
49 Let {
50 expression, binds, ..
51 } => {
52 f!(expression);
53 for decl in binds {
54 walk_decl(decl, pre, post);
55 }
56 }
57 Literal { value, .. } => match value {
58 ::Literal::Array { value } => {
59 for v in value {
60 f!(v)
61 }
62 }
63 ::Literal::Object { value } => {
64 for (_, v) in value {
65 f!(v)
66 }
67 }
68 _ => {}
69 },
70 ObjectUpdate {
71 expression,
72 updates,
73 ..
74 } => {
75 f!(expression);
76 for (_, update) in updates {
77 f!(update);
78 }
79 }
80 Var { .. } => {}
81 }
82 post(expr);
83
84 fn walk_decl(
85 decl: &Decl,
86 pre: &mut impl FnMut(&Expression),
87 post: &mut impl FnMut(&Expression),
88 ) {
89 let mut f = |bind: &Bind| expression(&bind.expression, pre, post);
90 match decl {
91 Decl::NonRec(bind) => f(bind),
92 Decl::Rec { binds } => {
93 for bind in binds {
94 f(bind)
95 }
96 }
97 }
98 }
99}
100
101pub fn expression_mut(
102 expr: &mut Expression,
103 pre: &mut impl FnMut(&mut Expression),
104 post: &mut impl FnMut(&mut Expression),
105) {
106 macro_rules! f {
107 ($a:expr) => {
108 expression_mut($a, pre, post);
109 };
110 }
111 use Expression::*;
112 pre(expr);
113 match expr {
114 Abs { body, .. } => f!(body),
115 Accessor { expression, .. } => f!(expression),
116 App {
117 abstraction,
118 argument,
119 ..
120 } => {
121 f!(abstraction);
122 f!(argument);
123 }
124 Case {
125 alternatives,
126 expressions,
127 ..
128 } => {
129 for alternative in alternatives {
130 match alternative {
131 Alternative::Guarded { expressions, .. } => {
132 for expression in expressions {
133 f!(&mut expression.guard);
134 f!(&mut expression.expression);
135 }
136 }
137 Alternative::Unguarded { expression, .. } => {
138 f!(expression);
139 }
140 }
141 }
142 for expression in expressions {
143 f!(expression);
144 }
145 }
146 Constructor { .. } => {}
147 Let {
148 expression, binds, ..
149 } => {
150 f!(expression);
151 for decl in binds {
152 walk_decl(decl, pre, post);
153 }
154 }
155 Literal { value, .. } => match value {
156 ::Literal::Array { value } => {
157 for v in value {
158 f!(v)
159 }
160 }
161 ::Literal::Object { value } => {
162 for (_, v) in value {
163 f!(v)
164 }
165 }
166 _ => {}
167 },
168 ObjectUpdate {
169 expression,
170 updates,
171 ..
172 } => {
173 f!(expression);
174 for (_, update) in updates {
175 f!(update);
176 }
177 }
178 Var { .. } => {}
179 }
180 post(expr);
181
182 fn walk_decl(
183 decl: &mut Decl,
184 pre: &mut impl FnMut(&mut Expression),
185 post: &mut impl FnMut(&mut Expression),
186 ) {
187 let mut f = |bind: &mut Bind| expression_mut(&mut bind.expression, pre, post);
188 match decl {
189 Decl::NonRec(bind) => f(bind),
190 Decl::Rec { binds } => {
191 for bind in binds {
192 f(bind)
193 }
194 }
195 }
196 }
197}