Rust
attribute macro
Write an attribute macro with #[proc_macro_attribute].
Attribute macros
Attribute macros take the whole item they mark and put whatever they want in its place. They also take the attribute's own arguments:
#[proc_macro_attribute]
pub fn olcumle(arg: TokenStream, oge: TokenStream) -> TokenStream {
let mut f = syn::parse_macro_input!(oge as syn::ItemFn);
let ad = f.sig.ident.to_string();
let govde = &f.block;
f.block = syn::parse_quote!({
println!("{} çağrıldı", #ad);
#govde
});
quote::quote!(#f).into()
}
// usage:
#[olcumle]
fn kare(x: i32) -> i32 { x * x }
#[tokio::main], things like #[test], and #[get("/")] in web frameworks are attribute macros.
Wrapping with macro_rules!
We can do the same transformation with macro_rules! by passing the function to the macro as an argument:
macro_rules! olcumle {
(fn $ad:ident($($arg:ident : $tur:ty),*) -> $don:ty $govde:block) => {
fn $ad($($arg: $tur),*) -> $don {
println!("{} çağrıldı", stringify!($ad));
$govde
}
};
}
olcumle! {
fn kare(x: i32) -> i32 { x * x }
}
$govde:block captures the braced body as a single piece.
Exercise Report the call
Write the olcumle! macro above and define the function fn kare(x: i32) -> i32 { x * x } with it. In main, print the result of kare(4).
Show example solution
macro_rules! olcumle {
(fn $ad:ident($($arg:ident : $tur:ty),*) -> $don:ty $govde:block) => {
fn $ad($($arg: $tur),*) -> $don {
println!("{} çağrıldı", stringify!($ad));
$govde
}
};
}
olcumle! {
fn kare(x: i32) -> i32 {
x * x
}
}
fn main() {
let s = kare(4);
println!("{}", s);
}
Test yourself
-
What happens if an attribute macro takes the function but doesn't put it in the output?
- It warns
- The function disappears from the program
- The compiler adds it back
- Panic
Show answer
The function disappears from the program — An attribute macro fully replaces the item; preserving the original item is the macro's responsibility.
-
Capture the body
(fn $ad:ident($($arg:ident : $tur:ty),*) -> $don:ty $govde:____) => { .. }
Show answer
(fn $ad:ident($($arg:ident : $tur:ty),*) -> $don:ty $govde:block) => { .. }
-
Attribute and role
- #[proc_macro_attribute]
- Defines an attribute macro
- arg: TokenStream
- Attribute arguments
- oge: TokenStream
- The marked item
- syn::ItemFn
- Function tree
Next lesson: syn and quote