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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
use proc_macro2::{Span, TokenStream};
use quote::{quote, ToTokens};
use syn::{
parse::{Parse, ParseStream},
parse_macro_input, Block, LitInt, Result,
};
use syn::{parse2, Ident};
extern crate proc_macro;
struct SimpleCodeLoop {
loops: usize,
block: Block,
}
impl Parse for SimpleCodeLoop {
fn parse(input: ParseStream) -> Result<Self> {
let loops: LitInt = input.parse()?;
let block: Block = input.parse()?;
let loops: usize = loops.base10_parse()?;
Ok(Self { loops, block })
}
}
struct AdvancedCodeLoop {
index_variable: Ident,
loops: usize,
number_type: Ident,
block: Block,
}
impl Parse for AdvancedCodeLoop {
fn parse(input: ParseStream) -> Result<Self> {
let index_variable: Ident = input.parse()?;
let number_type: Ident = input
.parse()
.unwrap_or_else(|_| Ident::new("usize", Span::call_site()));
let loops: LitInt = input.parse()?;
let block: Block = input.parse()?;
let loops: usize = loops.base10_parse()?;
Ok(Self {
index_variable,
loops,
number_type,
block,
})
}
}
#[proc_macro]
pub fn repeat(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let input = TokenStream::from(input);
if let Ok(code_loop) = parse2::<AdvancedCodeLoop>(input.clone()) {
let mut code = TokenStream::new();
for i in 0..code_loop.loops {
let block = &code_loop.block;
let variable = &code_loop.index_variable;
let kind = &code_loop.number_type;
let lit = LitInt::new(&i.to_string(), Span::call_site());
quote! {
{
const #variable: #kind = #lit;
#block
}
}
.to_tokens(&mut code);
}
code.into()
} else {
let input: proc_macro::TokenStream = input.into();
let code_loop = parse_macro_input!(input as SimpleCodeLoop);
let mut blocks = TokenStream::new();
for _ in 0..code_loop.loops {
code_loop.block.to_tokens(&mut blocks);
}
blocks.into()
}
}