1
//! Define the EngineNodes and the EngineZipper
2

            
3
use tracing::{instrument, trace};
4
use uniplate::{Uniplate, tagged_zipper::TaggedZipper, zipper::Zipper};
5

            
6
use crate::{cache::RewriteCache, events::EventHandlers, rule::Rule};
7

            
8
#[derive(Debug, Clone)]
9
pub(crate) struct EngineNodeState {
10
    /// Rule groups with lower indices have already been applied without change.
11
    /// For a level `n`, a state is 'dirty' if and only if `n >= dirty_from`.
12
    dirty_from: usize,
13
    pass_through_until: Option<usize>,
14
}
15

            
16
impl EngineNodeState {
17
    /// Marks the state as dirty for anything >= `level`.
18
2400828
    fn set_dirty_from(&mut self, level: usize) {
19
2400828
        self.dirty_from = level;
20
2400828
    }
21

            
22
    /// For a level `n`, a state is "dirty" if and only if `n >= dirty_from`.
23
    /// That is, all rules groups before `n` have been applied without change.
24
5337640
    fn is_dirty(&self, level: usize) -> bool {
25
5337640
        level >= self.dirty_from
26
5337640
    }
27
}
28

            
29
impl EngineNodeState {
30
163436
    fn new<T: Uniplate>(_: &T) -> Self {
31
163436
        Self {
32
163436
            dirty_from: 0,
33
163436
            pass_through_until: None,
34
163436
        }
35
163436
    }
36
}
37

            
38
/// A Zipper with optimisations for tree transformation.
39
pub(crate) struct EngineZipper<'a, T, M, R, C>
40
where
41
    T: Uniplate,
42
    R: Rule<T, M>,
43
    C: RewriteCache<T>,
44
{
45
    inner: TaggedZipper<T, EngineNodeState, fn(&T) -> EngineNodeState>,
46
    event_handlers: &'a EventHandlers<T, M, R>,
47
    down_predicate: fn(&T) -> bool,
48
    pub(crate) cache: &'a mut C,
49
    pub(crate) meta: M,
50
}
51

            
52
impl<'a, T, M, R, C> EngineZipper<'a, T, M, R, C>
53
where
54
    T: Uniplate,
55
    R: Rule<T, M>,
56
    C: RewriteCache<T>,
57
{
58
45
    pub fn new(
59
45
        tree: T,
60
45
        meta: M,
61
45
        down_predicate: fn(&T) -> bool,
62
45
        event_handlers: &'a EventHandlers<T, M, R>,
63
45
        cache: &'a mut C,
64
45
    ) -> Self {
65
45
        EngineZipper {
66
45
            inner: TaggedZipper::new(tree, EngineNodeState::new),
67
45
            event_handlers,
68
45
            down_predicate,
69
45
            cache,
70
45
            meta,
71
45
        }
72
45
    }
73

            
74
    /// Returns a reference to the currently focused node.
75
2398389
    pub fn focus(&self) -> &T {
76
2398389
        self.inner.focus()
77
2398389
    }
78

            
79
    /// Returns a reference to the focused node and a mutable reference to the metadata.
80
    /// This avoids borrow conflicts when both are needed simultaneously.
81
2404067
    pub fn focus_and_meta(&mut self) -> (&T, &mut M) {
82
2404067
        (self.inner.focus(), &mut self.meta)
83
2404067
    }
84

            
85
    /// Replaces the currently focused node with `replacement`.
86
2871
    pub fn replace_focus(&mut self, replacement: T) {
87
2871
        self.inner.replace_focus(replacement);
88
2871
    }
89

            
90
    /// Go to the next node in the tree which is dirty for the given level.
91
    /// That node may be the current one if it is dirty.
92
    /// If no such node exists, go to the root and return `None`.
93
    #[instrument(skip(self))]
94
2395474
    pub fn go_next_dirty(&mut self, level: usize) -> Option<()> {
95
2395474
        if self.inner.tag().is_dirty(level) {
96
22948
            let pass_through = self.inner.tag().pass_through_until;
97
168
            match pass_through {
98
168
                Some(n) if level <= n => {
99
168
                    if level == n {
100
168
                        self.inner.tag_mut().pass_through_until = None;
101
168
                    }
102
                    // Fall through to descend past this node
103
                }
104
                _ => {
105
22780
                    return Some(());
106
                }
107
            }
108
2372526
        }
109

            
110
2372694
        self.go_down()
111
2372694
            .and_then(|_| {
112
                // go right until we find a dirty child, if it exists.
113
                loop {
114
1469486
                    if self.inner.tag().is_dirty(level) {
115
1251340
                        return Some(());
116
218146
                    } else if self.go_right().is_none() {
117
                        // all children are clean
118
16500
                        self.go_up();
119
16500
                        return None;
120
201646
                    }
121
                }
122
1267840
            })
123
2372694
            .or_else(|| {
124
                // Neither this node, nor any of its children are dirty
125
                // Go right then up until we find a dirty node or reach the root
126
                loop {
127
2715861
                    if self.go_right().is_some() {
128
1463226
                        if self.inner.tag().is_dirty(level) {
129
1101082
                            return Some(());
130
362144
                        }
131
1252635
                    } else if self.go_up().is_none() {
132
                        // Reached the root without finding a dirty node
133
20272
                        return None;
134
1232363
                    }
135
                }
136
1121354
            })
137
2395474
    }
138

            
139
2372694
    fn go_down(&mut self) -> Option<()> {
140
2372694
        if !(self.down_predicate)(self.inner.focus()) {
141
            return None;
142
2372694
        }
143
2372694
        self.cache.push_ancestor(self.inner.focus());
144
2372694
        if self.inner.go_down().is_none() {
145
1104854
            self.cache.pop_ancestor(); // undo speculative push
146
1104854
            return None;
147
1267840
        }
148
1267840
        trace!("Go down");
149
1267840
        self.event_handlers
150
1267840
            .trigger_after_down(self.inner.focus(), &mut self.meta);
151
1267840
        Some(())
152
2372694
    }
153

            
154
1269135
    fn go_up(&mut self) -> Option<()> {
155
1269135
        if !self.inner.zipper().has_up() {
156
20272
            return None;
157
1248863
        }
158
1248863
        self.event_handlers
159
1248863
            .trigger_before_up(self.inner.focus(), &mut self.meta);
160
1248863
        self.inner.go_up().expect("checked above");
161
1248863
        self.cache.pop_ancestor();
162
1248863
        trace!("Go up");
163
1248863
        self.event_handlers
164
1248863
            .trigger_after_up(self.inner.focus(), &mut self.meta);
165
1248863
        Some(())
166
1269135
    }
167

            
168
2934007
    fn go_right(&mut self) -> Option<()> {
169
2934007
        if !self.inner.zipper().has_right() {
170
1269135
            return None;
171
1664872
        }
172
1664872
        self.event_handlers
173
1664872
            .trigger_before_right(self.inner.focus(), &mut self.meta);
174
1664872
        self.inner.go_right().expect("checked above");
175
1664872
        trace!("Go right");
176
1664872
        self.event_handlers
177
1664872
            .trigger_after_right(self.inner.focus(), &mut self.meta);
178
1664872
        Some(())
179
2934007
    }
180

            
181
    /// Trigger cache hit event handlers.
182
17
    pub fn trigger_cache_hit(&mut self) {
183
17
        self.event_handlers
184
17
            .trigger_on_cache_hit(self.inner.focus(), &mut self.meta);
185
17
    }
186

            
187
    /// Trigger cache miss event handlers.
188
2375185
    pub fn trigger_cache_miss(&mut self) {
189
2375185
        self.event_handlers
190
2375185
            .trigger_on_cache_miss(self.inner.focus(), &mut self.meta);
191
2375185
    }
192

            
193
    /// Mark the current focus as visited at the given level.
194
    /// Calling `go_next_dirty` with the same level will no longer yield this node.
195
2394177
    pub fn set_dirty_from(&mut self, level: usize) {
196
2394177
        trace!("Setting level = {}", level);
197
2394177
        self.inner.tag_mut().set_dirty_from(level);
198
2394177
    }
199

            
200
    /// Mark this node as pass-through
201
2624
    pub fn set_pass_through(&mut self, level: usize) {
202
2624
        self.inner.tag_mut().pass_through_until = Some(level);
203
2624
    }
204

            
205
    /// Mark ancestors as dirty for all levels, and return to the root.
206
    /// Pops ancestor hashes and inserts old→new ancestor mappings into the cache.
207
2675
    pub fn mark_dirty_to_root(&mut self, level: usize) {
208
2675
        trace!("Marking Dirty to Root");
209
2675
        self.set_dirty_from(0);
210
2675
        self.cache.invalidate_node(self.inner.focus());
211
21651
        while self.inner.zipper().has_up() {
212
18976
            self.event_handlers
213
18976
                .trigger_before_up(self.inner.focus(), &mut self.meta);
214
18976
            self.inner.go_up().expect("checked above");
215
18976
            self.set_dirty_from(0);
216
18976
            self.cache.invalidate_node(self.inner.focus());
217
18976
            self.cache.pop_and_map_ancestor(self.inner.focus(), level);
218
18976
            trace!("Go up (mark dirty)");
219
18976
            self.event_handlers
220
18976
                .trigger_after_up(self.inner.focus(), &mut self.meta);
221
        }
222
2675
    }
223
}
224

            
225
impl<T, M, R, C> From<EngineZipper<'_, T, M, R, C>> for (T, M)
226
where
227
    T: Uniplate,
228
    R: Rule<T, M>,
229
    C: RewriteCache<T>,
230
{
231
44
    fn from(val: EngineZipper<'_, T, M, R, C>) -> Self {
232
44
        let meta = val.meta;
233
44
        let tree = val.inner.rebuild_root();
234
44
        (tree, meta)
235
44
    }
236
}
237

            
238
/// A Naive Zipper. For testing, debugging and benching
239
pub(crate) struct NaiveZipper<'a, T, M, R, C>
240
where
241
    T: Uniplate,
242
    R: Rule<T, M>,
243
    C: RewriteCache<T>,
244
{
245
    inner: Zipper<T>,
246
    event_handlers: &'a EventHandlers<T, M, R>,
247
    down_predicate: fn(&T) -> bool,
248
    pub(crate) cache: &'a mut C,
249
    pub(crate) meta: M,
250
}
251

            
252
impl<'a, T, M, R, C> NaiveZipper<'a, T, M, R, C>
253
where
254
    T: Uniplate,
255
    R: Rule<T, M>,
256
    C: RewriteCache<T>,
257
{
258
40200
    pub fn new(
259
40200
        tree: T,
260
40200
        meta: M,
261
40200
        down_predicate: fn(&T) -> bool,
262
40200
        event_handlers: &'a EventHandlers<T, M, R>,
263
40200
        cache: &'a mut C,
264
40200
    ) -> Self {
265
40200
        NaiveZipper {
266
40200
            inner: Zipper::new(tree),
267
40200
            event_handlers,
268
40200
            down_predicate,
269
40200
            cache,
270
40200
            meta,
271
40200
        }
272
40200
    }
273

            
274
    /// Returns a reference to the currently focused node.
275
96098200
    pub fn focus(&self) -> &T {
276
96098200
        self.inner.focus()
277
96098200
    }
278

            
279
    /// Returns a reference to the focused node and a mutable reference to the metadata.
280
96693280
    pub fn focus_and_meta(&mut self) -> (&T, &mut M) {
281
96693280
        (self.inner.focus(), &mut self.meta)
282
96693280
    }
283

            
284
    /// Replaces the currently focused node with `replacement`.
285
325480
    pub fn replace_focus(&mut self, replacement: T) {
286
325480
        self.inner.replace_focus(replacement);
287
325480
    }
288

            
289
    /// Trigger cache hit event handlers.
290
    pub fn trigger_cache_hit(&mut self) {
291
        self.event_handlers
292
            .trigger_on_cache_hit(self.inner.focus(), &mut self.meta);
293
    }
294

            
295
    /// Trigger cache miss event handlers.
296
96098200
    pub fn trigger_cache_miss(&mut self) {
297
96098200
        self.event_handlers
298
96098200
            .trigger_on_cache_miss(self.inner.focus(), &mut self.meta);
299
96098200
    }
300

            
301
    /// Consumes the zipper and returns the reconstructed root and metadata.
302
40200
    pub fn into_parts(self) -> (T, M) {
303
40200
        (self.inner.rebuild_root(), self.meta)
304
40200
    }
305

            
306
95800660
    pub fn get_next(&mut self) -> Option<()> {
307
        // Try going down — speculative push, undo on failure
308
        // Do not descend if the down predicate rejects this node.
309
95800660
        if (self.down_predicate)(self.inner.focus()) {
310
95800660
            self.cache.push_ancestor(self.inner.focus());
311
95800660
            if self.inner.go_down().is_some() {
312
39323900
                return Some(());
313
56476760
            }
314
56476760
            self.cache.pop_ancestor();
315
        }
316
56476760
        if self.inner.go_right().is_some() {
317
39149300
            return Some(());
318
17327460
        }
319
41094480
        while self.inner.go_up().is_some() {
320
38655640
            self.cache.pop_ancestor();
321
38655640
            if self.inner.go_right().is_some() {
322
14888620
                return Some(());
323
23767020
            }
324
        }
325
2438840
        None
326
95800660
    }
327

            
328
    /// Walk back to root, inserting ancestor mappings at the given level.
329
297540
    pub fn map_ancestors_to_root(&mut self, level: usize) {
330
965800
        while self.inner.has_up() {
331
668260
            self.event_handlers
332
668260
                .trigger_before_up(self.inner.focus(), &mut self.meta);
333
668260
            self.inner.go_up().expect("checked above");
334
668260
            self.cache.invalidate_node(self.inner.focus());
335
668260
            self.cache.pop_and_map_ancestor(self.inner.focus(), level);
336
668260
            trace!("Go up (map ancestor)");
337
668260
            self.event_handlers
338
668260
                .trigger_after_up(self.inner.focus(), &mut self.meta);
339
        }
340
297540
    }
341
}