Skip to content

Instantly share code, notes, and snippets.

@rebo
Created May 31, 2020 21:06
Show Gist options
  • Select an option

  • Save rebo/3148bde9f7145c8e22f4acca08bffdad to your computer and use it in GitHub Desktop.

Select an option

Save rebo/3148bde9f7145c8e22f4acca08bffdad to your computer and use it in GitHub Desktop.
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