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

            
4
use uniplate::zipper::Zipper;
5

            
6
use crate::ast::{Expression, SubModel};
7

            
8
/// Traverses expressions in this sub-model, but not into inner sub-models.
9
///
10
/// Same types and usage as `Biplate::contexts_bi`.
11
137196
pub(super) fn submodel_ctx(
12
137196
    m: SubModel,
13
137196
) -> impl Iterator<Item = (Expression, Arc<dyn Fn(Expression) -> SubModel>)> {
14
137196
    SubmodelCtx {
15
137196
        zipper: SubmodelZipper {
16
137196
            inner: Zipper::new(m.root().clone()),
17
137196
        },
18
137196
        submodel: m.clone(),
19
137196
        done: false,
20
137196
    }
21
137196
}
22

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

            
30
impl SubmodelZipper {
31
    fn go_left(&mut self) -> Option<()> {
32
        self.inner.go_left()
33
    }
34

            
35
4527540
    fn go_right(&mut self) -> Option<()> {
36
4527540
        self.inner.go_right()
37
4527540
    }
38

            
39
2384478
    fn go_up(&mut self) -> Option<()> {
40
2384478
        self.inner.go_up()
41
2384478
    }
42

            
43
17784
    fn rebuild_root(self) -> Expression {
44
17784
        self.inner.rebuild_root()
45
17784
    }
46

            
47
4583628
    fn go_down(&mut self) -> Option<()> {
48
4583628
        if matches!(self.inner.focus(), Expression::Scope(_, _)) {
49
            None
50
        } else {
51
4583628
            self.inner.go_down()
52
        }
53
4583628
    }
54

            
55
4583628
    fn focus(&self) -> &Expression {
56
4583628
        self.inner.focus()
57
4583628
    }
58

            
59
17784
    fn focus_mut(&mut self) -> &mut Expression {
60
17784
        self.inner.focus_mut()
61
17784
    }
62
}
63

            
64
pub struct SubmodelCtx {
65
    zipper: SubmodelZipper,
66
    submodel: SubModel,
67
    done: bool,
68
}
69

            
70
impl Iterator for SubmodelCtx {
71
    type Item = (Expression, Arc<dyn Fn(Expression) -> SubModel>);
72

            
73
4703040
    fn next(&mut self) -> Option<Self::Item> {
74
4703040
        if self.done {
75
119412
            return None;
76
4583628
        }
77
4583628
        let node = self.zipper.focus().clone();
78
4583628
        let submodel = self.submodel.clone();
79
4583628
        let zipper = self.zipper.clone();
80
4583628

            
81
4583628
        #[allow(clippy::arc_with_non_send_sync)]
82
4583628
        let ctx = Arc::new(move |x| {
83
17784
            let mut zipper2 = zipper.clone();
84
17784
            *zipper2.focus_mut() = x;
85
17784
            let root = zipper2.rebuild_root();
86
17784
            let mut submodel2 = submodel.clone();
87
17784
            submodel2.replace_root(root);
88
17784
            submodel2
89
4583628
        });
90
4583628

            
91
4583628
        // prepare iterator for next element.
92
4583628
        // try moving down or right. if we can't move up the tree until we can move right.
93
4583628
        if self.zipper.go_down().is_none() {
94
4527540
            while self.zipper.go_right().is_none() {
95
2384478
                if self.zipper.go_up().is_none() {
96
                    // at the top again, so this will be the last time we return a node
97
119448
                    self.done = true;
98
119448
                    break;
99
2265030
                };
100
            }
101
2321118
        }
102

            
103
4583628
        Some((node, ctx))
104
4703040
    }
105
}