use super::PassAction;
use boa_ast::{
visitor::{VisitWith, VisitorMut},
Expression,
};
use std::{convert::Infallible, ops::ControlFlow};
pub(crate) struct Walker<F>
where
F: FnMut(&mut Expression) -> PassAction<Expression>,
{
f: F,
changed: bool,
}
impl<F> Walker<F>
where
F: FnMut(&mut Expression) -> PassAction<Expression>,
{
pub(crate) const fn new(f: F) -> Self {
Self { f, changed: false }
}
pub(crate) const fn changed(&self) -> bool {
self.changed
}
pub(crate) fn walk_expression_postorder(&mut self, expr: &mut Expression) {
self.visit_expression_mut(expr);
}
}
impl<'ast, F> VisitorMut<'ast> for Walker<F>
where
F: FnMut(&mut Expression) -> PassAction<Expression>,
{
type BreakTy = Infallible;
fn visit_expression_mut(&mut self, expr: &'ast mut Expression) -> ControlFlow<Self::BreakTy> {
expr.visit_with_mut(self);
match (self.f)(expr) {
PassAction::Keep => {}
PassAction::Modified => self.changed = true,
PassAction::Replace(new) => {
*expr = new;
self.changed = true;
}
}
ControlFlow::Continue(())
}
}