#[macro_export] macro_rules! system { ($name:ident $pat:tt => $($rest:tt)* ) => { struct $name; impl<'a> specs::System<'a> for $name { type SystemData = args_to_systemdata!($pat); fn run(&mut self, args_to_pat!($pat): Self::SystemData) { for args_to_pat!($pat) in args_to_join!($pat).join() { $($rest)* } } } }; } #[macro_export] macro_rules! args_to_systemdata { ( ( $name:ident : $ty:ty ) ) => { ( specs::ReadStorage<'a, $ty> ,) }; ( ( mut $name:ident : $ty:ty ) ) => { ( specs::WriteStorage<'a, $ty> ,) }; ( ( $name:ident : $ty:ty , $($tok:tt)* ) ) => { ( specs::ReadStorage<'a, $ty>, args_to_systemdata!( ( $( $tok )* ) ) ) }; ( ( mut $name:ident : $ty:ty , $( $tok:tt )* ) ) => { ( specs::WriteStorage<'a, $ty>, args_to_systemdata!( ( $( $tok )* ) ) ) }; } #[macro_export] macro_rules! args_to_pat { ( ( $name:ident : $ty:ty ) ) => { ( $name ,) }; ( ( mut $name:ident : $ty:ty ) ) => { ( mut $name ,) }; ( ( $name:ident : $ty:ty , $($tok:tt)* ) ) => { ( $name, args_to_pat!( ( $($tok)* ) ) ) }; ( ( $name:ident : $ty:ty , $($tok:tt)* ) ) => { ( mut $name, args_to_pat!( ( $($tok)* ) ) ) }; } #[macro_export] macro_rules! args_to_join { ( ( $name:ident : $ty:ty ) ) => { ( & $name ,) }; ( ( mut $name:ident : $ty:ty ) ) => { ( &mut $name ,) }; ( ( $name:ident : $ty:ty , $($tok:tt)* ) ) => { ( & $name, args_to_join!( ( $($tok)* ) ) ) }; ( ( $name:ident : $ty:ty , $($tok:tt)* ) ) => { ( &mut $name, args_to_join!( ( $($tok)* ) ) ) }; } #[cfg(test)] mod tests { use specs::join::Join; struct Pos { x: usize, } impl specs::Component for Pos { type Storage = specs::VecStorage; } struct Mov; impl specs::Component for Mov { type Storage = specs::VecStorage; } system!{ Foo (_x: Mov, mut y: Pos) => y.x += 1; } }