Created
May 31, 2020 21:06
-
-
Save rebo/3148bde9f7145c8e22f4acca08bffdad to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| extern crate proc_macro; | |
| use self::proc_macro::TokenStream; | |
| use quote::{format_ident, quote}; | |
| use syn::parse::{Parse, ParseStream, Result}; | |
| use syn::{parse_macro_input, Expr}; | |
| use syn::{ItemFn}; | |
| #[proc_macro_attribute] | |
| pub fn view_macro(_args: TokenStream, input: TokenStream) -> TokenStream { | |
| let input_fn: ItemFn = syn::parse_macro_input!(input); | |
| let macro_impl_quote = quote! { | |
| #[macro_export] | |
| #[allow(unused_macros)] | |
| macro_rules! rando_macro { | |
| ( $($ part:expr),* $(,)? ) => { | |
| { | |
| $ ( | |
| // process_part will transform each part | |
| // specifically if its a macro, call a different macro, | |
| // if its an expression it will simply return it | |
| process_part!($ part); | |
| )* | |
| } | |
| }; | |
| } | |
| }; | |
| quote::quote!( | |
| #macro_impl_quote | |
| #input_fn | |
| ) | |
| .into() | |
| } | |
| enum ProcessPart { | |
| Macro(ProcessPartMacro), | |
| Other(ProcessPartOther), | |
| } | |
| struct ProcessPartMacro { | |
| ident: syn::Ident, | |
| tokens: TokenStream, | |
| } | |
| struct ProcessPartOther { | |
| expr: Expr, | |
| } | |
| impl Parse for ProcessPart { | |
| fn parse(input: ParseStream) -> Result<Self> { | |
| let expr :Expr = input.parse()?; | |
| match expr { | |
| Expr::Group(expr_group) => { | |
| match *expr_group.expr { | |
| Expr::Macro(expr_macro) => { | |
| let path = expr_macro.mac.path.clone(); | |
| let ident = path.clone().get_ident().clone().expect("expr_macro inside Expr::Macro to exist").clone(); | |
| let tokens = expr_macro.mac.tokens.clone(); | |
| Ok(ProcessPart::Macro(ProcessPartMacro { | |
| ident: ident, | |
| tokens: tokens.into(), | |
| })) | |
| } | |
| exp => { | |
| Ok(ProcessPart::Other(ProcessPartOther { | |
| expr: exp.clone(), | |
| })) | |
| } | |
| } | |
| } | |
| _exp => { | |
| panic!("This is unimplemented you should never get here!{:#?}", _exp); | |
| } | |
| } | |
| } | |
| } | |
| #[proc_macro] | |
| pub fn process_part(input: TokenStream) -> TokenStream { | |
| let properties = parse_macro_input!(input as ProcessPart); | |
| match properties { | |
| ProcessPart::Macro(m) => { | |
| let global_macro_ident = format_ident!("some_rando_global_name_hohoho_{}", m.ident); | |
| let tokens: proc_macro2::TokenStream = m.tokens.into(); | |
| quote!( | |
| #global_macro_ident![#tokens] | |
| ).into() | |
| } | |
| ProcessPart::Other(ProcessPartOther{expr}) => { | |
| let exp = quote!( | |
| #expr | |
| ); | |
| exp.into() | |
| } | |
| } | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment