template_quote/
lib.rs

1//! This create provide [`quote!`] macro.
2
3/// The entrypoint with fully backward-compatibility with traditional `quote!`
4/// macro.
5///
6/// This macro is intended to use in your proc-macro, to generate `TokenStream`
7/// expanding variable interporation and expanding templates.
8///
9/// This macro is constructed based on `proc_macro` crate.
10///
11/// # Interporation
12///
13/// For backward compatibility, interporation rule is same as traditional
14/// `quote!` macro. The interporation is done with `#var` (similar to the
15/// variable `$var` in `macro_rules!`). Most variables in `Syn` crate are
16/// interporated using [`::proc_quote::ToTokens`] trait.
17///
18/// ## Rules
19///
20/// Repetition is done using syntax like `#(...)*` or `#(...),*`. It repeats the
21/// variables (`#var`) inside this syntax, which implements
22/// [`::proc_quote::Repeat`].
23///
24/// - `#(...)*` - repeat ... with no separators. at least one variable should be
25///   included in ...
26/// - `#(...),*` - same as before, but interporates with separator ','.
27///
28/// ## Problem
29///
30/// The interporation rule is **rough**, so I implemented new 'template' syntax.
31/// For example, the following code will not allowed, because `#var1` cannot be
32/// iterated double.
33///
34/// ```
35/// # use template_quote::quote;
36/// let var1 = vec!['a', 'b'];
37/// let var2 = vec![vec![1, 2], vec![3, 4]];
38/// let tokens = quote!{
39/// 	#(#(#var1 #var2)*)*
40/// };
41/// assert_eq!("'a' 1i32 'a' 2i32 'b' 3i32 'b' 4i32", tokens.to_string());
42/// ```
43///
44/// # Template syntax
45///
46/// Template syntax is proceedual-like syntax, which allows you to use structual
47/// statementsinside the macro.
48///
49/// ## If syntax
50///
51/// This code iterates around `#i` (with interporation), and emits `i32` into
52/// `TokenStream` while the number meets the condition.
53///
54/// ```
55/// # use template_quote::quote;
56/// let i = vec![1, 2, 3];
57/// let tokens = quote!{
58/// 	#(
59/// 		#(if i > &2) {
60/// 			#i
61/// 		}
62/// 	)*
63/// };
64/// assert_eq!("3i32", tokens.to_string());
65/// ```
66///
67/// The if-else and if-else-if is also allowed.
68///
69/// ```
70/// # use template_quote::quote;
71/// let i = vec![1, 2, 3];
72/// let tokens = quote!{
73/// 	#(
74/// 		#(if i > &2) {
75/// 			+ #i
76/// 		}
77/// 		#(else) {
78/// 			- #i
79/// 		}
80/// 	)*
81/// };
82/// assert_eq!("- 1i32 - 2i32 + 3i32", tokens.to_string());
83/// ```
84///
85/// ```
86/// # use template_quote::quote;
87/// let i = vec![1, 2, 3, 4, 5];
88/// let tokens = quote!{
89/// 	#(
90/// 		#(if i % &2 == 0) {
91/// 			+ #i
92/// 		}
93/// 		#(else if i % &3 == 0) {
94/// 			- #i
95/// 		}
96/// 		#(else) {
97/// 			#i
98/// 		}
99/// 	)*
100/// };
101/// assert_eq!("1i32 + 2i32 - 3i32 + 4i32 5i32", tokens.to_string());
102/// ```
103///
104/// ## For syntax
105///
106/// For syntax iterates around the variable (like interporation), but it
107/// specifies which variable to iterate.
108///
109/// ```
110/// # use template_quote::quote;
111/// let v1 = vec![1, 2];
112/// let v2 = vec!['a', 'b'];
113/// let tokens = quote!{
114/// 	#(for i1 in &v1) {
115/// 		#(for i2 in &v2) {
116/// 			#i1 -> #i2
117/// 		}
118/// 	}
119/// };
120/// assert_eq!("1i32 -> 'a' 1i32 -> 'b' 2i32 -> 'a' 2i32 -> 'b'", tokens.to_string());
121/// ```
122///
123/// Internal loop can be replaced with interporation:
124///
125/// ```
126/// # use template_quote::quote;
127/// let v1 = vec![1, 2];
128/// let v2 = vec!['a', 'b'];
129/// let tokens = quote!{
130/// 	#(for i1 in &v1) {
131/// 		#(
132/// 			#i1 -> #v2
133/// 		)*
134/// 	}
135/// };
136/// assert_eq!("1i32 -> 'a' 1i32 -> 'b' 2i32 -> 'a' 2i32 -> 'b'", tokens.to_string());
137/// ```
138///
139/// You can also specify separator with for statement.
140///
141/// ```
142/// # use template_quote::quote;
143/// let v = vec![1, 2];
144/// let tokens = quote!{
145/// 	#(for i in v) | { #i }
146/// };
147/// assert_eq!("1i32 | 2i32", tokens.to_string());
148/// ```
149///
150/// Interporation is not usable with variables binded in for syntax. For
151/// example,
152///
153/// ```compile_fail
154/// # use template_quote::quote;
155/// let v = vec![vec![1, 2], vec![3]];
156/// let tokens = quote!{
157/// 	#(
158/// 		#(for i in v) { #i }
159/// 	),*
160/// };
161/// assert_eq!("1i32 2i32 , 3i32", tokens.to_string());
162/// ```
163///
164/// will fail into error because no variables is available in the interporation
165/// syntax.
166///
167/// ```text
168/// error: proc macro panicked
169///   --> ***
170///    |
171/// 6  |   let tokens = quote!{
172///    |  ______________^
173/// 7  | |     #(
174/// 8  | |         #(for i in v) { #i }
175/// 9  | |     )*
176/// 10 | | };
177///    | |_^
178///    |
179///    = help: message: Iterative vals not found
180/// ```
181///
182/// In this case, you can use `#(for i in #v)` syntax to specify which variable
183/// to iterate with interporation:
184///
185/// ```
186/// # use template_quote::quote;
187/// let v = vec![vec![1, 2], vec![3]];
188/// let tokens = quote!{
189/// 	#(
190/// 		#(for i in #v) { #i }
191/// 	),*
192/// };
193/// assert_eq!("1i32 2i32 , 3i32", tokens.to_string());
194/// ```
195///
196/// ## While syntax
197///
198/// ```
199/// # use template_quote::quote;
200/// let mut v = vec![1, 2].into_iter();
201/// let tokens = quote!{
202/// 	#(while v.next().is_some()) { hello }
203/// };
204/// assert_eq!("hello hello", tokens.to_string());
205/// ```
206///
207/// ## While-Let syntax
208///
209/// ```
210/// # use template_quote::quote;
211/// let mut v = vec![1, 2].into_iter();
212/// let tokens = quote!{
213/// 	#(while let Some(i) = v.next()) { #i }
214/// };
215/// assert_eq!("1i32 2i32", tokens.to_string());
216/// ```
217///
218/// Same as 'for' syntax, the binded valiables in 'while' is not iteratable with
219/// interporation syntax. For example,
220///
221/// ```compile_fail
222/// # use template_quote::quote;
223/// let mut v = vec![1, 2].into_iter();
224/// quote!{
225/// 	#(
226/// 		#(while let Some(i) = v.next()) { #i }
227/// 	)*
228/// };
229/// ```
230///
231/// will fail.
232///
233/// ## Let syntax
234///
235/// Let syntax bind new variables usable inside the block.
236///
237/// ```
238/// # use template_quote::quote;
239/// let v = vec![(1, 'a'), (2, 'b')];
240/// let tokens = quote!{
241/// 	#(for i in v), {
242/// 		#(let (n, c) = i) {
243/// 			#n -> #c
244/// 		}
245/// 	}
246/// };
247/// assert_eq!("1i32 -> 'a' , 2i32 -> 'b'", tokens.to_string());
248/// ```
249///
250/// Here, `#n` and `#c` is not iteratable with interporation syntax.
251///
252/// ## Inline expression
253///
254/// You can place inline expression in `quote!` macro.
255///
256/// ```
257/// # use template_quote::quote;
258/// let v = vec![1, 2];
259/// let tokens = quote!{
260/// 	#(for i in v){
261/// 		#i -> #{ i.to_string() }
262/// 	}
263/// };
264/// assert_eq!("1i32 -> \"1\" 2i32 -> \"2\"", tokens.to_string());
265/// ```
266///
267/// The following example will fail to compile because it does not understand
268/// which variable to be interpolated:
269///
270/// ```compile_fail
271/// # use template_quote::quote;
272/// let v = vec![1, 2];
273/// let tokens = quote!{
274/// 	#(
275/// 		#{ v.to_string() }
276/// 	)*
277/// };
278/// assert_eq!("\"1\" \"2\"", tokens.to_string());
279/// ```
280///
281/// In this case, you can use `#i` syntax in inline expression to specify which
282/// variable to iterate with interporation syntax.
283///
284/// ```
285/// # use template_quote::quote;
286/// let v = vec![1, 2];
287/// let tokens = quote!{
288/// 	#(
289/// 		#{ #v.to_string() }
290/// 	)*
291/// };
292/// assert_eq!("\"1\" \"2\"", tokens.to_string());
293/// ```
294///
295/// ## Inline statement
296///
297/// You can place arbitrary statement inside this macro. For example,
298///
299/// ```
300/// # use template_quote::quote;
301/// let v = vec![1, 2, 3];
302/// let tokens = quote!{
303/// 	#(
304/// 		#v
305/// 		#{ eprintln!("debug: {}", &v); }
306/// 	)*
307/// };
308/// assert_eq!("1i32 2i32 3i32", tokens.to_string());
309/// ```
310///
311/// will print:
312///
313/// ```text
314/// debug: 1
315/// debug: 2
316/// debug: 3
317/// ```
318///
319/// To be distinguishable, all statements have to end with ';'. For example,
320/// 'if' statement in inline statement syntax should placed with extra ';'.
321///
322/// ```
323/// # use template_quote::quote;
324/// let v = vec![1, 2, 3];
325/// quote!{
326/// 	#(
327/// 		#v
328/// 		#{ if v >= &2 { eprintln!("debug: {}", &v); } ; }
329/// 	)*
330/// };
331/// ```
332///
333/// ## Break, Continue
334///
335/// You can put control statement like `break` or `continue` in inline
336/// statement, but it is a bit danger.
337///
338/// If you use `break;` inside block (like `{ ... }` or `( ... )`), `break` will
339/// suddenly give up emitting whole group, and nothing will be emitted. For
340/// example, the following code does not emit any group:
341///
342/// ```
343/// # use template_quote::quote;
344/// let v = vec![1, 2, 3];
345/// let tokens = quote!{
346/// 	#(for i in v) {
347/// 		#i // this is emitted once
348/// 		// The block is not emitted
349/// 		{
350/// 			#i
351/// 			#{ break; }
352/// 		}
353/// 	}
354/// };
355/// assert_eq!("1i32", tokens.to_string());
356/// ```
357///
358/// `break` also affects on interporation syntax like:
359///
360/// ```
361/// # use template_quote::quote;
362/// let v = vec![1, 2, 3];
363/// let tokens = quote!{
364/// 	#(
365/// 		#v
366/// 		#{ break; }
367/// 	),*
368/// };
369/// assert_eq!("1i32", tokens.to_string());
370/// ```
371///
372/// Unfortunately, `break` will leak outside of `quote!` macro. This is example
373/// which the internal `break` affects on 'for' loop, which is placed outer of
374/// the `quote!` macro.
375///
376/// ```
377/// # use template_quote::quote;
378/// let mut v = Vec::new();
379/// for _ in 0..3 {
380/// 	let tokens = quote!{
381/// 		#{ break; }
382/// 	};
383/// 	v.push(tokens);
384/// }
385/// assert_eq!(v.len(), 0);
386/// ```
387pub use template_quote_impl::quote;
388
389/// [`quote_configured!`] macro is configurable version of [`quote!`].
390///
391/// ```ignore
392/// # use template_quote::quote_configured;
393/// quote_configured! {
394/// 	{
395/// 		proc_macro2: ::proc_macro2,
396/// 		quote: ::quote,
397/// 		core: ::core,	// core crate in std
398/// 		quote: ::quote,
399/// 		span: ::some_span,
400/// 	} =>
401/// 	...
402/// };
403/// ```
404pub use template_quote_impl::quote_configured;
405
406/// [`quote_spanned!`] macro emit `TokenTree` with specified
407/// `Span`.
408///
409/// ```ignore
410/// use syn::Span;
411/// let span = Span::call_site();
412/// let tokens = quote_spanned! {span => ... };
413/// ```
414pub use template_quote_impl::quote_spanned;
415
416pub use imp::Repeat;
417pub use quote::ToTokens;
418
419mod imp {
420	use quote::ToTokens;
421	use std::borrow::Borrow;
422	use std::slice;
423
424	// This trait is from `proc-quote` crate.
425	pub unsafe trait Repeat<T: Iterator> {
426		#[allow(non_snake_case)]
427		#[doc(hidden)]
428		fn __template_quote__as_repeat(self) -> T;
429
430		#[allow(non_snake_case)]
431		#[doc(hidden)]
432		fn __template_quote_is_iterable(&self) -> bool;
433	}
434
435	unsafe impl<T, I: Iterator<Item = T>> Repeat<I> for I {
436		fn __template_quote__as_repeat(self) -> I {
437			self
438		}
439
440		fn __template_quote_is_iterable(&self) -> bool {
441			true
442		}
443	}
444
445	unsafe impl<'a, T: 'a, S: Borrow<[T]>> Repeat<slice::Iter<'a, T>> for &'a S {
446		fn __template_quote__as_repeat(self) -> slice::Iter<'a, T> {
447			(*self).borrow().iter()
448		}
449
450		fn __template_quote_is_iterable(&self) -> bool {
451			true
452		}
453	}
454
455	unsafe impl<'a, T: ToTokens + 'a> Repeat<ToTokensRepeat<'a, T>> for &'a T {
456		fn __template_quote__as_repeat(self) -> ToTokensRepeat<'a, T> {
457			ToTokensRepeat(self)
458		}
459
460		fn __template_quote_is_iterable(&self) -> bool {
461			false
462		}
463	}
464
465	pub struct ToTokensRepeat<'a, T: ToTokens + 'a>(&'a T);
466	impl<'a, T: ToTokens + 'a> Iterator for ToTokensRepeat<'a, T> {
467		type Item = &'a T;
468		fn next(&mut self) -> Option<Self::Item> {
469			Some(self.0)
470		}
471	}
472}