lib.rs 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. #[macro_export]
  2. macro_rules! system {
  3. ($name:ident ( $($pat:tt)* ) { $($rest:tt)* } ) => {
  4. pub struct $name;
  5. impl<'a> specs::System<'a> for $name {
  6. type SystemData = args_to_systemdata!(($($pat)*,));
  7. fn run(&mut self, args_to_fn_pat!(($($pat)*)): Self::SystemData) {
  8. for args_to_join_pat!(($($pat)*,)) in args_to_join!(($($pat)*,)).join() {
  9. $($rest)*
  10. }
  11. }
  12. }
  13. };
  14. ($name:ident $pat:tt { $($rest:tt)* } finally { $($finally:tt)* }) => {
  15. pub struct $name;
  16. impl<'a> specs::System<'a> for $name {
  17. type SystemData = args_to_systemdata!($pat);
  18. fn run(&mut self, args_to_fn_pat!($pat): Self::SystemData) {
  19. for args_to_join_pat!($pat) in args_to_join!($pat).join() {
  20. $($rest)*
  21. }
  22. $($finally)*
  23. }
  24. }
  25. };
  26. }
  27. #[macro_export]
  28. macro_rules! args_to_systemdata {
  29. ( ( $name:ident : $ty:ty $(,)? ) ) => {
  30. ( specs::ReadStorage<'a, $ty> ,)
  31. };
  32. ( ( mut $name:ident : $ty:ty $(,)? ) ) => {
  33. ( specs::WriteStorage<'a, $ty> ,)
  34. };
  35. ( ( resource $name:ident : $ty:ty $(,)? ) ) => {
  36. compile_error!("Resources cannot come at the end of the argument block.")
  37. };
  38. ( ( resource mut $name:ident : $ty:ty $(,)? ) ) => {
  39. compile_error!("Resources cannot come at the end of the argument block.")
  40. };
  41. ( ( $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  42. ( specs::ReadStorage<'a, $ty>, args_to_systemdata!( ( $( $tok )* ) ) )
  43. };
  44. ( ( mut $name:ident : $ty:ty , $( $tok:tt )* ) ) => {
  45. ( specs::WriteStorage<'a, $ty>, args_to_systemdata!( ( $( $tok )* ) ) )
  46. };
  47. ( ( resource $name:ident : $ty:ty , $( $tok:tt )* ) ) => {
  48. ( specs::ReadExpect<'a, $ty>, args_to_systemdata!( ( $( $tok )* ) ) )
  49. };
  50. ( ( resource mut $name:ident : $ty:ty , $( $tok:tt )* ) ) => {
  51. ( specs::WriteExpect<'a, $ty>, args_to_systemdata!( ( $( $tok )* ) ) )
  52. };
  53. }
  54. #[macro_export]
  55. macro_rules! args_to_fn_pat {
  56. ( ( $name:ident : $ty:ty $(,)? ) ) => {
  57. ( $name ,)
  58. };
  59. ( ( mut $name:ident : $ty:ty $(,)? ) ) => {
  60. ( mut $name ,)
  61. };
  62. ( ( resource $name:ident : $ty:ty $(,)? ) ) => {
  63. compile_error!("Resources cannot come at the end of the argument block.")
  64. };
  65. ( ( resource mut $name:ident : $ty:ty $(,)? ) ) => {
  66. compile_error!("Resources cannot come at the end of the argument block.")
  67. };
  68. ( ( $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  69. ( $name, args_to_fn_pat!( ( $($tok)* ) ) )
  70. };
  71. ( ( mut $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  72. ( mut $name, args_to_fn_pat!( ( $($tok)* ) ) )
  73. };
  74. ( ( resource $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  75. ( $name, args_to_fn_pat!( ( $($tok)* ) ) )
  76. };
  77. ( ( resource mut $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  78. ( mut $name, args_to_fn_pat!( ( $($tok)* ) ) )
  79. };
  80. }
  81. #[macro_export]
  82. macro_rules! args_to_join_pat {
  83. ( ( $name:ident : $ty:ty $(,)? ) ) => {
  84. ( $name ,)
  85. };
  86. ( ( mut $name:ident : $ty:ty $(,)? ) ) => {
  87. ( mut $name ,)
  88. };
  89. ( ( resource $name:ident : $ty:ty $(,)? ) ) => {
  90. compile_error!("Resources cannot come at the end of the argument block.")
  91. };
  92. ( ( resource mut $name:ident : $ty:ty $(,)? ) ) => {
  93. compile_error!("Resources cannot come at the end of the argument block.")
  94. };
  95. ( ( $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  96. ( $name, args_to_join_pat!( ( $($tok)* ) ) )
  97. };
  98. ( ( mut $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  99. ( mut $name, args_to_join_pat!( ( $($tok)* ) ) )
  100. };
  101. ( ( resource $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  102. args_to_join_pat!( ( $($tok)* ) )
  103. };
  104. ( ( resource mut $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  105. args_to_join_pat!( ( $($tok)* ) )
  106. };
  107. }
  108. #[macro_export]
  109. macro_rules! args_to_join {
  110. ( ( $name:ident : $ty:ty $(,)? ) ) => {
  111. ( & $name ,)
  112. };
  113. ( ( mut $name:ident : $ty:ty $(,)? ) ) => {
  114. ( &mut $name ,)
  115. };
  116. ( ( resource $name:ident : $ty:ty $(,)? ) ) => {
  117. compile_error!("Resources cannot come at the end of the argument block.")
  118. };
  119. ( ( resource mut $name:ident : $ty:ty $(,)? ) ) => {
  120. compile_error!("Resources cannot come at the end of the argument block.")
  121. };
  122. ( ( $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  123. ( & $name, args_to_join!( ( $($tok)* ) ) )
  124. };
  125. ( ( mut $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  126. ( &mut $name, args_to_join!( ( $($tok)* ) ) )
  127. };
  128. ( ( resource $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  129. args_to_join!( ( $($tok)* ) )
  130. };
  131. ( ( resource mut $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  132. args_to_join!( ( $($tok)* ) )
  133. };
  134. }
  135. #[cfg(test)]
  136. mod tests {
  137. use specs::join::Join;
  138. pub struct Pos {
  139. x: usize,
  140. }
  141. impl specs::Component for Pos {
  142. type Storage = specs::VecStorage<Pos>;
  143. }
  144. pub struct Mov;
  145. impl specs::Component for Mov {
  146. type Storage = specs::VecStorage<Mov>;
  147. }
  148. system! {
  149. Foo (_x: Mov, mut y: Pos) {
  150. y.x += 1;
  151. }
  152. }
  153. system! {
  154. Bar (_x: Mov, mut y: Pos) {
  155. y.x += 1;
  156. } finally {
  157. println!("Done!");
  158. }
  159. }
  160. system! {
  161. Baz (resource n: usize, _x: Mov, mut y: Pos) {
  162. y.x += *n;
  163. }
  164. }
  165. }