]> git.proxmox.com Git - rustc.git/blame - src/vendor/quote/src/lib.rs
New upstream version 1.21.0+dfsg1
[rustc.git] / src / vendor / quote / src / lib.rs
CommitLineData
3b2f2976
XL
1//! Quasi-quoting without a Syntex dependency, intended for use with [Macros
2//! 1.1](https://github.com/rust-lang/rfcs/blob/master/text/1681-macros-1.1.md).
3//!
4//! ```toml
5//! [dependencies]
6//! quote = "0.3"
7//! ```
8//!
9//! ```rust,ignore
10//! #[macro_use]
11//! extern crate quote;
12//! ```
13//!
14//! Interpolation is done with `#var`:
15//!
16//! ```text
17//! let tokens = quote! {
18//! struct SerializeWith #generics #where_clause {
19//! value: &'a #field_ty,
20//! phantom: ::std::marker::PhantomData<#item_ty>,
21//! }
22//!
23//! impl #generics serde::Serialize for SerializeWith #generics #where_clause {
24//! fn serialize<S>(&self, s: &mut S) -> Result<(), S::Error>
25//! where S: serde::Serializer
26//! {
27//! #path(self.value, s)
28//! }
29//! }
30//!
31//! SerializeWith {
32//! value: #value,
33//! phantom: ::std::marker::PhantomData::<#item_ty>,
34//! }
35//! };
36//! ```
37//!
38//! Repetition is done using `#(...)*` or `#(...),*` very similar to `macro_rules!`:
39//!
40//! - `#(#var)*` - no separators
41//! - `#(#var),*` - the character before the asterisk is used as a separator
42//! - `#( struct #var; )*` - the repetition can contain other things
43//! - `#( #k => println!("{}", #v), )*` - even multiple interpolations
44//!
45//! The return type of `quote!` is `quote::Tokens`. Tokens can be interpolated into
46//! other quotes:
47//!
48//! ```text
49//! let t = quote! { /* ... */ };
50//! return quote! { /* ... */ #t /* ... */ };
51//! ```
52//!
53//! Call `to_string()` or `as_str()` on a Tokens to get a `String` or `&str` of Rust
54//! code.
55//!
56//! The `quote!` macro relies on deep recursion so some large invocations may fail
57//! with "recursion limit reached" when you compile. If it fails, bump up the
58//! recursion limit by adding `#![recursion_limit = "128"]` to your crate. An even
59//! higher limit may be necessary for especially large invocations.
60
61mod tokens;
62pub use tokens::Tokens;
63
64mod to_tokens;
65pub use to_tokens::{ToTokens, ByteStr, Hex};
66
67mod ident;
68pub use ident::Ident;
69
70/// The whole point.
71#[macro_export]
72macro_rules! quote {
73 () => {
74 $crate::Tokens::new()
75 };
76
77 ($($tt:tt)+) => {
78 {
79 let mut _s = $crate::Tokens::new();
80 quote_each_token!(_s $($tt)*);
81 _s
82 }
83 };
84}
85
86// Extract the names of all #metavariables and pass them to the $finish macro.
87//
88// in: pounded_var_names!(then () a #b c #( #d )* #e)
89// out: then!(() b d e)
90#[macro_export]
91#[doc(hidden)]
92macro_rules! pounded_var_names {
93 ($finish:ident ($($found:ident)*) # ( $($inner:tt)* ) $($rest:tt)*) => {
94 pounded_var_names!($finish ($($found)*) $($inner)* $($rest)*)
95 };
96
97 ($finish:ident ($($found:ident)*) # [ $($inner:tt)* ] $($rest:tt)*) => {
98 pounded_var_names!($finish ($($found)*) $($inner)* $($rest)*)
99 };
100
101 ($finish:ident ($($found:ident)*) # { $($inner:tt)* } $($rest:tt)*) => {
102 pounded_var_names!($finish ($($found)*) $($inner)* $($rest)*)
103 };
104
105 ($finish:ident ($($found:ident)*) # $first:ident $($rest:tt)*) => {
106 pounded_var_names!($finish ($($found)* $first) $($rest)*)
107 };
108
109 ($finish:ident ($($found:ident)*) ( $($inner:tt)* ) $($rest:tt)*) => {
110 pounded_var_names!($finish ($($found)*) $($inner)* $($rest)*)
111 };
112
113 ($finish:ident ($($found:ident)*) [ $($inner:tt)* ] $($rest:tt)*) => {
114 pounded_var_names!($finish ($($found)*) $($inner)* $($rest)*)
115 };
116
117 ($finish:ident ($($found:ident)*) { $($inner:tt)* } $($rest:tt)*) => {
118 pounded_var_names!($finish ($($found)*) $($inner)* $($rest)*)
119 };
120
121 ($finish:ident ($($found:ident)*) $ignore:tt $($rest:tt)*) => {
122 pounded_var_names!($finish ($($found)*) $($rest)*)
123 };
124
125 ($finish:ident ($($found:ident)*)) => {
126 $finish!(() $($found)*)
127 };
128}
129
130// in: nested_tuples_pat!(() a b c d e)
131// out: ((((a b) c) d) e)
132//
133// in: nested_tuples_pat!(() a)
134// out: a
135#[macro_export]
136#[doc(hidden)]
137macro_rules! nested_tuples_pat {
138 (()) => {
139 &()
140 };
141
142 (() $first:ident $($rest:ident)*) => {
143 nested_tuples_pat!(($first) $($rest)*)
144 };
145
146 (($pat:pat) $first:ident $($rest:ident)*) => {
147 nested_tuples_pat!((($pat, $first)) $($rest)*)
148 };
149
150 (($done:pat)) => {
151 $done
152 };
153}
154
155// in: multi_zip_expr!(() a b c d e)
156// out: a.into_iter().zip(b).zip(c).zip(d).zip(e)
157//
158// in: multi_zip_iter!(() a)
159// out: a
160#[macro_export]
161#[doc(hidden)]
162macro_rules! multi_zip_expr {
163 (()) => {
164 &[]
165 };
166
167 (() $single:ident) => {
168 $single
169 };
170
171 (() $first:ident $($rest:ident)*) => {
172 multi_zip_expr!(($first.into_iter()) $($rest)*)
173 };
174
175 (($zips:expr) $first:ident $($rest:ident)*) => {
176 multi_zip_expr!(($zips.zip($first)) $($rest)*)
177 };
178
179 (($done:expr)) => {
180 $done
181 };
182}
183
184#[macro_export]
185#[doc(hidden)]
186macro_rules! quote_each_token {
187 ($tokens:ident) => {};
188
189 ($tokens:ident # ! $($rest:tt)*) => {
190 $tokens.append("#");
191 $tokens.append("!");
192 quote_each_token!($tokens $($rest)*);
193 };
194
195 ($tokens:ident # ( $($inner:tt)* ) * $($rest:tt)*) => {
196 for pounded_var_names!(nested_tuples_pat () $($inner)*)
197 in pounded_var_names!(multi_zip_expr () $($inner)*) {
198 quote_each_token!($tokens $($inner)*);
199 }
200 quote_each_token!($tokens $($rest)*);
201 };
202
203 ($tokens:ident # ( $($inner:tt)* ) $sep:tt * $($rest:tt)*) => {
204 for (_i, pounded_var_names!(nested_tuples_pat () $($inner)*))
205 in pounded_var_names!(multi_zip_expr () $($inner)*).into_iter().enumerate() {
206 if _i > 0 {
207 $tokens.append(stringify!($sep));
208 }
209 quote_each_token!($tokens $($inner)*);
210 }
211 quote_each_token!($tokens $($rest)*);
212 };
213
214 ($tokens:ident # [ $($inner:tt)* ] $($rest:tt)*) => {
215 $tokens.append("#");
216 $tokens.append("[");
217 quote_each_token!($tokens $($inner)*);
218 $tokens.append("]");
219 quote_each_token!($tokens $($rest)*);
220 };
221
222 ($tokens:ident # $first:ident $($rest:tt)*) => {
223 $crate::ToTokens::to_tokens(&$first, &mut $tokens);
224 quote_each_token!($tokens $($rest)*);
225 };
226
227 ($tokens:ident ( $($first:tt)* ) $($rest:tt)*) => {
228 $tokens.append("(");
229 quote_each_token!($tokens $($first)*);
230 $tokens.append(")");
231 quote_each_token!($tokens $($rest)*);
232 };
233
234 ($tokens:ident [ $($first:tt)* ] $($rest:tt)*) => {
235 $tokens.append("[");
236 quote_each_token!($tokens $($first)*);
237 $tokens.append("]");
238 quote_each_token!($tokens $($rest)*);
239 };
240
241 ($tokens:ident { $($first:tt)* } $($rest:tt)*) => {
242 $tokens.append("{");
243 quote_each_token!($tokens $($first)*);
244 $tokens.append("}");
245 quote_each_token!($tokens $($rest)*);
246 };
247
248 ($tokens:ident $first:tt $($rest:tt)*) => {
249 $tokens.append(stringify!($first));
250 quote_each_token!($tokens $($rest)*);
251 };
252}