0

I'm making a macro to iterate over any tuple of components in my ECS.

In the main lines, here is how it goes :

for (pos: &Position, vel: &Velocity) in iterate_over_components!(components; Position, Velocity) {[...]}

Where Position and Velocity are structs.

For now, I'm having two iterator: a immutable one and a mutable one. I would like to merge them into one, specifying which components are mutable.

for (pos: &mut Position, vel: &Velocity) in iterate_over_components!(components; mut Position, Velocity) {[...]}

Currently, the rule is parsed like this :

($components:expr; $($comp:ident),+) => {[...]}

And I match the different components like so :

$(
     $comp,
)+

Do I have a way to read any mut keyword in front of my declarations of multiple components ? How do I change the generated code depending on the presence of such a keyword ?

I've seen here that I would need a separate rule to match both, but in my case I don't know what components will be mutable, so I would like a way to change the generated code accordingly.

If any one want to take a look, here is the full macro, in the ECS lib.

Some edits after looking throught TT-munching :

I'm trying to pass each component or mut component as tt, but I still can't match other macros. A simple example :

#[macro_export]
macro_rules! get_component {
    ($components:expr; mut $comp:ident) => {
        "mut".to_string()
    };
    ($components:expr; $comp:ident) => {
        "imm".to_string()
    };
}

#[macro_export]
macro_rules! get_components {
    ($components:expr; $($comp:tt),+) => {
        {
            $(
                get_component!($components; $comp);
            )+
        }
    }
}

Can't match :

get_components!(&mut world.components; Component1, mut Component2);

I'm having an error on Component2 :

no rules expected the token Component2 while trying to match ,

1 Answers1

1

You need to use TT munching and match the components one-by-one.

Chayim Friedman
  • 47,971
  • 5
  • 48
  • 77
  • The given expression does not work on my side (it fails to parse the Ident after the "mut", expecting a comma). – LucioleMaléfique Mar 06 '23 at 10:07
  • @LucioleMaléfique Right, this is my mistake. Updated the answer. – Chayim Friedman Mar 06 '23 at 10:13
  • @LucioleMaléfique This is not how TT munching works, you need to use [something like that](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=b2cec471c3541ee35a2594cebaf23d94). – Chayim Friedman Mar 06 '23 at 10:15
  • I've been trying to use your example, but I'm still having errors when trying to build a tuple. I've made an example of the issue I'm having in the playground : https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=430a8c1851679c4748226306d5ed275b – LucioleMaléfique Mar 06 '23 at 11:41
  • @LucioleMaléfique Macros can only expand to whole items. You need to use [push-down accumulation](https://veykril.github.io/tlborm/decl-macros/patterns/push-down-acc.html). – Chayim Friedman Mar 06 '23 at 19:27