Jason Macnak | bbac34b | 2020-03-25 01:28:44 +0000 | [diff] [blame] | 1 | //! Support for nested invocations of proc-macro-hack expression macros. |
| 2 | //! |
| 3 | //! By default, macros defined through proc-macro-hack do not support nested |
| 4 | //! invocations, i.e. the code emitted by a proc-macro-hack macro invocation |
| 5 | //! cannot contain recursive calls to the same proc-macro-hack macro nor calls |
| 6 | //! to any other proc-macro-hack macros. |
| 7 | //! |
| 8 | //! This crate provides opt-in support for such nested invocations. |
| 9 | //! |
| 10 | //! To make a macro callable recursively, add a dependency on this crate from |
| 11 | //! your declaration crate and update the `#[proc_macro_hack]` re-export as |
| 12 | //! follows. |
| 13 | //! |
| 14 | //! ``` |
| 15 | //! // Before |
| 16 | //! # const IGNORE: &str = stringify! { |
| 17 | //! #[proc_macro_hack] |
| 18 | //! pub use demo_hack_impl::add_one; |
| 19 | //! # }; |
| 20 | //! ``` |
| 21 | //! |
| 22 | //! ``` |
| 23 | //! // After |
| 24 | //! # const IGNORE: &str = stringify! { |
| 25 | //! #[proc_macro_hack(support_nested)] |
| 26 | //! pub use demo_hack_impl::add_one; |
| 27 | //! # }; |
| 28 | //! ``` |
| 29 | //! |
| 30 | //! No change is required within your definition crate, only to the re-export in |
| 31 | //! the declaration crate. |
| 32 | //! |
| 33 | //! # Limitations |
| 34 | //! |
| 35 | //! - Nested invocations are preprocessed by a TT-muncher, so the caller's crate |
| 36 | //! will be required to contain `#![recursion_limit = "..."]` if there are |
| 37 | //! lengthy macro invocations. |
| 38 | //! |
| 39 | //! - Only up to 64 nested invocations are supported. |
| 40 | |
| 41 | #![no_std] |
| 42 | |
Matthew Maurer | fe7c85d | 2020-07-06 13:22:35 -0700 | [diff] [blame] | 43 | // ANDROID: Use std to allow building as a dylib. |
| 44 | extern crate std; |
| 45 | |
Chih-Hung Hsieh | 905c18a | 2020-10-25 03:57:56 -0700 | [diff] [blame] | 46 | include!(concat!(env!("OUT_DIR"), "/count.rs")); |
Jason Macnak | bbac34b | 2020-03-25 01:28:44 +0000 | [diff] [blame] | 47 | |
| 48 | #[doc(hidden)] |
| 49 | #[macro_export] |
| 50 | macro_rules! dispatch { |
| 51 | (() $($bang:tt)*) => { |
| 52 | $crate::count!($($bang)*) |
| 53 | }; |
| 54 | ((($($first:tt)*) $($rest:tt)*) $($bang:tt)*) => { |
| 55 | $crate::dispatch!(($($first)* $($rest)*) $($bang)*) |
| 56 | }; |
| 57 | (([$($first:tt)*] $($rest:tt)*) $($bang:tt)*) => { |
| 58 | $crate::dispatch!(($($first)* $($rest)*) $($bang)*) |
| 59 | }; |
| 60 | (({$($first:tt)*} $($rest:tt)*) $($bang:tt)*) => { |
| 61 | $crate::dispatch!(($($first)* $($rest)*) $($bang)*) |
| 62 | }; |
| 63 | ((! $($rest:tt)*) $($bang:tt)*) => { |
| 64 | $crate::dispatch!(($($rest)*) $($bang)* !) |
| 65 | }; |
| 66 | ((!= $($rest:tt)*) $($bang:tt)*) => { |
| 67 | $crate::dispatch!(($($rest)*) $($bang)* !) |
| 68 | }; |
| 69 | (($first:tt $($rest:tt)*) $($bang:tt)*) => { |
| 70 | $crate::dispatch!(($($rest)*) $($bang)*) |
| 71 | }; |
| 72 | } |