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
#[macro_use]
extern crate nom;
use proc_macro::TokenStream;
use syn::punctuated::Punctuated;
use syn::{
parse::{Parse, ParseBuffer},
spanned::Spanned,
Token,
};
mod generator;
mod parser;
#[proc_macro]
pub fn derive(input: TokenStream) -> TokenStream {
let Args {
avx,
pairs,
print,
simd,
} = match syn::parse::<Builder>(input).and_then(Builder::build) {
Ok(s) => s,
Err(e) => return e.to_compile_error().into(),
};
let code = generator::generate(&parser::parse(&pairs), simd, avx);
if print {
eprintln!("{}", code);
}
code.parse().unwrap()
}
struct Args {
pairs: String,
avx: bool,
print: bool,
simd: bool,
}
struct MetaOpt<Lit: Parse> {
pub path: syn::Path,
pub eq_token: Token![=],
pub lit: Lit,
}
impl<Lit: Parse> Parse for MetaOpt<Lit> {
fn parse<'a>(input: &'a ParseBuffer<'a>) -> syn::Result<Self> {
Ok(Self {
path: input.parse()?,
eq_token: input.parse()?,
lit: input.parse()?,
})
}
}
struct Builder {
pub pairs: syn::LitStr,
pub comma: Option<Token![,]>,
pub opts: Punctuated<MetaOpt<syn::LitBool>, Token![,]>,
}
impl Parse for Builder {
fn parse<'a>(input: &'a ParseBuffer<'a>) -> syn::Result<Self> {
Ok(Self {
pairs: input.parse()?,
comma: input.parse()?,
opts: Punctuated::parse_terminated(input)?,
})
}
}
impl Builder {
fn build(self) -> syn::Result<Args> {
let Builder { pairs, opts, .. } = self;
let mut avx = true;
let mut print = false;
let mut simd = true;
for MetaOpt { path, lit, .. } in opts {
if path.is_ident("avx") {
avx = lit.value
} else if path.is_ident("print") {
print = lit.value;
} else if path.is_ident("simd") {
simd = lit.value;
} else {
return Err(syn::Error::new(
path.span(),
format!("invalid attribute '{:?}'", path.get_ident()),
));
}
}
Ok(Args {
pairs: pairs.value(),
avx,
print,
simd,
})
}
}