genawaiter-proc-macro-0.99.1/Cargo.toml.orig000064400000000000000000000011661363130263300170610ustar0000000000000000[package] name = "genawaiter-proc-macro" version = "0.99.1" authors = ["Devin R "] license = "MIT/Apache-2.0" description = "procedural macro for generators (genawaiter)" edition = "2018" repository = "https://github.com/whatisaphone/genawaiter" readme = "../README.md" keywords = ["generator", "yield", "coroutine", "async", "await"] categories = ["asynchronous", "concurrency", "rust-patterns"] [lib] proc-macro = true [dependencies] quote = "1.0" proc-macro2 = "1.0" syn = { version = "1.0", features = ["visit-mut", "full"] } proc-macro-error = "0.4" proc-macro-hack = "0.5" [features] strict = [] genawaiter-proc-macro-0.99.1/Cargo.toml0000644000000023331363130327000134150ustar00# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] edition = "2018" name = "genawaiter-proc-macro" version = "0.99.1" authors = ["Devin R "] description = "procedural macro for generators (genawaiter)" readme = "../README.md" keywords = ["generator", "yield", "coroutine", "async", "await"] categories = ["asynchronous", "concurrency", "rust-patterns"] license = "MIT/Apache-2.0" repository = "https://github.com/whatisaphone/genawaiter" [lib] proc-macro = true [dependencies.proc-macro-error] version = "0.4" [dependencies.proc-macro-hack] version = "0.5" [dependencies.proc-macro2] version = "1.0" [dependencies.quote] version = "1.0" [dependencies.syn] version = "1.0" features = ["visit-mut", "full"] [features] strict = [] genawaiter-proc-macro-0.99.1/src/lib.rs000064400000000000000000000125361362227666700161210ustar0000000000000000#![warn(future_incompatible, rust_2018_compatibility, rust_2018_idioms, unused)] #![warn(clippy::cargo, clippy::pedantic)] #![cfg_attr(feature = "strict", deny(warnings))] extern crate proc_macro; use crate::visit::YieldReplace; use proc_macro::TokenStream; use proc_macro_error::{abort, abort_call_site, proc_macro_error}; use proc_macro_hack::proc_macro_hack; use quote::quote; use std::string::ToString; use syn::{ self, parse_macro_input, parse_str, spanned::Spanned, visit_mut::VisitMut, ExprBlock, FnArg, Ident, ItemFn, Type, }; mod visit; #[proc_macro_attribute] #[proc_macro_error] pub fn stack_producer_fn(args: TokenStream, input: TokenStream) -> TokenStream { let a = args.clone(); // make sure it is a valid type let _ = parse_macro_input!(a as Type); let mut function = parse_macro_input!(input as ItemFn); let co_arg = format!("{}{}>", stack::CO_ARG_FN, args); add_coroutine_arg(&mut function, &co_arg); YieldReplace.visit_item_fn_mut(&mut function); let tokens = quote! { #function }; tokens.into() } #[proc_macro_hack] #[proc_macro_error] pub fn stack_producer(input: TokenStream) -> TokenStream { let mut input = parse_macro_input!(input as ExprBlock); YieldReplace.visit_expr_block_mut(&mut input); // for some reason parsing as a PatType (correct for closures) fails // the only way around is to destructure. let arg = match parse_str::(stack::CO_ARG) { Ok(FnArg::Typed(x)) => x, _ => abort_call_site!("string Pat parse failed Co<...>"), }; let tokens = quote! { |#arg| async move #input }; tokens.into() } #[proc_macro_attribute] #[proc_macro_error] pub fn sync_producer_fn(args: TokenStream, input: TokenStream) -> TokenStream { let a = args.clone(); // make sure it is a valid type let _ = parse_macro_input!(a as Type); let mut function = parse_macro_input!(input as ItemFn); let co_arg = format!("{}{}>", sync::CO_ARG_FN, args); add_coroutine_arg(&mut function, &co_arg); YieldReplace.visit_item_fn_mut(&mut function); let tokens = quote! { #function }; tokens.into() } #[proc_macro_hack] #[proc_macro_error] pub fn sync_producer(input: TokenStream) -> TokenStream { let mut input = parse_macro_input!(input as ExprBlock); YieldReplace.visit_expr_block_mut(&mut input); // for some reason parsing as a PatType (correct for closures) fails let arg = match parse_str::(sync::CO_ARG) { Ok(FnArg::Typed(x)) => x, _ => abort_call_site!("string Pat parse failed Co<...>"), }; let tokens = quote! { |#arg| async move #input }; tokens.into() } #[proc_macro_attribute] #[proc_macro_error] pub fn rc_producer_fn(args: TokenStream, input: TokenStream) -> TokenStream { let a = args.clone(); // make sure it is a valid type let _ = parse_macro_input!(a as Type); let mut function = parse_macro_input!(input as ItemFn); let co_arg = format!("{}{}>", rc::CO_ARG_FN, args); add_coroutine_arg(&mut function, &co_arg); YieldReplace.visit_item_fn_mut(&mut function); let tokens = quote! { #function }; tokens.into() } #[proc_macro_hack] #[proc_macro_error] pub fn rc_producer(input: TokenStream) -> TokenStream { let mut input = parse_macro_input!(input as ExprBlock); YieldReplace.visit_expr_block_mut(&mut input); // for some reason parsing as a PatType (correct for closures) fails let arg = match parse_str::(rc::CO_ARG) { Ok(FnArg::Typed(x)) => x, _ => abort_call_site!("string Pat parse failed Co<...>"), }; let tokens = quote! { |#arg| async move #input }; tokens.into() } mod stack { pub(crate) const CO_ARG_FN: &str = "__private_co_arg__: ::genawaiter::stack::Co<'_, "; pub(crate) const CO_ARG: &str = "__private_co_arg__: ::genawaiter::stack::Co<'_, _, _>"; } mod sync { pub(crate) const CO_ARG_FN: &str = "__private_co_arg__: ::genawaiter::sync::Co<"; pub(crate) const CO_ARG: &str = "__private_co_arg__: ::genawaiter::sync::Co<_, _>"; } mod rc { pub(crate) const CO_ARG_FN: &str = "__private_co_arg__: ::genawaiter::rc::Co<"; pub(crate) const CO_ARG: &str = "__private_co_arg__: ::genawaiter::rc::Co<_, _>"; } /// Mutates the input `Punctuated` to a lifetimeless `co: /// Co<{type}>`. fn add_coroutine_arg(func: &mut ItemFn, co_ty: &str) { let co_arg_found = func.sig.inputs.iter().any(|input| { match input { FnArg::Receiver(_) => false, FnArg::Typed(arg) => { match &*arg.ty { Type::Path(ty) => { ty.path.segments.iter().any(|seg| { seg.ident == parse_str::("Co").expect("Ident parse failed") }) } _ => false, } } } }); if !co_arg_found { let co_arg: FnArg = match parse_str::(co_ty) { Ok(s) => s, Err(err) => abort_call_site!(format!("invalid type for Co yield {}", err)), }; func.sig.inputs.push_value(co_arg) } else { abort!( func.sig.span(), "A generator producer cannot accept any arguments. Instead, consider \ using a closure and capturing the values you need.", ) } } genawaiter-proc-macro-0.99.1/src/visit.rs000064400000000000000000000014501362210310600164530ustar0000000000000000use proc_macro2::TokenStream as TokenStream2; use quote::quote; use syn::{ parse2, visit_mut::{self, VisitMut}, Expr, }; pub struct YieldReplace; impl VisitMut for YieldReplace { fn visit_expr_mut(&mut self, expr: &mut Expr) { if let Expr::Macro(m) = expr { if m.mac.path.segments.iter().any(|seg| seg.ident == "yield_") { let tkns: TokenStream2 = syn::parse2(m.mac.tokens.clone()) .expect("parse of TokensStream failed"); let co_call = quote! { yield_!(@__impl => __private_co_arg__, #tkns) }; let cc: Expr = parse2(co_call).expect("parse of Expr failed"); *expr = cc; } } visit_mut::visit_expr_mut(self, expr) } } genawaiter-proc-macro-0.99.1/.cargo_vcs_info.json0000644000000001121363130327000154100ustar00{ "git": { "sha1": "f48046a9f66fbd2e535d5614fa7fe0d0b1a6a046" } }