synkit_core/traits/to_tokens.rs
1use super::printer::Printer;
2
3/// Trait for converting AST nodes back to text.
4///
5/// `ToTokens` is the inverse of `Parse` - it converts parsed structures
6/// back into their textual representation. This enables:
7///
8/// - Code formatting / pretty-printing
9/// - Source-to-source transformations
10/// - Round-trip testing (parse → modify → print)
11///
12/// # Associated Types
13///
14/// - [`Printer`]: The printer implementation for formatting output
15///
16/// # Required Methods
17///
18/// - `write(&self, printer)`: Write this value to the printer
19///
20/// # Provided Methods
21///
22/// - `to_string_formatted()`: Convenience method for getting a String
23///
24/// # Example
25///
26/// ```ignore
27/// use synkit::{ToTokens, Printer};
28///
29/// struct BinaryExpr {
30/// left: Box<Expr>,
31/// op: &'static str,
32/// right: Box<Expr>,
33/// }
34///
35/// impl ToTokens for BinaryExpr {
36/// type Printer = MyPrinter;
37///
38/// fn write(&self, p: &mut Self::Printer) {
39/// self.left.write(p);
40/// p.write(" ");
41/// p.write(self.op);
42/// p.write(" ");
43/// self.right.write(p);
44/// }
45/// }
46/// ```
47///
48/// # Blanket Implementations
49///
50/// - `Option<T>`: Writes nothing for `None`, delegates for `Some`
51/// - `Box<T>`: Delegates to inner value
52/// - `Vec<T>`: Writes each element in sequence
53/// - `&T`: Delegates to referenced value
54pub trait ToTokens {
55 /// The printer type for formatting output.
56 type Printer: Printer;
57
58 /// Write this value to the printer.
59 ///
60 /// # Arguments
61 ///
62 /// * `printer` - The printer to write to
63 fn write(&self, printer: &mut Self::Printer);
64
65 /// Convert to a formatted string.
66 ///
67 /// Convenience method that creates a default printer, writes to it,
68 /// and returns the result as a String.
69 ///
70 /// # Returns
71 ///
72 /// The formatted string representation
73 fn to_string_formatted(&self) -> String
74 where
75 Self::Printer: Default,
76 {
77 let mut printer = Self::Printer::default();
78 self.write(&mut printer);
79 printer.into_string()
80 }
81}
82
83impl<T: ToTokens> ToTokens for Option<T> {
84 type Printer = T::Printer;
85
86 fn write(&self, p: &mut Self::Printer) {
87 if let Some(v) = self {
88 v.write(p);
89 }
90 }
91}
92
93impl<T: ToTokens> ToTokens for Box<T> {
94 type Printer = T::Printer;
95
96 fn write(&self, p: &mut Self::Printer) {
97 self.as_ref().write(p);
98 }
99}
100
101impl<T: ToTokens> ToTokens for Vec<T> {
102 type Printer = T::Printer;
103
104 fn write(&self, p: &mut Self::Printer) {
105 for item in self {
106 item.write(p);
107 }
108 }
109}
110
111impl<T: ToTokens> ToTokens for &T {
112 type Printer = T::Printer;
113
114 fn write(&self, p: &mut Self::Printer) {
115 (*self).write(p);
116 }
117}