pipeline_script/postprocessor/
mod.rs1use crate::ast::NodeTrait;
2use std::collections::VecDeque;
3
4pub mod function_printer;
5mod id;
6pub mod module_merger;
7pub mod printer;
8pub mod r#type;
9
10pub enum VisitResult {
11 Continue,
12 Break,
14 #[allow(unused)]
16 Skip,
17}
18#[derive(PartialEq)]
19pub enum Stage {
20 BeforeTypeInfer,
21 AfterTypeInfer,
22}
23pub trait Visitor {
24 fn stage(&self) -> Stage;
25 fn match_id(&self, id: &str) -> bool;
26 fn visit(&self, node: &mut (impl NodeTrait + ?Sized)) -> crate::postprocessor::VisitResult
28 where
29 Self: Sized;
30}
31
32pub trait DynVisitor: Visitor {
33 fn dyn_visit(&self, node: &mut dyn NodeTrait) -> crate::postprocessor::VisitResult;
34}
35
36impl<T: Visitor> DynVisitor for T {
37 fn dyn_visit(&self, node: &mut dyn NodeTrait) -> crate::postprocessor::VisitResult {
38 self.visit(node)
39 }
40}
41
42pub fn run_visitor(node: &mut dyn NodeTrait, visitor: &dyn DynVisitor) {
43 let mut queue: VecDeque<&mut dyn NodeTrait> = VecDeque::new();
44 queue.push_back(node);
45 while !queue.is_empty() {
46 let mut skip = false;
47 let node = queue.pop_front().unwrap();
48 if visitor.match_id(node.get_id()) {
49 let result = visitor.dyn_visit(node);
50 if let VisitResult::Break = result {
51 break;
52 }
53 if let VisitResult::Skip = result {
54 skip = true;
55 }
56 }
57 if skip {
58 continue;
59 }
60 for i in node.get_mut_children() {
61 queue.push_back(i);
62 }
63 }
64}