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
1232274
    fn set_dirty_from(&mut self, level: usize) {
19
1232274
        self.dirty_from = level;
20
1232274
    }
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
2724800
    fn is_dirty(&self, level: usize) -> bool {
25
2724800
        level >= self.dirty_from
26
2724800
    }
27
}
28

            
29
impl EngineNodeState {
30
83670
    fn new<T: Uniplate>(_: &T) -> Self {
31
83670
        Self {
32
83670
            dirty_from: 0,
33
83670
            pass_through_until: None,
34
83670
        }
35
83670
    }
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
35
    pub fn new(
59
35
        tree: T,
60
35
        meta: M,
61
35
        down_predicate: fn(&T) -> bool,
62
35
        event_handlers: &'a EventHandlers<T, M, R>,
63
35
        cache: &'a mut C,
64
35
    ) -> Self {
65
35
        EngineZipper {
66
35
            inner: TaggedZipper::new(tree, EngineNodeState::new),
67
35
            event_handlers,
68
35
            down_predicate,
69
35
            cache,
70
35
            meta,
71
35
        }
72
35
    }
73

            
74
    /// Returns a reference to the currently focused node.
75
1227755
    pub fn focus(&self) -> &T {
76
1227755
        self.inner.focus()
77
1227755
    }
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
1230657
    pub fn focus_and_meta(&mut self) -> (&T, &mut M) {
82
1230657
        (self.inner.focus(), &mut self.meta)
83
1230657
    }
84

            
85
    /// Replaces the currently focused node with `replacement`.
86
1483
    pub fn replace_focus(&mut self, replacement: T) {
87
1483
        self.inner.replace_focus(replacement);
88
1483
    }
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
1226276
    pub fn go_next_dirty(&mut self, level: usize) -> Option<()> {
95
1226276
        if self.inner.tag().is_dirty(level) {
96
11548
            let pass_through = self.inner.tag().pass_through_until;
97
104
            match pass_through {
98
104
                Some(n) if level <= n => {
99
104
                    if level == n {
100
104
                        self.inner.tag_mut().pass_through_until = None;
101
104
                    }
102
                    // Fall through to descend past this node
103
                }
104
                _ => {
105
11444
                    return Some(());
106
                }
107
            }
108
1214728
        }
109

            
110
1214832
        self.go_down()
111
1214832
            .and_then(|_| {
112
                // go right until we find a dirty child, if it exists.
113
                loop {
114
748200
                    if self.inner.tag().is_dirty(level) {
115
641592
                        return Some(());
116
106608
                    } else if self.go_right().is_none() {
117
                        // all children are clean
118
7972
                        self.go_up();
119
7972
                        return None;
120
98636
                    }
121
                }
122
649564
            })
123
1214832
            .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
1383113
                    if self.go_right().is_some() {
128
740870
                        if self.inner.tag().is_dirty(level) {
129
563078
                            return Some(());
130
177792
                        }
131
642243
                    } else if self.go_up().is_none() {
132
                        // Reached the root without finding a dirty node
133
10162
                        return None;
134
632081
                    }
135
                }
136
573240
            })
137
1226276
    }
138

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

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

            
168
1489721
    fn go_right(&mut self) -> Option<()> {
169
1489721
        if !self.inner.zipper().has_right() {
170
650215
            return None;
171
839506
        }
172
839506
        self.event_handlers
173
839506
            .trigger_before_right(self.inner.focus(), &mut self.meta);
174
839506
        self.inner.go_right().expect("checked above");
175
839506
        trace!("Go right");
176
839506
        self.event_handlers
177
839506
            .trigger_after_right(self.inner.focus(), &mut self.meta);
178
839506
        Some(())
179
1489721
    }
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
1216097
    pub fn trigger_cache_miss(&mut self) {
189
1216097
        self.event_handlers
190
1216097
            .trigger_on_cache_miss(self.inner.focus(), &mut self.meta);
191
1216097
    }
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
1225623
    pub fn set_dirty_from(&mut self, level: usize) {
196
1225623
        trace!("Setting level = {}", level);
197
1225623
        self.inner.tag_mut().set_dirty_from(level);
198
1225623
    }
199

            
200
    /// Mark this node as pass-through
201
1334
    pub fn set_pass_through(&mut self, level: usize) {
202
1334
        self.inner.tag_mut().pass_through_until = Some(level);
203
1334
    }
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
1385
    pub fn mark_dirty_to_root(&mut self, level: usize) {
208
1385
        trace!("Marking Dirty to Root");
209
1385
        self.set_dirty_from(0);
210
1385
        self.cache.invalidate_node(self.inner.focus());
211
10895
        while self.inner.zipper().has_up() {
212
9510
            self.event_handlers
213
9510
                .trigger_before_up(self.inner.focus(), &mut self.meta);
214
9510
            self.inner.go_up().expect("checked above");
215
9510
            self.set_dirty_from(0);
216
9510
            self.cache.invalidate_node(self.inner.focus());
217
9510
            self.cache.pop_and_map_ancestor(self.inner.focus(), level);
218
9510
            trace!("Go up (mark dirty)");
219
9510
            self.event_handlers
220
9510
                .trigger_after_up(self.inner.focus(), &mut self.meta);
221
        }
222
1385
    }
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
34
    fn from(val: EngineZipper<'_, T, M, R, C>) -> Self {
232
34
        let meta = val.meta;
233
34
        let tree = val.inner.rebuild_root();
234
34
        (tree, meta)
235
34
    }
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
39220
    pub fn new(
259
39220
        tree: T,
260
39220
        meta: M,
261
39220
        down_predicate: fn(&T) -> bool,
262
39220
        event_handlers: &'a EventHandlers<T, M, R>,
263
39220
        cache: &'a mut C,
264
39220
    ) -> Self {
265
39220
        NaiveZipper {
266
39220
            inner: Zipper::new(tree),
267
39220
            event_handlers,
268
39220
            down_predicate,
269
39220
            cache,
270
39220
            meta,
271
39220
        }
272
39220
    }
273

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

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

            
284
    /// Replaces the currently focused node with `replacement`.
285
315840
    pub fn replace_focus(&mut self, replacement: T) {
286
315840
        self.inner.replace_focus(replacement);
287
315840
    }
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
94285220
    pub fn trigger_cache_miss(&mut self) {
297
94285220
        self.event_handlers
298
94285220
            .trigger_on_cache_miss(self.inner.focus(), &mut self.meta);
299
94285220
    }
300

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

            
306
93995800
    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
93995800
        if (self.down_predicate)(self.inner.focus()) {
310
93995800
            self.cache.push_ancestor(self.inner.focus());
311
93995800
            if self.inner.go_down().is_some() {
312
38004920
                return Some(());
313
55990880
            }
314
55990880
            self.cache.pop_ancestor();
315
        }
316
55990880
        if self.inner.go_right().is_some() {
317
39117380
            return Some(());
318
16873500
        }
319
39755620
        while self.inner.go_up().is_some() {
320
37377600
            self.cache.pop_ancestor();
321
37377600
            if self.inner.go_right().is_some() {
322
14495480
                return Some(());
323
22882120
            }
324
        }
325
2378020
        None
326
93995800
    }
327

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