microcad_lang_base/
code_display.rs1#[derive(derive_more::Deref, derive_more::DerefMut)]
6pub struct CodeFormatContext<'a> {
7 pub depth: usize,
9
10 #[deref]
12 #[deref_mut]
13 pub f: &'a mut dyn std::fmt::Write,
14}
15
16impl<'a> CodeFormatContext<'a> {
17 pub fn new(f: &'a mut dyn std::fmt::Write) -> Self {
19 Self { depth: 0, f }
20 }
21
22 pub fn indent(&mut self) -> std::fmt::Result {
24 let indent = self.depth * 4;
25 write!(self, "{:indent$}", "")
26 }
27
28 pub fn nest<F>(&mut self, f: F) -> std::fmt::Result
30 where
31 F: FnOnce(&mut Self) -> std::fmt::Result,
32 {
33 self.depth += 1;
34 let result = f(self);
35 self.depth -= 1;
36 result
37 }
38}
39
40pub trait CodeDisplay<'a, Context = CodeFormatContext<'a>> {
42 fn code_display(&self, f: &mut Context) -> std::fmt::Result;
44}
45
46impl<'a, T> CodeDisplay<'a> for T
48where
49 T: std::fmt::Display,
50{
51 fn code_display(&self, ctx: &mut CodeFormatContext) -> std::fmt::Result {
52 write!(ctx, "{self}")
53 }
54}
55
56pub struct CodeStack<'a, T>(pub &'a [T]);
58
59pub struct CodeList<'a, T>(pub &'a [T]);
61
62impl<'a, 'b, T> CodeDisplay<'a> for CodeList<'b, T>
63where
64 T: CodeDisplay<'a>,
65{
66 fn code_display(&self, f: &mut CodeFormatContext<'a>) -> std::fmt::Result {
67 self.0.iter().try_for_each(|item| {
68 item.code_display(f)?;
69 write!(f, ", ")
70 })
71 }
72}
73
74impl<'a, 'b, T> CodeDisplay<'a> for CodeStack<'b, T>
75where
76 T: CodeDisplay<'a>,
77{
78 fn code_display(&self, f: &mut CodeFormatContext<'a>) -> std::fmt::Result {
79 self.0.iter().try_for_each(|item| {
80 item.code_display(f)?;
81 writeln!(f)
82 })
83 }
84}
85
86#[macro_export]
88macro_rules! code_display {
89 ($f:expr => { $($body:expr)* }) => {
92 {
93 writeln!($f, "{{")?;
94 $f.nest(|f| {
95 $(
96 $body.code_display(f)?;
97 )*
98 Ok(())
99 })?;
100 $f.indent()?; write!($f, "}}")
101 }
102 };
103
104
105 ($f:expr => $($arg:expr)*) => {
108 {
109 $(
110 $arg.code_display($f)?;
111 )*
112 Ok(())
113 }
114 };
115
116}