![](/img/trans.png)
[英]How to parse other attributes in custom rust proc_macro attribute?
[英]How to provide an enumerated index to a macro interpolation function in quote with proc_macro?
我已經實現了以下 proc_macro
builtin_method!(hello_world(a, b, c) {
println!("{} {} {}", a, b, c);
}
並且應該生成
pub fn hello_world(args: Vec<String>) {
let a = args.get(0).unwrap();
let b = args.get(1).unwrap();
let c = args.get(2).unwrap();
println!("{} {} {}", a, b, c);
}
這是我當前的代碼。
use proc_macro::TokenStream;
use quote::quote;
use syn;
struct BuiltinDef {
function: syn::Ident,
arguments: Vec<syn::Ident>,
body: syn::Block,
}
impl syn::parse::Parse for BuiltinDef {
fn parse(stream: syn::parse::ParseStream) -> syn::Result<Self> {
let function: syn::Ident = stream.parse()?;
let content;
let _: syn::token::Paren = syn::parenthesized!(content in stream);
let arguments: syn::punctuated::Punctuated<syn::Ident, syn::Token![,]> =
content.parse_terminated(syn::Ident::parse)?;
let body: syn::Block = stream.parse()?;
Ok(BuiltinDef {
function,
arguments: arguments.into_iter().collect(),
body,
})
}
}
#[proc_macro]
pub fn builtin_method(input: TokenStream) -> TokenStream {
let def = syn::parse_macro_input!(input as BuiltinDef);
let function = def.function;
let arguments = def.arguments;
let body = def.body;
let gen = quote! {
pub fn #function(args: Vec<String>) {
let mut _i = 0;
#(
let mut #arguments = args.get(_i).unwrap().clone();
_i += 1;
)*
#body
}
};
TokenStream::from(gen)
}
在變量插值中,我需要某種枚舉變量計數。 根據文檔,沒有這種方法。
我怎樣才能更好地實現這一點而不是數數_i
?
let mut _i = 0;
#(
let mut #arguments = args.get(_i).unwrap().clone();
_i += 1;
)*
使用標准Iterator::enumerate()
:
let arguments = arguments.into_iter().enumerate().map(|(index, arg)| quote! {
let mut #arg = args.get(#index).unwrap().clone();
});
let gen = quote! {
pub fn #function(args: Vec<String>) {
let mut _i = 0;
#(#arguments)*
#body
}
};
好的,在遵循https://stackoverflow.com/a/70939071/694705之后,我能夠通過將 arguments 收集回Vec<proc_macro2::TokenStream>
來實現它。
這是我的解決方案:
let arguments: Vec<proc_macro2::TokenStream> =
arguments
.into_iter()
.enumerate()
.map(|(idx, arg)| {
quote! {
let mut #arg = args.get(#idx).unwrap().clone();
}
})
.collect();
let gen = quote! {
pub fn #function(args: Vec<String>) {
#(#arguments)*
#body
}
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.