osaka_macros/
lib.rs

1extern crate proc_macro;
2#[macro_use]
3extern crate syn;
4#[macro_use]
5extern crate quote;
6extern crate proc_macro2;
7
8use proc_macro::TokenStream;
9use syn::export::ToTokens;
10use syn::ItemFn;
11
12#[proc_macro_attribute]
13pub fn osaka(_args: TokenStream, input: TokenStream) -> TokenStream {
14    let mut f = parse_macro_input!(input as ItemFn);
15
16    let output = match f.decl.output.clone() {
17        syn::ReturnType::Default => quote! {()},
18        syn::ReturnType::Type(_, t) => quote! {#t},
19    };
20
21    f.decl.output = match syn::parse((quote! {
22        -> osaka::Task<#output>
23    }).into(),
24    ) {
25        Ok(v) => v,
26        Err(e) => return e.to_compile_error().into(),
27    };
28
29    let oblock = f.block;
30    f.block = match syn::parse(
31        (quote! {{
32            use std::pin::Pin;
33            use std::ops::Generator;
34            let mut l = Box::new(move||{
35                #oblock
36            });
37
38            let a = match Pin::new(l.as_mut()).resume() {
39                std::ops::GeneratorState::Complete(y) => {
40                    return osaka::Task::immediate(y);
41                }
42                std::ops::GeneratorState::Yielded(y) => {
43                    y
44                }
45            };
46            osaka::Task::new(l,a)
47        }})
48        .into(),
49    ) {
50        Ok(v) => v,
51        Err(e) => return e.to_compile_error().into(),
52    };
53
54    f.into_token_stream().into()
55}