Commit fd8df75f authored by Rahix's avatar Rahix 🦀

Use quote to generate the proc-macro output

parent 67cef272
extern crate proc_macro;
use std::str::FromStr;
use proc_macro::TokenStream;
use quote::{ToTokens};
use syn::{ReturnType, parse_macro_input};
fn wrap_function(token_stream: TokenStream, attr: TokenStream) -> TokenStream {
let mut function = parse_macro_input!(token_stream as syn::ItemFn);
let output = function.sig.output;
function.sig.output = ReturnType::Default;
//let prepend = format!("match || {} {{ ", output.to_token_stream().to_string());
//let append = "}() { Ok(_) => {}, Err(err) => println!(\"{}\", err), }";
let prepend = format!("crate::error::handle_system_result(|| {} {{ ", output.to_token_stream().to_string());
let append = "})";
let mut function_block_str = function.block.to_token_stream().to_string();
function_block_str.insert_str(1, &prepend);
function_block_str.insert_str(function_block_str.len() - 2, append);
println!("{}", function_block_str);
let function_block_token_stream = TokenStream::from_str(&function_block_str).unwrap();
let function_block = parse_macro_input!(function_block_token_stream as syn::Block);
function.block = Box::new(function_block);
let attr_str: String = attr.to_string();
let legion_system_str = if attr_str.is_empty() {
"#[legion::system]".to_string()
} else {
format!("#[legion::system({})]", attr_str)
};
let new_function_string = format!("{} {}", legion_system_str, function.to_token_stream().to_string());
println!("{}", new_function_string);
TokenStream::from_str(&new_function_string).unwrap()
}
#[proc_macro_attribute]
pub fn angel_system(attr: TokenStream, item: TokenStream) -> TokenStream {
println!("attr: \"{}\"", attr.to_string());
println!("item: \"{}\"", item.to_string());
wrap_function(item, attr)
pub fn angel_system(args: TokenStream, input: TokenStream) -> TokenStream {
let f = syn::parse_macro_input!(input as syn::ItemFn);
let fname = f.sig.ident;
let attrs = f.attrs;
let inputs = f.sig.inputs;
let block = f.block;
let stmts = block.stmts;
let rtype = f.sig.output;
let vis = f.vis;
let legion_attr = if !args.is_empty() {
let args: proc_macro2::TokenStream = args.into();
quote::quote!(#[legion::system(#args)])
} else {
quote::quote!(#[legion::system])
};
quote::quote!(
#legion_attr
#(#attrs)*
#vis fn #fname(#inputs) {
crate::error::handle_system_result(|| #rtype {
#(#stmts)*
});
}
)
.into()
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment