kodept_macros/default/
ast_formatter.rs1use 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}