purescript_corefn/
walk.rs

1use {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}