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
4594312
pub(super) fn expression_ctx(
12
4594312
    root_expression: Expression,
13
4594312
) -> impl Iterator<Item = (Expression, Arc<dyn Fn(Expression) -> Expression>)> {
14
4594312
    ExpressionCtx {
15
4594312
        zipper: SubmodelZipper {
16
4594312
            inner: Zipper::new(root_expression),
17
4594312
        },
18
4594312
        done: false,
19
4594312
    }
20
4594312
}
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
89150658
    pub fn go_right(&mut self) -> Option<()> {
38
89150658
        self.inner.go_right()
39
89150658
    }
40

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

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

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

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

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

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

            
76
    #[doc(hidden)]
77
189584
    pub fn new(root_expression: Expression) -> Self {
78
189584
        SubmodelZipper {
79
189584
            inner: Zipper::new(root_expression),
80
189584
        }
81
189584
    }
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
87984298
    fn next(&mut self) -> Option<Self::Item> {
93
87984298
        if self.done {
94
4279118
            return None;
95
83705180
        }
96
83705180
        let node = self.zipper.focus().clone();
97
83705180
        let zipper = self.zipper.clone();
98

            
99
        #[allow(clippy::arc_with_non_send_sync)]
100
83705180
        let ctx = Arc::new(move |x| {
101
315194
            let mut zipper2 = zipper.clone();
102
315194
            *zipper2.focus_mut() = x;
103
315194
            zipper2.rebuild_root()
104
315194
        });
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
83705180
        if self.zipper.go_down().is_none() {
109
82892256
            while self.zipper.go_right().is_none() {
110
38824326
                if self.zipper.go_up().is_none() {
111
                    // at the top again, so this will be the last time we return a node
112
4288822
                    self.done = true;
113
4288822
                    break;
114
34535504
                };
115
            }
116
35348428
        }
117

            
118
83705180
        Some((node, ctx))
119
87984298
    }
120
}