1
#![allow(dead_code)]
2
use std::sync::Arc;
3

            
4
use uniplate::zipper::Zipper;
5

            
6
use crate::ast::Expression;
7

            
8
/// Traverses expressions in a root expression tree, but not into nested scopes.
9
///
10
/// Same types and usage as `Biplate::contexts_bi`.
11
5076720
pub(super) fn expression_ctx(
12
5076720
    root_expression: Expression,
13
5076720
) -> impl Iterator<Item = (Expression, Arc<dyn Fn(Expression) -> Expression>)> {
14
5076720
    ExpressionCtx {
15
5076720
        zipper: SubmodelZipper {
16
5076720
            inner: Zipper::new(root_expression),
17
5076720
        },
18
5076720
        done: false,
19
5076720
    }
20
5076720
}
21

            
22
/// A zipper that traverses over the current expression tree and does not traverse into nested
23
/// scopes.
24
#[derive(Clone)]
25
#[doc(hidden)]
26
pub struct SubmodelZipper {
27
    inner: Zipper<Expression>,
28
}
29

            
30
impl SubmodelZipper {
31
    #[doc(hidden)]
32
    pub fn go_left(&mut self) -> Option<()> {
33
        self.inner.go_left()
34
    }
35

            
36
    #[doc(hidden)]
37
94983884
    pub fn go_right(&mut self) -> Option<()> {
38
94983884
        self.inner.go_right()
39
94983884
    }
40

            
41
    #[doc(hidden)]
42
45093628
    pub fn go_up(&mut self) -> Option<()> {
43
45093628
        self.inner.go_up()
44
45093628
    }
45

            
46
    #[doc(hidden)]
47
525384
    pub fn rebuild_root(self) -> Expression {
48
525384
        self.inner.rebuild_root()
49
525384
    }
50

            
51
    #[doc(hidden)]
52
95871320
    pub fn go_down(&mut self) -> Option<()> {
53
        // Do not enter comprehensions, which have their own local symbol table.
54
95871320
        if matches!(self.inner.focus(), Expression::Comprehension(_, _)) {
55
507868
            None
56
        } else {
57
95363452
            self.inner.go_down()
58
        }
59
95871320
    }
60

            
61
    #[doc(hidden)]
62
95680348
    pub fn focus(&self) -> &Expression {
63
95680348
        self.inner.focus()
64
95680348
    }
65

            
66
    #[doc(hidden)]
67
23292
    pub fn replace_focus(&mut self, new_focus: Expression) -> Expression {
68
23292
        self.inner.replace_focus(new_focus)
69
23292
    }
70

            
71
    #[doc(hidden)]
72
334412
    pub fn focus_mut(&mut self) -> &mut Expression {
73
334412
        self.inner.focus_mut()
74
334412
    }
75

            
76
    #[doc(hidden)]
77
190972
    pub fn new(root_expression: Expression) -> Self {
78
190972
        SubmodelZipper {
79
190972
            inner: Zipper::new(root_expression),
80
190972
        }
81
190972
    }
82
}
83

            
84
pub struct ExpressionCtx {
85
    zipper: SubmodelZipper,
86
    done: bool,
87
}
88

            
89
impl Iterator for ExpressionCtx {
90
    type Item = (Expression, Arc<dyn Fn(Expression) -> Expression>);
91

            
92
94209604
    fn next(&mut self) -> Option<Self::Item> {
93
94209604
        if self.done {
94
4742308
            return None;
95
89467296
        }
96
89467296
        let node = self.zipper.focus().clone();
97
89467296
        let zipper = self.zipper.clone();
98

            
99
        #[allow(clippy::arc_with_non_send_sync)]
100
89467296
        let ctx = Arc::new(move |x| {
101
334412
            let mut zipper2 = zipper.clone();
102
334412
            *zipper2.focus_mut() = x;
103
334412
            zipper2.rebuild_root()
104
334412
        });
105

            
106
        // prepare iterator for next element.
107
        // try moving down or right. if we can't move up the tree until we can move right.
108
89467296
        if self.zipper.go_down().is_none() {
109
88579860
            while self.zipper.go_right().is_none() {
110
42300764
                if self.zipper.go_up().is_none() {
111
                    // at the top again, so this will be the last time we return a node
112
4752376
                    self.done = true;
113
4752376
                    break;
114
37548388
                };
115
            }
116
38435824
        }
117

            
118
89467296
        Some((node, ctx))
119
94209604
    }
120
}