1#![recursion_limit = "256"]
6#![allow(clippy::type_complexity)]
7#![cfg_attr(proc_macro_span, feature(proc_macro_span))]
8
9extern crate proc_macro;
10
11use proc_macro2::Span;
12use syn::parse::{ParseStream, Parser as _};
13
14struct Ctxt {
15 receiver: syn::Ident,
16 module: syn::Path,
17}
18
19impl Default for Ctxt {
20 fn default() -> Self {
21 let mut module = syn::Path {
22 leading_colon: None,
23 segments: syn::punctuated::Punctuated::default(),
24 };
25
26 module
27 .segments
28 .push(syn::Ident::new("genco", Span::call_site()).into());
29
30 Self {
31 receiver: syn::Ident::new("__genco_macros_toks", Span::call_site()),
32 module,
33 }
34 }
35}
36
37mod ast;
38mod cursor;
39mod encoder;
40mod fake;
41mod quote;
42mod quote_fn;
43mod quote_in;
44mod requirements;
45mod static_buffer;
46mod string_parser;
47
48#[proc_macro]
49pub fn quote(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
50 let cx = Ctxt::default();
51 let parser = crate::quote::Quote::new(&cx);
52
53 let parser = move |stream: ParseStream| parser.parse(stream);
54
55 let (req, output) = match parser.parse(input) {
56 Ok(data) => data,
57 Err(e) => return proc_macro::TokenStream::from(e.to_compile_error()),
58 };
59
60 let check = req.into_check(&cx.receiver);
61
62 let Ctxt { receiver, module } = &cx;
63
64 let gen = q::quote! {{
65 let mut #receiver = #module::tokens::Tokens::new();
66
67 {
68 let mut #receiver = &mut #receiver;
69 #output
70 }
71
72 #check
73 #receiver
74 }};
75
76 gen.into()
77}
78
79#[proc_macro]
80pub fn quote_in(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
81 let quote_in = syn::parse_macro_input!(input as quote_in::QuoteIn);
82 quote_in.stream.into()
83}
84
85#[proc_macro]
86pub fn quote_fn(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
87 let quote_fn = syn::parse_macro_input!(input as quote_fn::QuoteFn);
88 quote_fn.stream.into()
89}