use std::{iter, ops::ControlFlow};
use crate::AlgebraicExpression;
pub trait Children<O> {
fn children(&self) -> Box<dyn Iterator<Item = &O> + '_>;
fn children_mut(&mut self) -> Box<dyn Iterator<Item = &mut O> + '_>;
}
pub trait AllChildren<O> {
fn all_children(&self) -> Box<dyn Iterator<Item = &O> + '_>;
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum VisitOrder {
Pre,
Post,
}
pub trait ExpressionVisitable<Expr> {
fn pre_visit_expressions_mut<F>(&mut self, f: &mut F)
where
F: FnMut(&mut Expr),
{
let _ = self.visit_expressions_mut(
&mut move |e| {
f(e);
ControlFlow::Continue::<()>(())
},
VisitOrder::Pre,
);
}
fn post_visit_expressions_mut<F>(&mut self, f: &mut F)
where
F: FnMut(&mut Expr),
{
let _ = self.visit_expressions_mut(
&mut move |e| {
f(e);
ControlFlow::Continue::<()>(())
},
VisitOrder::Post,
);
}
fn visit_expressions<F, B>(&self, f: &mut F, order: VisitOrder) -> ControlFlow<B>
where
F: FnMut(&Expr) -> ControlFlow<B>;
fn visit_expressions_mut<F, B>(&mut self, f: &mut F, order: VisitOrder) -> ControlFlow<B>
where
F: FnMut(&mut Expr) -> ControlFlow<B>;
}
impl<Expr: ExpressionVisitable<Expr>, C: Children<Expr>> ExpressionVisitable<Expr> for C {
fn visit_expressions_mut<F, B>(&mut self, f: &mut F, o: VisitOrder) -> ControlFlow<B>
where
F: FnMut(&mut Expr) -> ControlFlow<B>,
{
self.children_mut()
.try_for_each(|child| child.visit_expressions_mut(f, o))
}
fn visit_expressions<F, B>(&self, f: &mut F, o: VisitOrder) -> ControlFlow<B>
where
F: FnMut(&Expr) -> ControlFlow<B>,
{
self.children()
.try_for_each(|child| child.visit_expressions(f, o))
}
}
impl<Expr: AllChildren<Expr>, C: Children<Expr>> AllChildren<Expr> for C {
fn all_children(&self) -> Box<dyn Iterator<Item = &Expr> + '_> {
Box::new(self.children().flat_map(|e| e.all_children()))
}
}
impl<T, R> ExpressionVisitable<AlgebraicExpression<T, R>> for AlgebraicExpression<T, R> {
fn visit_expressions_mut<F, B>(&mut self, f: &mut F, o: VisitOrder) -> ControlFlow<B>
where
F: FnMut(&mut AlgebraicExpression<T, R>) -> ControlFlow<B>,
{
if o == VisitOrder::Pre {
f(self)?;
}
self.children_mut()
.try_for_each(|e| e.visit_expressions_mut(f, o))?;
if o == VisitOrder::Post {
f(self)?;
}
ControlFlow::Continue(())
}
fn visit_expressions<F, B>(&self, f: &mut F, o: VisitOrder) -> ControlFlow<B>
where
F: FnMut(&AlgebraicExpression<T, R>) -> ControlFlow<B>,
{
if o == VisitOrder::Pre {
f(self)?;
}
self.children()
.try_for_each(|e| e.visit_expressions(f, o))?;
if o == VisitOrder::Post {
f(self)?;
}
ControlFlow::Continue(())
}
}
impl<T, R> AllChildren<AlgebraicExpression<T, R>> for AlgebraicExpression<T, R> {
fn all_children(&self) -> Box<dyn Iterator<Item = &AlgebraicExpression<T, R>> + '_> {
Box::new(iter::once(self).chain(self.children().flat_map(|e| e.all_children())))
}
}