How to get body inside a function in macro rules

How to get body inside a function in macro rules as well function name?

Example

fn greet_fn(name:String) {
    let mut greet = String::from("Hello ");
    greet.push_str(name);
}

So in this case how can I get the body of that function which will be

let mut greet = String::from("Hello ");
greet.push_str(name);

So how the macro rules will be ?

I think the easiest way to do this would be to write a macro which matches something that looks like a function signature followed by a block.

macro_rules! print_body {
  (fn $name:ident (
      $( $arg:ident : $arg_type:ty ),* $(,)?
    )  $(-> $ret:ty )? {
      $( $body:stmt );* $(;)?
    }) => {
    $(
        println!("{}", stringify!($body));
    )*
  }
}

fn main() {
    print_body! {
        fn greet_fn(name:String) {
            let mut greet = String::from("Hello ");
            greet.push_str(name);
        }
    }
}

(playground)

Unfortunately, the resulting code tends to be borderline unreadable. Often my solution is the more verbose TT muncher.

Breaking down a function like that may be easier to achieve with a procedural macro - doing it that way, you'd be able to lean on crates like syn and quote to break down the input code.

Also, when you talk about getting function names and stuff like that: it's important to understand that macros operate purely based on the individual tokens of the code (i.e. fn, then greet_fn, then (, then name, then :, and so on...). You can't 'look up' a name in a macro, as name resolution hasn't taken place at the point in compilation where they run. I'm not sure if that's what you're trying to do, though!

1 Like

Hi
Can you please give me a snippet of how this will be in proc macro ?
Thank you

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.