1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#![deny(clippy::all)]
#![warn(clippy::pedantic)]

pub mod std_impls;

use downcast_rs::{impl_downcast, Downcast};

pub use another_visitor_macros::Visitable;
pub use another_visitor_macros::VisitableMut;
pub use another_visitor_macros::Visitor;
pub use another_visitor_macros::VisitorMut;

pub trait Visitable: Downcast {
    fn children(&self) -> Vec<&dyn Visitable>;
}
impl_downcast!(Visitable);

pub trait VisitableMut: Downcast {
    fn children_mut(&mut self) -> Vec<&mut dyn VisitableMut>;
}
impl_downcast!(VisitableMut);

pub trait VisitorHelper {
    type Output: Default;

    #[allow(unused_variables)]
    fn aggregate(&mut self, a: Self::Output, b: Self::Output) -> Self::Output {
        b
    }
}

pub trait Visitor: VisitorHelper {
    fn visit(&mut self, v: &dyn Visitable) -> Self::Output;

    fn visit_children(&mut self, v: &dyn Visitable) -> Self::Output {
        let mut res = Self::Output::default();
        let ch = v.children();
        for ele in ch {
            let v = self.visit(ele);
            res = self.aggregate(res, v);
        }
        res
    }
}

pub trait VisitorMut: VisitorHelper {
    fn visit(&mut self, v: &mut dyn VisitableMut) -> Self::Output;

    fn visit_children(&mut self, v: &mut dyn VisitableMut) -> Self::Output {
        let mut res = Self::Output::default();
        for ele in v.children_mut() {
            let v = self.visit(ele);
            res = self.aggregate(res, v);
        }
        res
    }
}