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
extern crate proc_macro;
use proc_macro::TokenStream;
use std::str::FromStr;
enum PreOrPostFix {
Pre(String),
Post(String),
}
#[proc_macro]
pub fn nested_iter_yield(item: TokenStream) -> TokenStream {
let item_string = item.to_string();
let inps = item_string.split(",").collect::<Vec<_>>();
let source_iter = inps[0].trim();
let n = usize::from_str(inps[1].trim())
.expect("nested_iter_yield: could not parse input n as usize.");
let value_transformation = match inps.len() {
2 => None,
l if l > 2 => Some(match inps[2] {
m if m.starts_with(".") => PreOrPostFix::Post(inps[2].to_string()),
_ => PreOrPostFix::Pre(inps[2].to_string()),
}),
_ => unreachable!("missing input fields to nested_iter_yield macro"),
};
let generator_open = "genawaiter::sync::Gen::new(|co| async move {".to_string();
let open_loops = (0..n)
.map(|i| format!("for val_{i} in {source_iter} {{"))
.collect::<Vec<_>>()
.join("\n");
let yield_open = "co.yield_(vec![";
let yield_args = (0..n)
.map(|i| format!("val_{i}"))
.map(|variable| match &value_transformation {
None => variable,
Some(trans) => match trans {
PreOrPostFix::Pre(pre) => pre.to_string() + variable.as_str(),
PreOrPostFix::Post(post) => variable + post.as_str(),
},
})
.collect::<Vec<_>>()
.join(", ");
let yield_close = "]).await;";
let close_loops = (0..n).map(|_| "}").collect::<Vec<_>>().join("\n");
let generator_closed = "})";
let generated_code = generator_open
+ open_loops.as_str()
+ yield_open
+ yield_args.as_str()
+ yield_close
+ close_loops.as_str()
+ generator_closed;
generated_code.parse().unwrap()
}