1
// Expr and Stmt from the paper, manually derived.
2

            
3
use std::iter::zip;
4

            
5
use im::vector;
6
//use uniplate::test_common::paper::*;
7
use uniplate::biplate::*;
8

            
9
use self::Expr::*;
10

            
11
// Stmt and Expr to demonstrate and test multitype traversals.
12
#[derive(Eq, PartialEq, Clone, Debug)]
13
pub enum Stmt {
14
    Assign(String, Expr),
15
    Sequence(Vec<Stmt>),
16
    If(Expr, Box<Stmt>, Box<Stmt>),
17
    While(Expr, Box<Stmt>),
18
}
19

            
20
#[derive(Eq, PartialEq, Clone, Debug)]
21
pub enum Expr {
22
    Add(Box<Expr>, Box<Expr>),
23
    Sub(Box<Expr>, Box<Expr>),
24
    Mul(Box<Expr>, Box<Expr>),
25
    Div(Box<Expr>, Box<Expr>),
26
    Val(i32),
27
    Var(String),
28
    Neg(Box<Expr>),
29
}
30

            
31
impl Uniplate for Expr {
32
    fn uniplate(&self) -> (Tree<Self>, Box<dyn Fn(Tree<Self>) -> Self>) {
33
        match self.clone() {
34
            Add(f0, f1) => {
35
                // Field 0 - Box<Expr>
36
                let (f0_tree, f0_ctx) = <Expr as Biplate<Expr>>::biplate(&*f0);
37

            
38
                // Field 1 - Box<Expr>
39
                let (f1_tree, f1_ctx) = <Expr as Biplate<Expr>>::biplate(&*f1);
40

            
41
                let tree = Many(vector![f0_tree, f1_tree]);
42
                let ctx = Box::new(move |new_tree| {
43
                    let Many(ts) = new_tree else { panic!() };
44
                    assert_eq!(ts.len(), 2);
45
                    Add(
46
                        Box::new(f0_ctx(ts[0].clone())),
47
                        Box::new(f1_ctx(ts[1].clone())),
48
                    )
49
                });
50

            
51
                (tree, ctx)
52
            }
53
            Sub(f0, f1) => {
54
                // Field 0 - Box<Expr>
55
                let (f0_tree, f0_ctx) = <Expr as Biplate<Expr>>::biplate(&*f0);
56

            
57
                // Field 1 - Box<Expr>
58
                let (f1_tree, f1_ctx) = <Expr as Biplate<Expr>>::biplate(&*f1);
59

            
60
                let tree = Many(vector![f0_tree, f1_tree]);
61
                let ctx = Box::new(move |new_tree| {
62
                    let Many(ts) = new_tree else { panic!() };
63
                    assert_eq!(ts.len(), 2);
64
                    Add(
65
                        Box::new(f0_ctx(ts[0].clone())),
66
                        Box::new(f1_ctx(ts[1].clone())),
67
                    )
68
                });
69

            
70
                (tree, ctx)
71
            }
72
            Mul(f0, f1) => {
73
                // Field 0 - Box<Expr>
74
                let (f0_tree, f0_ctx) = <Expr as Biplate<Expr>>::biplate(&*f0);
75

            
76
                // Field 1 - Box<Expr>
77
                let (f1_tree, f1_ctx) = <Expr as Biplate<Expr>>::biplate(&*f1);
78

            
79
                let tree = Many(vector![f0_tree, f1_tree]);
80
                let ctx = Box::new(move |new_tree| {
81
                    let Many(ts) = new_tree else { panic!() };
82
                    assert_eq!(ts.len(), 2);
83
                    Add(
84
                        Box::new(f0_ctx(ts[0].clone())),
85
                        Box::new(f1_ctx(ts[1].clone())),
86
                    )
87
                });
88

            
89
                (tree, ctx)
90
            }
91
            Div(f0, f1) => {
92
                // Field 0 - Box<Expr>
93
                let (f0_tree, f0_ctx) = <Expr as Biplate<Expr>>::biplate(&*f0);
94

            
95
                // Field 1 - Box<Expr>
96
                let (f1_tree, f1_ctx) = <Expr as Biplate<Expr>>::biplate(&*f1);
97

            
98
                let tree = Many(vector![f0_tree, f1_tree]);
99
                let ctx = Box::new(move |new_tree| {
100
                    let Many(ts) = new_tree else { panic!() };
101
                    assert_eq!(ts.len(), 2);
102
                    Add(
103
                        Box::new(f0_ctx(ts[0].clone())),
104
                        Box::new(f1_ctx(ts[1].clone())),
105
                    )
106
                });
107

            
108
                (tree, ctx)
109
            }
110

            
111
            Val(f0) => (
112
                Zero,
113
                Box::new(move |x| {
114
                    let Zero = x else { panic!() };
115
                    Val(f0)
116
                }),
117
            ),
118
            Var(f0) => (
119
                Zero,
120
                Box::new(move |x| {
121
                    let Zero = x else { panic!() };
122
                    Var(f0.clone())
123
                }),
124
            ),
125

            
126
            Neg(f0) => (
127
                Zero,
128
                Box::new(move |x| {
129
                    let Zero = x else { panic!() };
130
                    Neg(f0.clone())
131
                }),
132
            ),
133
        }
134
    }
135
}
136

            
137
impl Biplate<Stmt> for Expr {
138
    fn biplate(&self) -> (Tree<Stmt>, Box<dyn Fn(Tree<Stmt>) -> Expr>) {
139
        // Optimisation - in derivation, build index of types that lead to eachother.
140
        // Walk this graph to generate all "reachable types from expr"
141
        //
142
        // Stmt is not reachable so just return 0.
143
        //
144
        // Paper does this with the combinators!
145
        //
146
        // We may also need this to know what Biplates to derive!
147
        let expr = self.clone();
148
        (
149
            Zero,
150
            Box::new(move |stmt| {
151
                let Zero = stmt else { panic!() };
152
                expr.clone()
153
            }),
154
        )
155
    }
156
}
157

            
158
//this is the most interesting example!
159
#[allow(clippy::type_complexity)]
160
impl Biplate<Expr> for Stmt {
161
    fn biplate(&self) -> (Tree<Expr>, Box<dyn Fn(Tree<Expr>) -> Stmt>) {
162
        match self.clone() {
163
            Assign(f0, f1) => {
164
                // Field 0 - non recursive (String)
165
                let (f0_tree, f0_ctx) = (
166
                    Tree::<Expr>::Zero,
167
                    Box::new(move |_: Tree<Expr>| f0.clone()),
168
                );
169

            
170
                //field 1 - Expr - target type
171
                let (f1_tree, f1_ctx) = <Expr as Biplate<Expr>>::biplate(&f1);
172

            
173
                let tree = Tree::<Expr>::Many(vector![f0_tree, f1_tree]);
174

            
175
                let ctx = Box::new(move |new_tree| {
176
                    let Many(ts) = new_tree else { panic!() };
177
                    assert_eq!(ts.len(), 2);
178
                    Assign(f0_ctx(ts[0].clone()), f1_ctx(ts[1].clone()))
179
                });
180

            
181
                (tree, ctx)
182
            }
183
            Sequence(f0) => {
184
                // Field 0 - Vec<Stmt>
185

            
186
                // Get trees and contexts for each element.
187
                let (f0_elems, f0_ctxs): (Vec<Tree<Expr>>, Vec<Box<dyn Fn(Tree<Expr>) -> Stmt>>) =
188
                    f0.into_iter()
189
                        .map(|stmt| <Stmt as Biplate<Expr>>::biplate(&stmt))
190
                        .unzip();
191

            
192
                let f0_tree = Many(f0_elems.into());
193
                let f0_ctx: Box<dyn Fn(Tree<Expr>) -> Vec<Stmt>> = Box::new(move |new_tree| {
194
                    let Many(elem_ts) = new_tree else {
195
                        panic!();
196
                    };
197

            
198
                    zip(&f0_ctxs, elem_ts).map(|(ctx, t)| (**ctx)(t)).collect()
199
                });
200

            
201
                let tree = Many(vector![f0_tree]);
202
                let ctx = Box::new(move |new_tree| {
203
                    let Many(ts) = new_tree else {
204
                        panic!();
205
                    };
206
                    assert_eq!(ts.len(), 1);
207
                    Sequence(f0_ctx(ts[0].clone()))
208
                });
209

            
210
                (tree, ctx)
211
            }
212

            
213
            If(f0, f1, f2) => {
214
                // Field 0 - Expr
215
                let (f0_tree, f0_ctx) = <Expr as Biplate<Expr>>::biplate(&f0);
216

            
217
                // Field 1 - Box::(stmt)
218
                let (f1_tree, f1_ctx) = <Stmt as Biplate<Expr>>::biplate(&*f1);
219

            
220
                //Field 2 - Box::(Stmt)
221
                let (f2_tree, f2_ctx) = <Stmt as Biplate<Expr>>::biplate(&*f2);
222

            
223
                let tree = Many(vector![f0_tree, f1_tree, f2_tree]);
224
                let ctx = Box::new(move |new_tree| {
225
                    let Many(ts) = new_tree else { panic!() };
226
                    assert_eq!(ts.len(), 3);
227
                    If(
228
                        f0_ctx(ts[0].clone()),
229
                        Box::new(f1_ctx(ts[1].clone())),
230
                        Box::new(f2_ctx(ts[2].clone())),
231
                    )
232
                });
233

            
234
                (tree, ctx)
235
            }
236
            While(f0, f1) => {
237
                // Field 0 - Expr
238
                let (f0_tree, f0_ctx) = <Expr as Biplate<Expr>>::biplate(&f0);
239

            
240
                //Field 1 - Box::(Stmt)
241
                let (f1_tree, f1_ctx) = <Stmt as Biplate<Expr>>::biplate(&*f1);
242

            
243
                let tree = Many(vector![f0_tree, f1_tree]);
244
                let ctx = Box::new(move |new_tree| {
245
                    let Many(ts) = new_tree else { panic!() };
246
                    assert_eq!(ts.len(), 2);
247
                    While(f0_ctx(ts[0].clone()), Box::new(f1_ctx(ts[1].clone())))
248
                });
249

            
250
                (tree, ctx)
251
            }
252
        }
253
    }
254
}
255

            
256
impl Biplate<Expr> for Expr {
257
    fn biplate(&self) -> (Tree<Expr>, Box<dyn Fn(Tree<Expr>) -> Self>) {
258
        (
259
            One(self.clone()),
260
            Box::new(|t| {
261
                let One(stmt) = t else { panic!() };
262
                stmt
263
            }),
264
        )
265
    }
266
}
267

            
268
impl Biplate<Stmt> for Stmt {
269
    fn biplate(&self) -> (Tree<Stmt>, Box<dyn Fn(Tree<Stmt>) -> Self>) {
270
        (
271
            One(self.clone()),
272
            Box::new(|t| {
273
                let One(stmt) = t else { panic!() };
274
                stmt
275
            }),
276
        )
277
    }
278
}
279

            
280
use Stmt::*;
281
use Tree::*;
282

            
283
impl Uniplate for Stmt {
284
    fn uniplate(&self) -> (Tree<Stmt>, Box<dyn Fn(Tree<Stmt>) -> Stmt>) {
285
        match self.clone() {
286
            Assign(s, expr) => {
287
                // Field 0 - non recursive (String)
288
                let (f0_tree, f0_ctx) =
289
                    (Tree::<Stmt>::Zero, Box::new(move |_: Tree<Stmt>| s.clone()));
290

            
291
                // Field 1- ADT (Expr)
292
                let (f1_tree, f1_ctx) = <Expr as Biplate<Stmt>>::biplate(&expr);
293

            
294
                // we know there is no path Expr -> Stmt, so we could just inline the zero
295
                // defintion (see Biplate<Stmt> for Expr comments)
296
                // let (f1_tree,f1_ctx) (Zero, Box::new(move |stmt| {let Zero = stmt else {panic!()}; f1.clone()}));
297

            
298
                let tree = Many(vector![f0_tree, f1_tree]);
299
                let ctx = Box::new(move |new_tree| {
300
                    let Many(ts) = new_tree else { panic!() };
301
                    assert_eq!(ts.len(), 2);
302
                    Assign(f0_ctx(ts[0].clone()), f1_ctx(ts[1].clone()))
303
                });
304

            
305
                (tree, ctx)
306
            }
307
            Sequence(f0) => {
308
                // Field 0 - Vec<Stmt>
309
                // Special case for iterables / lists?
310

            
311
                // Get trees and contexts for each element.
312
                let (f0_elems, f0_ctxs): (Vec<Tree<Stmt>>, Vec<Box<dyn Fn(Tree<Stmt>) -> Stmt>>) =
313
                    f0.into_iter()
314
                        .map(|stmt| <Stmt as Biplate<Stmt>>::biplate(&stmt))
315
                        .unzip();
316

            
317
                let f0_tree = Many(f0_elems.into());
318
                let f0_ctx: Box<dyn Fn(Tree<Stmt>) -> Vec<Stmt>> = Box::new(move |new_tree| {
319
                    let Many(elem_ts) = new_tree else {
320
                        panic!();
321
                    };
322

            
323
                    zip(&f0_ctxs, elem_ts).map(|(ctx, t)| (**ctx)(t)).collect()
324
                });
325

            
326
                let tree = Many(vector![f0_tree]);
327
                let ctx = Box::new(move |new_tree| {
328
                    let Many(ts) = new_tree else {
329
                        panic!();
330
                    };
331
                    assert_eq!(ts.len(), 1);
332
                    Sequence(f0_ctx(ts[0].clone()))
333
                });
334

            
335
                (tree, ctx)
336
            }
337
            If(f0, f1, f2) => {
338
                // Field 0 - Expr
339
                let (f0_tree, f0_ctx) = <Expr as Biplate<Stmt>>::biplate(&f0);
340

            
341
                //field 1 - box::(stmt)
342
                // Treat T, Box<T> as a special case as defining Uniplate and Biplate for Box<T> is
343
                // a lot of moving things from stack to heap and back for no reason.
344
                let (f1_tree, f1_ctx) = <Stmt as Biplate<Stmt>>::biplate(&*f1);
345

            
346
                //Field 2 - Box::(Stmt)
347
                let (f2_tree, f2_ctx) = <Stmt as Biplate<Stmt>>::biplate(&*f2);
348

            
349
                let tree = Many(vector![f0_tree, f1_tree, f2_tree]);
350
                let ctx = Box::new(move |new_tree| {
351
                    let Many(ts) = new_tree else { panic!() };
352
                    assert_eq!(ts.len(), 3);
353
                    If(
354
                        f0_ctx(ts[0].clone()),
355
                        Box::new(f1_ctx(ts[1].clone())),
356
                        Box::new(f2_ctx(ts[2].clone())),
357
                    )
358
                });
359

            
360
                (tree, ctx)
361
            }
362
            While(f0, f1) => {
363
                // Field 0 - Expr
364
                let (f0_tree, f0_ctx) = <Expr as Biplate<Stmt>>::biplate(&f0);
365

            
366
                //Field 1 - Box::(Stmt)
367
                let (f1_tree, f1_ctx) = <Stmt as Biplate<Stmt>>::biplate(&*f1);
368

            
369
                let tree = Many(vector![f0_tree, f1_tree]);
370
                let ctx = Box::new(move |new_tree| {
371
                    let Many(ts) = new_tree else { panic!() };
372
                    assert_eq!(ts.len(), 2);
373
                    While(f0_ctx(ts[0].clone()), Box::new(f1_ctx(ts[1].clone())))
374
                });
375

            
376
                (tree, ctx)
377
            }
378
        }
379
    }
380
}
381

            
382
#[test]
383
fn children_bi_multitype() {
384
    let my_stmt = Sequence(vec![
385
        While(
386
            Val(0),
387
            Box::new(Assign(
388
                "x".to_owned(),
389
                Add(Box::new(Var("x".to_owned())), Box::new(Val(10))),
390
            )),
391
        ),
392
        If(
393
            Var("x".to_string()),
394
            Box::new(Assign(
395
                "x".to_string(),
396
                Add(Box::new(Var("x".to_owned())), Box::new(Val(10))),
397
            )),
398
            Box::new(Sequence(vec![])),
399
        ),
400
    ]);
401

            
402
    let expected_expr_children = 4;
403

            
404
    let children = <Stmt as Biplate<Expr>>::children_bi(&my_stmt);
405

            
406
    assert_eq!(expected_expr_children, children.len());
407

            
408
    println!("{:?}", children);
409
    let Val(_) = children[0] else { panic!() };
410
    let Add(_, _) = children[1] else { panic!() };
411
    let Var(_) = children[2] else { panic!() };
412
    let Add(_, _) = children[3] else { panic!() };
413
}
414

            
415
#[test]
416
fn universe_bi_multitype() {
417
    let my_stmt = Sequence(vec![
418
        While(
419
            Val(0),
420
            Box::new(Assign(
421
                "x".to_owned(),
422
                Add(Box::new(Var("x".to_owned())), Box::new(Val(10))),
423
            )),
424
        ),
425
        If(
426
            Var("x".to_string()),
427
            Box::new(Assign(
428
                "x".to_string(),
429
                Add(Box::new(Var("x".to_owned())), Box::new(Val(10))),
430
            )),
431
            Box::new(Sequence(vec![])),
432
        ),
433
    ]);
434

            
435
    let expected_expr_universe = 8;
436

            
437
    let children = <Stmt as Biplate<Expr>>::universe_bi(&my_stmt);
438

            
439
    assert_eq!(expected_expr_universe, children.len());
440

            
441
    println!("{:?}", children);
442
    let Val(_) = children[0] else { panic!() };
443
    let Add(_, _) = children[1] else { panic!() };
444
    let Var(_) = children[2] else { panic!() };
445
    let Val(_) = children[3] else { panic!() };
446
    let Var(_) = children[4] else { panic!() };
447
    let Add(_, _) = children[5] else { panic!() };
448
    let Var(_) = children[6] else { panic!() };
449
    let Val(_) = children[7] else { panic!() };
450
}