kodept_macros/default/
ast_formatter.rs

1use std::io::{Error, Write};
2use std::ops::Deref;
3
4use codespan_reporting::diagnostic::Severity;
5
6use kodept_ast::graph::{ChangeSet, AnyNode};
7use kodept_ast::utils::Execution;
8use kodept_ast::utils::Execution::Completed;
9use kodept_ast::visit_side::{VisitGuard, VisitSide};
10
11use crate::error::report::ReportMessage;
12use crate::Macro;
13use crate::traits::Context;
14
15pub struct ASTFormatter<W: Write> {
16    writer: W,
17    indent: usize,
18}
19
20pub struct IOError(Error);
21
22impl From<IOError> for ReportMessage {
23    fn from(value: IOError) -> Self {
24        Self::new(Severity::Bug, "IO000", value.0.to_string())
25    }
26}
27
28impl<W: Write> ASTFormatter<W> {
29    pub fn new(writer: W) -> Self {
30        Self { writer, indent: 0 }
31    }
32}
33
34impl<W: Write> Macro for ASTFormatter<W> {
35    type Error = IOError;
36    type Node = AnyNode;
37
38    fn transform(
39        &mut self,
40        guard: VisitGuard<Self::Node>,
41        _: &mut impl Context,
42    ) -> Execution<Self::Error, ChangeSet> {
43        let (node, side) = guard.allow_all();
44        let node_data = node.deref();
45        let f = &mut self.writer;
46
47        match side {
48            VisitSide::Entering => {
49                writeln!(f, "{}{:?} {{", "  ".repeat(self.indent), node_data).map_err(IOError)?;
50                self.indent += 1;
51            }
52            VisitSide::Leaf => {
53                writeln!(f, "{}{:?};", "  ".repeat(self.indent), node_data).map_err(IOError)?
54            }
55            VisitSide::Exiting => {
56                self.indent -= 1;
57                writeln!(f, "{}}}", "  ".repeat(self.indent)).map_err(IOError)?;
58            }
59        }
60
61        Completed(ChangeSet::new())
62    }
63}