1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
// force-host
// no-prefer-dynamic
#![crate_type = "proc-macro"]
extern crate proc_macro;
use proc_macro::{Ident, Group, TokenStream, TokenTree as Tt};
// This constant has to be above the ALLOCATING_ALGO_THRESHOLD
// constant in inherent_impls_overlap.rs
const REPEAT_COUNT: u32 = 501;
#[proc_macro]
/// Repeats the input many times, while replacing idents
/// named "IDENT" with "id_$v", where v is a counter.
pub fn repeat_with_idents(input: TokenStream) -> TokenStream {
let mut res = Vec::new();
fn visit_stream(res: &mut Vec<Tt>, stream :TokenStream, v: u32) {
let mut stream_iter = stream.into_iter();
while let Some(tt) = stream_iter.next() {
match tt {
Tt::Group(group) => {
let tt = Tt::Group(visit_group(group, v));
res.push(tt);
},
Tt::Ident(id) => {
let id = if &id.to_string() == "IDENT" {
Ident::new(&format!("id_{}", v), id.span())
} else {
id
};
res.push(Tt::Ident(id));
},
Tt::Punct(p) => {
res.push(Tt::Punct(p));
},
Tt::Literal(lit) => {
res.push(Tt::Literal(lit));
},
}
}
}
fn visit_group(group :Group, v: u32) -> Group {
let mut res = Vec::new();
visit_stream(&mut res, group.stream(), v);
let stream = res.into_iter().collect();
let delim = group.delimiter();
Group::new(delim, stream)
}
for v in 0 .. REPEAT_COUNT {
visit_stream(&mut res, input.clone(), v)
}
res.into_iter().collect()
}
|