Path: blob/main/pulley/macros/src/interp_disable_if_cfg.rs
1692 views
use proc_macro::TokenStream;1use quote::{ToTokens, TokenStreamExt, quote};2use syn::{3Attribute, Result, Signature, Visibility, braced,4parse::{Parse, ParseStream},5parse_macro_input, token,6};78pub fn run(attrs: TokenStream, item: TokenStream) -> TokenStream {9let mut cfg = None;1011let config_parser = syn::meta::parser(|meta| {12cfg = Some(meta.path.require_ident()?.clone());13Ok(())14});1516parse_macro_input!(attrs with config_parser);1718match expand(cfg.unwrap(), parse_macro_input!(item as Fn)) {19Ok(tok) => tok,20Err(e) => e.into_compile_error().into(),21}22}2324/// Custom function parser.25/// Parses the function's attributes, visibility and signature, leaving the26/// block as an opaque [`TokenStream`].27struct Fn {28attrs: Vec<Attribute>,29visibility: Visibility,30sig: Signature,31body: Block,32}3334impl Parse for Fn {35fn parse(input: ParseStream) -> Result<Self> {36let attrs = input.call(Attribute::parse_outer)?;37let visibility: Visibility = input.parse()?;38let sig: Signature = input.parse()?;39let body: Block = input.parse()?;4041Ok(Self {42attrs,43visibility,44sig,45body,46})47}48}4950impl ToTokens for Fn {51fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {52for attr in &self.attrs {53attr.to_tokens(tokens);54}55self.visibility.to_tokens(tokens);56self.sig.to_tokens(tokens);57self.body.to_tokens(tokens);58}59}6061/// A generic function body represented as a braced [`TokenStream`].62struct Block {63brace: token::Brace,64rest: proc_macro2::TokenStream,65}6667impl Parse for Block {68fn parse(input: ParseStream) -> Result<Self> {69let content;70Ok(Self {71brace: braced!(content in input),72rest: content.parse()?,73})74}75}7677impl ToTokens for Block {78fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {79self.brace.surround(tokens, |tokens| {80tokens.append_all(self.rest.clone());81});82}83}8485fn expand(cfg: syn::Ident, func: Fn) -> Result<TokenStream> {86let Fn {87attrs,88visibility,89sig,90body: _,91} = &func;92let name = &sig.ident;93Ok(quote! {94#[cfg(#cfg)]95#(#attrs)*96#[allow(unused_variables)]97#visibility #sig {98self.done_trap_kind::<crate::#name>(Some(TrapKind::DisabledOpcode))99}100101#[cfg(not(#cfg))]102#func103}104.into())105}106107108