comacro/
repr.rs

1use std::io::Write;
2use std::fmt::Display;
3
4use crate::trace::*;
5use crate::visitor::Visitor;
6
7pub(crate) trait Emitter {
8    fn meta(&mut self, x: u32);
9    fn item(&mut self, s: impl Display);
10    fn text_item(&mut self, s: impl Display);
11    fn opener(&mut self, s: impl Display);
12    fn closer(&mut self);
13    fn maybe_break(&mut self) {}
14    fn finish(self) -> Vec<u8>;
15}
16
17pub(crate) struct ReprEmitter {
18    buf: std::io::Cursor<Vec<u8>>,
19    sibling: bool,
20}
21
22impl ReprEmitter {
23    pub fn new() -> Self {
24        let buf = std::io::Cursor::new(Vec::new());
25        let sibling = false;
26        ReprEmitter { buf, sibling }
27    }
28
29    fn maybe_comma(&mut self) {
30        if self.sibling { self.comma(); }
31    }
32
33    fn comma(&mut self) {
34        write!(self.buf, " ").unwrap();
35    }
36}
37
38impl Emitter for ReprEmitter {
39    fn meta(&mut self, x: u32) {
40        self.maybe_comma();
41        write!(self.buf, "${}", x);
42        self.sibling = true;
43    }
44
45    fn item(&mut self, s: impl Display) {
46        self.maybe_comma();
47        write!(self.buf, "{}", s);
48        self.sibling = true;
49    }
50
51    fn text_item(&mut self, s: impl Display) {
52        self.maybe_comma();
53        write!(self.buf, "{}", s);
54        self.sibling = true;
55    }
56
57    fn opener(&mut self, s: impl Display) {
58        self.maybe_comma();
59        write!(self.buf, "{}{{", s);
60        self.sibling = true;
61    }
62
63    fn closer(&mut self) {
64        self.maybe_comma();
65        write!(self.buf, "}}");
66        self.sibling = true;
67    }
68
69    fn maybe_break(&mut self) {
70        if self.buf.position() != 0 {
71            write!(self.buf, "\n");
72            self.sibling = false;
73        }
74    }
75
76    fn finish(self) -> Vec<u8> {
77        self.buf.into_inner()
78    }
79}
80
81pub(crate) struct JsonEmitter {
82    buf: std::io::Cursor<Vec<u8>>,
83    sibling: bool,
84    scalar_context: bool,
85}
86
87impl JsonEmitter {
88    pub fn new() -> Self {
89        let mut buf = std::io::Cursor::new(Vec::new());
90        write!(buf, "[");
91        let sibling = false;
92        JsonEmitter { buf, sibling, scalar_context: false }
93    }
94
95    pub fn new_scalar() -> Self {
96        let buf = std::io::Cursor::new(Vec::new());
97        let sibling = false;
98        JsonEmitter { buf, sibling, scalar_context: true }
99    }
100
101    fn maybe_comma(&mut self) {
102        if self.sibling { self.comma(); }
103    }
104
105    fn comma(&mut self) {
106        write!(self.buf, ",").unwrap();
107    }
108}
109
110impl Emitter for JsonEmitter {
111    fn finish(mut self) -> Vec<u8> {
112        if !self.scalar_context {
113            write!(self.buf, "]");
114        }
115        self.buf.into_inner()
116    }
117
118    fn meta(&mut self, x: u32) {
119        self.maybe_comma();
120        write!(self.buf, "\"${}\"", x);
121        self.sibling = true;
122    }
123
124    fn item(&mut self, s: impl Display) {
125        self.maybe_comma();
126        write!(self.buf, "{}", s);
127        self.sibling = true;
128    }
129
130    fn text_item(&mut self, s: impl Display) {
131        self.maybe_comma();
132        write!(self.buf, "\"{}\"", s);
133        self.sibling = true;
134    }
135
136    fn opener(&mut self, s: impl Display) {
137        self.maybe_comma();
138        write!(self.buf, "[\"{}\"", s);
139        self.sibling = true;
140    }
141
142    fn closer(&mut self) {
143        write!(self.buf, "]");
144        self.sibling = true;
145    }
146}
147
148/// An AST visitor that compares compiled MatchCode for a pattern with the AST for that pattern's
149/// <nodes> or <ids> tree to emit a representation of the pattern.
150pub(crate) struct ReprGenerator<E> {
151    emitter: E,
152    trace: ReTracer,
153}
154
155impl<E: Emitter> ReprGenerator<E> {
156    pub fn new(old: Trace, emitter: E) -> Self {
157        let trace = ReTracer::new(old);
158        ReprGenerator { emitter, trace }
159    }
160
161    pub fn finish(self) -> Vec<u8> {
162        self.emitter.finish()
163    }
164}
165
166impl<E: Emitter> Visitor<'_> for ReprGenerator<E> {
167    fn open_expr(&mut self, x: &syn::Expr) -> Result<(), ()> {
168        if let Err(()) = self.trace.open_subtree() {
169            let x = u32::from(self.trace.consume_meta());
170            self.emitter.meta(x);
171            return Err(());
172        }
173        self.emitter.opener(crate::names::expr_discrim(x));
174        Ok(())
175    }
176    fn open_ident(&mut self, x: &syn::Ident) -> Result<(), ()> {
177        if let Err(()) = self.trace.open_subtree() {
178            let x = u32::from(self.trace.consume_meta());
179            self.emitter.meta(x);
180            return Err(());
181        }
182        self.emitter.text_item(x);
183        Ok(())
184    }
185    fn open_stmt(&mut self, x: &syn::Stmt) {
186        self.open_subtree();
187        self.emitter.maybe_break();
188        self.emitter.opener(crate::names::stmt_discrim(x));
189    }
190    fn open_pat(&mut self, x: &syn::Pat) {
191        self.open_subtree();
192        self.emitter.opener(crate::names::pat_discrim(x));
193    }
194    fn open_lit_int(&mut self, x: &syn::LitInt) {
195        self.open_datum();
196        self.emitter.item(x.value());
197    }
198
199    fn close_expr(&mut self, _: &syn::Expr) {
200        self.close_subtree();
201        self.emitter.closer();
202    }
203    fn close_stmt(&mut self, _: &syn::Stmt) {
204        self.close_subtree();
205        self.emitter.closer();
206    }
207    fn close_pat(&mut self, _: &syn::Pat) {
208        self.close_subtree();
209        self.emitter.closer();
210    }
211
212    fn open_subtree(&mut self) { self.trace.open_subtree().unwrap(); }
213    fn close_subtree(&mut self) { self.trace.close_subtree().unwrap(); }
214    fn open_datum(&mut self) { self.trace.open_datum(); }
215    fn close_datum(&mut self) { self.trace.close_datum(); }
216    fn push_byte(&mut self, x: u8) { self.trace.push_byte(x); }
217    fn extend_bytes(&mut self, x: &[u8]) { self.trace.extend_bytes(x); }
218}
219
220/// Serialize a normal AST (no metavars)
221pub(crate) struct PlainAstRepr<E> {
222    emitter: E,
223}
224
225impl<E: Emitter> PlainAstRepr<E> {
226    pub fn new(emitter: E) -> Self {
227        PlainAstRepr { emitter }
228    }
229
230    pub fn finish(self) -> Vec<u8> {
231        self.emitter.finish()
232    }
233}
234
235
236impl<E: Emitter> Visitor<'_> for PlainAstRepr<E> {
237    fn open_expr(&mut self, x: &syn::Expr) -> Result<(), ()> {
238        self.emitter.opener(crate::names::expr_discrim(x));
239        Ok(())
240    }
241    fn open_ident(&mut self, x: &syn::Ident) -> Result<(), ()> {
242        self.emitter.text_item(x);
243        Ok(())
244    }
245    fn open_stmt(&mut self, x: &syn::Stmt) {
246        self.emitter.maybe_break();
247        self.emitter.opener(crate::names::stmt_discrim(x));
248    }
249    fn open_pat(&mut self, x: &syn::Pat) {
250        self.emitter.opener(crate::names::pat_discrim(x));
251    }
252    fn open_lit_int(&mut self, x: &syn::LitInt) {
253        self.emitter.item(x.value());
254    }
255
256    fn close_expr(&mut self, _: &syn::Expr) {
257        self.emitter.closer();
258    }
259    fn close_stmt(&mut self, _: &syn::Stmt) {
260        self.emitter.closer();
261    }
262    fn close_pat(&mut self, _: &syn::Pat) {
263        self.emitter.closer();
264    }
265
266    fn open_subtree(&mut self) {}
267    fn close_subtree(&mut self) {}
268    fn open_datum(&mut self) {}
269    fn close_datum(&mut self) {}
270    fn push_byte(&mut self, x: u8) {}
271    fn extend_bytes(&mut self, x: &[u8]) {}
272}
273