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}