1use crate::transform::Transformer;
2use parse::YieldFn;
3use quote::quote;
4use syn::{fold::Fold, parse_macro_input, parse_quote, GenericParam, LifetimeParam};
5use transform::DefineLifetimes;
6
7mod parse;
8mod transform;
9
10#[proc_macro]
11pub fn generator(body: proc_macro::TokenStream) -> proc_macro::TokenStream {
12 let YieldFn {
13 attrs,
14 vis,
15 mut sig,
16 yield_ty: ty,
17 block,
18 ..
19 } = parse_macro_input!(body as YieldFn);
20
21 let mut lts = DefineLifetimes::default();
22 sig = lts.fold_signature(sig);
23 sig.generics.params.extend(
24 lts.unique
25 .iter()
26 .cloned()
27 .map(|x| GenericParam::Lifetime(LifetimeParam::new(x))),
28 );
29
30 let lts = lts.unique.map(|x| quote!(#x +));
32
33 let block = Transformer(&ty).fold_block(block);
34 let (arrow, output) = match sig.output {
35 syn::ReturnType::Default => (Default::default(), parse_quote!(())),
36 syn::ReturnType::Type(arrow, output) => (arrow, output),
37 };
38
39 sig.output = parse_quote! {
40 #arrow impl #lts ::generatox::Generator<Yield = #ty, Return = #output>
41 };
42
43 return quote! {
44 #(#attrs)*
45 #vis #sig {
46 ::generatox::wrapper::Wrapper::new(async move #block)
47 }
48 }
49 .into();
50}