conjure_core/rule_engine/
submodel_zipper.rs
1#![allow(dead_code)]
2use std::sync::Arc;
3
4use uniplate::zipper::Zipper;
5
6use crate::ast::{Expression, SubModel};
7
8pub(super) fn submodel_ctx(
12 m: SubModel,
13) -> impl Iterator<Item = (Expression, Arc<dyn Fn(Expression) -> SubModel>)> {
14 SubmodelCtx {
15 zipper: SubmodelZipper {
16 inner: Zipper::new(m.root().clone()),
17 },
18 submodel: m.clone(),
19 done: false,
20 }
21}
22
23#[derive(Clone)]
26struct SubmodelZipper {
27 inner: Zipper<Expression>,
28}
29
30impl SubmodelZipper {
31 fn go_left(&mut self) -> Option<()> {
32 self.inner.go_left()
33 }
34
35 fn go_right(&mut self) -> Option<()> {
36 self.inner.go_right()
37 }
38
39 fn go_up(&mut self) -> Option<()> {
40 self.inner.go_up()
41 }
42
43 fn rebuild_root(self) -> Expression {
44 self.inner.rebuild_root()
45 }
46
47 fn go_down(&mut self) -> Option<()> {
48 if matches!(
50 self.inner.focus(),
51 Expression::Scope(_, _) | Expression::Comprehension(_, _)
52 ) {
53 None
54 } else {
55 self.inner.go_down()
56 }
57 }
58
59 fn focus(&self) -> &Expression {
60 self.inner.focus()
61 }
62
63 fn focus_mut(&mut self) -> &mut Expression {
64 self.inner.focus_mut()
65 }
66}
67
68pub struct SubmodelCtx {
69 zipper: SubmodelZipper,
70 submodel: SubModel,
71 done: bool,
72}
73
74impl Iterator for SubmodelCtx {
75 type Item = (Expression, Arc<dyn Fn(Expression) -> SubModel>);
76
77 fn next(&mut self) -> Option<Self::Item> {
78 if self.done {
79 return None;
80 }
81 let node = self.zipper.focus().clone();
82 let submodel = self.submodel.clone();
83 let zipper = self.zipper.clone();
84
85 #[allow(clippy::arc_with_non_send_sync)]
86 let ctx = Arc::new(move |x| {
87 let mut zipper2 = zipper.clone();
88 *zipper2.focus_mut() = x;
89 let root = zipper2.rebuild_root();
90 let mut submodel2 = submodel.clone();
91 submodel2.replace_root(root);
92 submodel2
93 });
94
95 if self.zipper.go_down().is_none() {
98 while self.zipper.go_right().is_none() {
99 if self.zipper.go_up().is_none() {
100 self.done = true;
102 break;
103 };
104 }
105 }
106
107 Some((node, ctx))
108 }
109}