pulley_macros/
interp_disable_if_cfg.rs1use proc_macro::TokenStream;
2use quote::{ToTokens, TokenStreamExt, quote};
3use syn::{
4 Attribute, Result, Signature, Visibility, braced,
5 parse::{Parse, ParseStream},
6 parse_macro_input, token,
7};
8
9pub fn run(attrs: TokenStream, item: TokenStream) -> TokenStream {
10 let mut cfg = None;
11
12 let config_parser = syn::meta::parser(|meta| {
13 cfg = Some(meta.path.require_ident()?.clone());
14 Ok(())
15 });
16
17 parse_macro_input!(attrs with config_parser);
18
19 match expand(cfg.unwrap(), parse_macro_input!(item as Fn)) {
20 Ok(tok) => tok,
21 Err(e) => e.into_compile_error().into(),
22 }
23}
24
25struct Fn {
29 attrs: Vec<Attribute>,
30 visibility: Visibility,
31 sig: Signature,
32 body: Block,
33}
34
35impl Parse for Fn {
36 fn parse(input: ParseStream) -> Result<Self> {
37 let attrs = input.call(Attribute::parse_outer)?;
38 let visibility: Visibility = input.parse()?;
39 let sig: Signature = input.parse()?;
40 let body: Block = input.parse()?;
41
42 Ok(Self {
43 attrs,
44 visibility,
45 sig,
46 body,
47 })
48 }
49}
50
51impl ToTokens for Fn {
52 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
53 for attr in &self.attrs {
54 attr.to_tokens(tokens);
55 }
56 self.visibility.to_tokens(tokens);
57 self.sig.to_tokens(tokens);
58 self.body.to_tokens(tokens);
59 }
60}
61
62struct Block {
64 brace: token::Brace,
65 rest: proc_macro2::TokenStream,
66}
67
68impl Parse for Block {
69 fn parse(input: ParseStream) -> Result<Self> {
70 let content;
71 Ok(Self {
72 brace: braced!(content in input),
73 rest: content.parse()?,
74 })
75 }
76}
77
78impl ToTokens for Block {
79 fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
80 self.brace.surround(tokens, |tokens| {
81 tokens.append_all(self.rest.clone());
82 });
83 }
84}
85
86fn expand(cfg: syn::Ident, func: Fn) -> Result<TokenStream> {
87 let Fn {
88 attrs,
89 visibility,
90 sig,
91 body: _,
92 } = &func;
93 let name = &sig.ident;
94 Ok(quote! {
95 #[cfg(#cfg)]
96 #(#attrs)*
97 #[allow(unused_variables)]
98 #visibility #sig {
99 self.done_trap_kind::<crate::#name>(Some(TrapKind::DisabledOpcode))
100 }
101
102 #[cfg(not(#cfg))]
103 #func
104 }
105 .into())
106}