1
//! Various selector functions for different use cases.
2
//!
3
//! A selector function accepts an iterator over ([`Rule`], [`Update`]) pairs and returns the
4
//! selected [`Update`], or `None`.
5
//!
6
//! [`morph`](crate::morph) will call the given selector function when there is an ambiguity in
7
//! which rule to apply. That is, when more than one rule from the same group returns [`Some(...)`]
8
//! for a given sub-tree.
9

            
10
use std::{collections::VecDeque, fmt::Display, io::Write, sync::Arc};
11

            
12
use crate::{Rule, Update};
13
use multipeek::multipeek;
14
use uniplate::Uniplate;
15

            
16
/// Returns the first [`Update`] if the iterator only yields one, otherwise calls `select`.
17
///
18
/// See the module-level documentation for more information.
19
87
pub(crate) fn one_or_select<T, M, R>(
20
87
    select: impl Fn(&T, &mut dyn Iterator<Item = (&R, Update<T, M>)>) -> Option<Update<T, M>>,
21
87
    t: &T,
22
87
    rs: &mut dyn Iterator<Item = (&R, Update<T, M>)>,
23
87
) -> Option<Update<T, M>>
24
87
where
25
87
    T: Uniplate,
26
87
    R: Rule<T, M>,
27
87
{
28
87
    let mut rs = multipeek(rs);
29
87
    if rs.peek_nth(1).is_none() {
30
86
        return rs.next().map(|(_, u)| u);
31
1
    }
32
1
    select(t, &mut rs)
33
87
}
34

            
35
/// Returns the first available [`Update`] if there is one, otherwise returns `None`.
36
///
37
/// This is a good default selection strategy, especially when you expect only one possible
38
/// rule to apply to any one term.
39
///
40
/// See the module-level documentation for more information.
41
pub fn select_first<T, M, R>(
42
    _: &T,
43
    rs: &mut dyn Iterator<Item = (&R, Update<T, M>)>,
44
) -> Option<Update<T, M>>
45
where
46
    T: Uniplate,
47
    R: Rule<T, M>,
48
{
49
    rs.next().map(|(_, u)| u)
50
}
51

            
52
/// Panics when called by the engine, printing the original subtree and all applicable rules
53
/// and their results.
54
///
55
/// This is useful when you always expect no more than one rule to be applicable, as the
56
/// engine will only call the selector function when there is an ambiguity in which to apply.
57
///
58
/// See the module-level documentation for more information.
59
1
pub fn select_panic<T, M, R>(
60
1
    t: &T,
61
1
    rs: &mut dyn Iterator<Item = (&R, Update<T, M>)>,
62
1
) -> Option<Update<T, M>>
63
1
where
64
1
    T: Uniplate + std::fmt::Debug,
65
1
    R: Rule<T, M> + std::fmt::Debug,
66
1
{
67
2
    let rules = rs.map(|(r, _)| r).collect::<Vec<_>>();
68
1
    // Since `one_or_select` only calls the selector if there is more than one rule,
69
1
    // at this point there is guaranteed to be more than one rule.
70
1
    panic!(
71
1
        "Multiple rules applicable to expression {:?}\n{:?}",
72
1
        t, rules
73
1
    );
74
}
75

            
76
/// Selects an [`Update`] based on user input through stdin.
77
///
78
/// See the module-level documentation for more information.
79
pub fn select_user_input<T, M, R>(
80
    t: &T,
81
    rs: &mut dyn Iterator<Item = (&R, Update<T, M>)>,
82
) -> Option<Update<T, M>>
83
where
84
    T: Uniplate + Display,
85
    R: Rule<T, M> + Display,
86
{
87
    let mut choices: Vec<_> = rs.collect();
88

            
89
    let rules = choices
90
        .iter()
91
        .enumerate()
92
        .map(
93
            |(
94
                i,
95
                (
96
                    r,
97
                    Update {
98
                        new_subtree: new_tree,
99
                        ..
100
                    },
101
                ),
102
            )| {
103
                format!(
104
                    "{}. {}
105
   ~> {}",
106
                    i + 1,
107
                    r,
108
                    new_tree
109
                )
110
            },
111
        )
112
        .collect::<Vec<_>>()
113
        .join("\n\n");
114

            
115
    loop {
116
        print!(
117
            "--- Current Expression ---
118
{}
119

            
120
--- Rules ---
121
{}
122

            
123
---
124
q   No change
125
<n> Apply rule n
126

            
127
:",
128
            t, rules
129
        );
130
        std::io::stdout().flush().unwrap(); // Print the : on same line
131

            
132
        let mut line = String::new();
133
        std::io::stdin().read_line(&mut line).unwrap();
134

            
135
        match line.trim() {
136
            "q" => return None,
137
            n => {
138
                if let Ok(n) = n.parse::<usize>() {
139
                    if n > 0 && n <= choices.len() {
140
                        let ret = choices.swap_remove(n - 1).1;
141
                        return Some(ret);
142
                    }
143
                }
144
            }
145
        }
146
    }
147
}
148

            
149
/// Selects a random [`Update`] from the iterator.
150
///
151
/// See the module-level documentation for more information.
152
pub fn select_random<T, M, R>(
153
    _: &T,
154
    rs: &mut dyn Iterator<Item = (&R, Update<T, M>)>,
155
) -> Option<Update<T, M>>
156
where
157
    T: Uniplate,
158
    R: Rule<T, M>,
159
{
160
    use rand::seq::IteratorRandom;
161
    let mut rng = rand::rng();
162
    rs.choose(&mut rng).map(|(_, u)| u)
163
}
164

            
165
/// Selects the [`Update`] which results in the smallest subtree.
166
///
167
/// Subtree size is determined by maximum depth.
168
/// Among trees with the same depth, the first in the iterator order is selected.
169
///
170
/// See the module-level documentation for more information.
171
pub fn select_smallest_subtree<T, M, R>(
172
    _: &T,
173
    rs: &mut dyn Iterator<Item = (&R, Update<T, M>)>,
174
) -> Option<Update<T, M>>
175
where
176
    T: Uniplate,
177
    R: Rule<T, M>,
178
{
179
    rs.min_by_key(|(_, u)| {
180
        u.new_subtree.cata(Arc::new(|_, cs: VecDeque<i32>| {
181
            // Max subtree height + 1
182
            cs.iter().max().unwrap_or(&0) + 1
183
        }))
184
    })
185
    .map(|(_, u)| u)
186
}