1
//! Here we test rule groups with differing priorities.
2
//! Rules in a higher-index group will be applied first, even if they apply to lower nodes in the tree.
3

            
4
use tree_morph::prelude::*;
5
use uniplate::derive::Uniplate;
6

            
7
/// A simple language of two literals and a wrapper
8
#[derive(Debug, Clone, PartialEq, Eq, Uniplate)]
9
#[uniplate()]
10
enum Expr {
11
    A,               // a
12
    B,               // b
13
    Wrap(Box<Expr>), // [E]
14
}
15

            
16
/// [a] ~> a
17
5
fn rule_unwrap_a(_: &mut Commands<Expr, ()>, expr: &Expr, _: &()) -> Option<Expr> {
18
5
    if let Expr::Wrap(inner) = expr {
19
2
        if let Expr::A = **inner {
20
1
            return Some(Expr::A);
21
1
        }
22
3
    }
23
4
    None
24
5
}
25

            
26
/// a ~> b
27
6
fn rule_a_to_b(_: &mut Commands<Expr, ()>, expr: &Expr, _: &()) -> Option<Expr> {
28
6
    if let Expr::A = expr {
29
2
        return Some(Expr::B);
30
4
    }
31
4
    None
32
6
}
33

            
34
#[test]
35
1
fn same_group() {
36
1
    // If the rules are in the same group, unwrap_a will apply higher in the tree
37
1

            
38
1
    // [a]
39
1
    let expr = Expr::Wrap(Box::new(Expr::A));
40
1

            
41
1
    let (result, _) = morph(
42
1
        vec![rule_fns![rule_unwrap_a], rule_fns![rule_a_to_b]],
43
1
        select_first,
44
1
        expr,
45
1
        (),
46
1
    );
47
1

            
48
1
    // [a] ~> a ~> b
49
1
    assert_eq!(result, Expr::B);
50
1
}
51

            
52
#[test]
53
1
fn a_to_b_first() {
54
1
    // a_to_b is in a higher group than unwrap_a, so it will be applied first to the lower expression
55
1

            
56
1
    // [a]
57
1
    let expr = Expr::Wrap(Box::new(Expr::A));
58
1

            
59
1
    let (result, _) = morph(
60
1
        vec![rule_fns![rule_a_to_b], rule_fns![rule_unwrap_a]],
61
1
        select_first,
62
1
        expr,
63
1
        (),
64
1
    );
65
1

            
66
1
    // [a] ~> [b]
67
1
    assert_eq!(result, Expr::Wrap(Box::new(Expr::B)));
68
1
}