use super::*;
pub trait TreeWalker: Sized {
fn apply_children(
&self,
op: &mut dyn FnMut(&Self) -> PolarsResult<VisitRecursion>,
) -> PolarsResult<VisitRecursion>;
fn map_children(self, op: &mut dyn FnMut(Self) -> PolarsResult<Self>) -> PolarsResult<Self>;
fn visit(&self, visitor: &mut dyn Visitor<Node = Self>) -> PolarsResult<VisitRecursion> {
match visitor.pre_visit(self)? {
VisitRecursion::Continue => {},
VisitRecursion::Skip => return Ok(VisitRecursion::Continue),
VisitRecursion::Stop => return Ok(VisitRecursion::Stop),
};
match self.apply_children(&mut |node| node.visit(visitor))? {
VisitRecursion::Continue | VisitRecursion::Skip => {},
VisitRecursion::Stop => return Ok(VisitRecursion::Stop),
}
visitor.post_visit(self)
}
fn rewrite(self, rewriter: &mut dyn RewritingVisitor<Node = Self>) -> PolarsResult<Self> {
let mutate_this_node = match rewriter.pre_visit(&self)? {
RewriteRecursion::MutateAndStop => return rewriter.mutate(self),
RewriteRecursion::Stop => return Ok(self),
RewriteRecursion::MutateAndContinue => true,
RewriteRecursion::NoMutateAndContinue => false,
};
let after_applied_children = self.map_children(&mut |node| node.rewrite(rewriter))?;
if mutate_this_node {
rewriter.mutate(after_applied_children)
} else {
Ok(after_applied_children)
}
}
}
pub trait Visitor {
type Node;
fn pre_visit(&mut self, _node: &Self::Node) -> PolarsResult<VisitRecursion> {
Ok(VisitRecursion::Continue)
}
fn post_visit(&mut self, _node: &Self::Node) -> PolarsResult<VisitRecursion> {
Ok(VisitRecursion::Continue)
}
}
pub trait RewritingVisitor {
type Node;
fn pre_visit(&mut self, _node: &Self::Node) -> PolarsResult<RewriteRecursion> {
Ok(RewriteRecursion::MutateAndContinue)
}
fn mutate(&mut self, node: Self::Node) -> PolarsResult<Self::Node>;
}