| //! Support for nested invocations of proc-macro-hack expression macros. |
| //! |
| //! By default, macros defined through proc-macro-hack do not support nested |
| //! invocations, i.e. the code emitted by a proc-macro-hack macro invocation |
| //! cannot contain recursive calls to the same proc-macro-hack macro nor calls |
| //! to any other proc-macro-hack macros. |
| //! |
| //! This crate provides opt-in support for such nested invocations. |
| //! |
| //! To make a macro callable recursively, add a dependency on this crate from |
| //! your declaration crate and update the `#[proc_macro_hack]` re-export as |
| //! follows. |
| //! |
| //! ``` |
| //! // Before |
| //! # const IGNORE: &str = stringify! { |
| //! #[proc_macro_hack] |
| //! pub use demo_hack_impl::add_one; |
| //! # }; |
| //! ``` |
| //! |
| //! ``` |
| //! // After |
| //! # const IGNORE: &str = stringify! { |
| //! #[proc_macro_hack(support_nested)] |
| //! pub use demo_hack_impl::add_one; |
| //! # }; |
| //! ``` |
| //! |
| //! No change is required within your definition crate, only to the re-export in |
| //! the declaration crate. |
| //! |
| //! # Limitations |
| //! |
| //! - Nested invocations are preprocessed by a TT-muncher, so the caller's crate |
| //! will be required to contain `#![recursion_limit = "..."]` if there are |
| //! lengthy macro invocations. |
| //! |
| //! - Only up to 64 nested invocations are supported. |
| |
| #![no_std] |
| |
| // ANDROID: Use std to allow building as a dylib. |
| extern crate std; |
| |
| include!(concat!(env!("OUT_DIR"), "/count.rs")); |
| |
| #[doc(hidden)] |
| #[macro_export] |
| macro_rules! dispatch { |
| (() $($bang:tt)*) => { |
| $crate::count!($($bang)*) |
| }; |
| ((($($first:tt)*) $($rest:tt)*) $($bang:tt)*) => { |
| $crate::dispatch!(($($first)* $($rest)*) $($bang)*) |
| }; |
| (([$($first:tt)*] $($rest:tt)*) $($bang:tt)*) => { |
| $crate::dispatch!(($($first)* $($rest)*) $($bang)*) |
| }; |
| (({$($first:tt)*} $($rest:tt)*) $($bang:tt)*) => { |
| $crate::dispatch!(($($first)* $($rest)*) $($bang)*) |
| }; |
| ((! $($rest:tt)*) $($bang:tt)*) => { |
| $crate::dispatch!(($($rest)*) $($bang)* !) |
| }; |
| ((!= $($rest:tt)*) $($bang:tt)*) => { |
| $crate::dispatch!(($($rest)*) $($bang)* !) |
| }; |
| (($first:tt $($rest:tt)*) $($bang:tt)*) => { |
| $crate::dispatch!(($($rest)*) $($bang)*) |
| }; |
| } |