use crate::zipper::{Zipper, ZipperBi};
use super::{Biplate, Uniplate};
pub(super) struct ContextIter<T: Uniplate> {
zipper: Zipper<T>,
done: bool,
}
impl<T: Uniplate> ContextIter<T> {
pub(super) fn new(root: T) -> ContextIter<T> {
ContextIter {
zipper: Zipper::new(root),
done: false,
}
}
}
impl<T: Uniplate> Iterator for ContextIter<T> {
type Item = (T, Box<dyn Fn(T) -> T>);
fn next(&mut self) -> Option<Self::Item> {
if self.done {
return None;
};
let node = self.zipper.focus().clone();
let zipper1 = self.zipper.clone();
let hole_fn = Box::new(move |x| {
let mut zipper2 = zipper1.clone();
zipper2.replace_focus(x);
zipper2.rebuild_root()
});
if self.zipper.go_down().is_none() {
while self.zipper.go_right().is_none() {
if self.zipper.go_up().is_none() {
self.done = true;
break;
};
}
}
Some((node, hole_fn))
}
}
pub(super) struct ContextIterBi<T: Uniplate, U: Biplate<T>> {
zipper: Option<ZipperBi<T, U>>,
done: bool,
}
impl<T: Uniplate, U: Biplate<T>> ContextIterBi<T, U> {
pub(super) fn new(root: U) -> ContextIterBi<T, U> {
ContextIterBi {
zipper: ZipperBi::new(root),
done: false,
}
}
}
impl<T: Uniplate, U: Biplate<T>> Iterator for ContextIterBi<T, U> {
type Item = (T, Box<dyn Fn(T) -> U>);
fn next(&mut self) -> Option<Self::Item> {
if self.done {
return None;
};
let Some(zipper) = &mut self.zipper else {
return None;
};
let node = zipper.focus().clone();
let zipper1 = zipper.clone();
let hole_fn = Box::new(move |x| {
let mut zipper1 = zipper1.clone();
zipper1.replace_focus(x);
zipper1.rebuild_root()
});
if zipper.go_down().is_none() {
while zipper.go_right().is_none() {
if zipper.go_up().is_none() {
self.done = true;
break;
};
}
}
Some((node, hole_fn))
}
}