ligen_core/generator/
visitor.rs

1//! Generator visitor module.
2
3use crate::ir::{Implementation, Function, Parameter, Type};
4use crate::generator::{Context, FileSet};
5
6/// Generic visitor type.
7#[derive(Debug, Clone)]
8pub struct Visitor<Parent, Current> {
9    /// Visitor's parent.
10    pub parent: Parent,
11    /// Currently visited.
12    pub current: Current
13}
14
15impl<Parent, Current> Visitor<Parent, Current> {
16    /// Creates a new Visitor.
17    pub fn new(parent: Parent, current: Current) -> Self {
18        Self { parent, current }
19    }
20
21    /// Creates a new child.
22    pub fn child<Child>(&self, current: Child) -> Visitor<Visitor<Parent, Current>, Child>
23    where Parent: Clone,
24          Current: Clone
25    {
26        let parent = self.clone();
27        Visitor { parent, current }
28    }
29}
30
31/// Implementation visitor.
32pub type ImplementationVisitor = Visitor<(), Implementation>;
33
34/// Function visitor.
35pub type FunctionVisitor = Visitor<ImplementationVisitor, Function>;
36
37/// Parameter visitor.
38pub type ParameterVisitor = Visitor<FunctionVisitor, Parameter>;
39
40impl FunctionVisitor {
41    /// Check if the function is a method.
42    // TODO: Use these rules https://doc.rust-lang.org/reference/items/associated-items.html#methods
43    pub fn is_method(&self) -> bool {
44        if let Some(input) = self.current.inputs.get(0) {
45            input.type_.path() == self.parent.current.self_.path() || input.type_ == Type::self_type()
46        } else {
47            false
48        }
49    }
50}
51
52/// File processor visitor.
53pub trait FileProcessorVisitor: Default {
54    /// Visitor's type.
55    type Visitor;
56
57    /// Processor executed while visiting the current element and before visiting its children.
58    fn process(&self, _context: &Context, _file_set: &mut FileSet, _visitor: &Self::Visitor) {}
59
60    /// Post-processor executed after visiting the current element and its children.
61    /// It has a special behavior for `ParameterVisitor`: It only executes if the `parameter` isn't
62    /// the last parameter, which is useful for writing separators.
63    fn post_process(&self, _context: &Context, _file_set: &mut FileSet, _visitor: &Self::Visitor) {}
64}