1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
#![feature(proc_macro)] extern crate proc_macro; #[macro_use] extern crate quote; extern crate syn; use syn::*; use proc_macro::TokenStream; #[proc_macro_attribute] pub fn thread_spawn(_args: TokenStream, input: TokenStream) -> TokenStream { let input: ItemFn = match parse(input) { Ok(input) => input, Err(..) => panic!("#[spawn()] must be applied on functions"), }; if input.decl.generics.where_clause.is_some() { panic!("#[spawn()] does not work with where clauses") } let mut args = vec![]; let mut where_args = vec![]; let mut pat_args = vec![]; for arg in input.decl.inputs.iter() { match *arg { FnArg::Captured(ref cap) => { let ty = &cap.ty; let pat = &cap.pat; where_args.push(quote!(#ty)); pat_args.push(quote!(#pat)); args.push(quote!(#pat: #ty)); } _ => panic!("Unexpected argument {:?}", arg) } } let funcname = &input.ident; let attributes = &input.attrs; let vis = &input.vis; let constness = &input.constness; let unsafety = &input.unsafety; let abi = &input.abi; let output = match input.decl.output { syn::ReturnType::Default => { Box::new(syn::parse_str("()").unwrap()) } syn::ReturnType::Type(_, ref ret) => { ret.to_owned() } }; let body = &input.block; quote!( #(#attributes),* #vis #constness #unsafety #abi fn #funcname (#(#args),*) -> ::std::thread::JoinHandle<#output> { ::std::thread::Builder::new() .name(stringify!(#funcname).to_string()) .spawn(move || { #body }) .unwrap() } ).into() }