Jean Lopes
Jean Lopes

Reputation: 33

Can I execute a function inside a declarative macro?

I'm stuck trying to "rename" a identifier inside a declarative macro, I have the renaming function already, but can't find a way to "execute" it inside the macro. Is this possible with declarative macros?

Example:

fn to_pascal_case(s: &str) -> String { ... }

macro_rules! test_gl_enum {
    ($n: ident) => { struct to_pascal_case(stringify!($n)); }
}

test_gl_enum!(VERTEX_SHADER);

expands to:

struct to_pascal_case(());

desired result would be:

struct VertexShader;

Upvotes: 0

Views: 1262

Answers (1)

cameron1024
cameron1024

Reputation: 10216

You can't execute arbitrary code in a declarative macro. You have a couple of options:

Proc Macro

Proc macros are basically just functions that take a TokenStream and return a TokenStream (with some variations between function-like, attribute and derive macros). They can contain arbitrary code, so you could absolutely parse the identifier and apply some transformation to it.

If you're going to take this route, you will likely want to use syn and quote, and I'd also very strongly recommend going through the proc macro workshop, which is a series of exercises to teach you the basics.

Or use a crate

As is often the case, someone else has also had this problem, and has written a crate for it: https://crates.io/crates/casey

With that, you can write:

use casey::*;

macro_rules! test_gl_enum {
  ($n:ident) => {
    struct pascal!($n);
  };
}

Here, pascal!() is a proc macro that does the transformation, and since it's a macro (rather than a function) it is also evaluated at compile time, so the expansion won't look like struct pascal!(my_enum_name);

Upvotes: 3

Related Questions