conjure_core/rule_engine/
submodel_zipper.rs1#![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!(self.inner.focus(), Expression::Scope(_, _)) {
49 None
50 } else {
51 self.inner.go_down()
52 }
53 }
54
55 fn focus(&self) -> &Expression {
56 self.inner.focus()
57 }
58
59 fn focus_mut(&mut self) -> &mut Expression {
60 self.inner.focus_mut()
61 }
62}
63
64pub struct SubmodelCtx {
65 zipper: SubmodelZipper,
66 submodel: SubModel,
67 done: bool,
68}
69
70impl Iterator for SubmodelCtx {
71 type Item = (Expression, Arc<dyn Fn(Expression) -> SubModel>);
72
73 fn next(&mut self) -> Option<Self::Item> {
74 if self.done {
75 return None;
76 }
77 let node = self.zipper.focus().clone();
78 let submodel = self.submodel.clone();
79 let zipper = self.zipper.clone();
80
81 #[allow(clippy::arc_with_non_send_sync)]
82 let ctx = Arc::new(move |x| {
83 let mut zipper2 = zipper.clone();
84 *zipper2.focus_mut() = x;
85 let root = zipper2.rebuild_root();
86 let mut submodel2 = submodel.clone();
87 submodel2.replace_root(root);
88 submodel2
89 });
90
91 if self.zipper.go_down().is_none() {
94 while self.zipper.go_right().is_none() {
95 if self.zipper.go_up().is_none() {
96 self.done = true;
98 break;
99 };
100 }
101 }
102
103 Some((node, ctx))
104 }
105}