lib.rs 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  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. use specs::join::Join;
  9. for args_to_join_pat!(($($pat)*,)) in args_to_join!(($($pat)*,)).join() {
  10. $($rest)*
  11. }
  12. }
  13. }
  14. };
  15. ($name:ident $pat:tt { $($rest:tt)* } finally { $($finally:tt)* }) => {
  16. pub struct $name;
  17. impl<'a> specs::System<'a> for $name {
  18. type SystemData = args_to_systemdata!($pat);
  19. fn run(&mut self, args_to_fn_pat!($pat): Self::SystemData) {
  20. use specs::join::Join;
  21. for args_to_join_pat!($pat) in args_to_join!($pat).join() {
  22. $($rest)*
  23. }
  24. $($finally)*
  25. }
  26. }
  27. };
  28. }
  29. #[macro_export]
  30. macro_rules! system_impl {
  31. ($name:ident ( $($pat:tt)* ) { $($rest:tt)* } ) => {
  32. pub struct $name;
  33. impl<'a> specs::System<'a> for $name {
  34. type SystemData = args_to_systemdata!(($($pat)*,));
  35. fn run(&mut self, args_to_fn_pat!(($($pat)*)): Self::SystemData) {
  36. use specs::join::Join;
  37. $($rest)*
  38. }
  39. }
  40. };
  41. }
  42. #[macro_export]
  43. macro_rules! args_to_systemdata {
  44. ( ( $name:ident : $ty:ty $(,)? ) ) => {
  45. ( specs::ReadStorage<'a, $ty> ,)
  46. };
  47. ( ( mut $name:ident : $ty:ty $(,)? ) ) => {
  48. ( specs::WriteStorage<'a, $ty> ,)
  49. };
  50. ( ( resource $name:ident : $ty:ty $(,)? ) ) => {
  51. compile_error!("Resources cannot come at the end of the argument block.")
  52. };
  53. ( ( resource mut $name:ident : $ty:ty $(,)? ) ) => {
  54. compile_error!("Resources cannot come at the end of the argument block.")
  55. };
  56. ( ( $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  57. ( specs::ReadStorage<'a, $ty>, args_to_systemdata!( ( $( $tok )* ) ) )
  58. };
  59. ( ( mut $name:ident : $ty:ty , $( $tok:tt )* ) ) => {
  60. ( specs::WriteStorage<'a, $ty>, args_to_systemdata!( ( $( $tok )* ) ) )
  61. };
  62. ( ( resource $name:ident : $ty:ty , $( $tok:tt )* ) ) => {
  63. ( specs::ReadExpect<'a, $ty>, args_to_systemdata!( ( $( $tok )* ) ) )
  64. };
  65. ( ( resource mut $name:ident : $ty:ty , $( $tok:tt )* ) ) => {
  66. ( specs::WriteExpect<'a, $ty>, args_to_systemdata!( ( $( $tok )* ) ) )
  67. };
  68. }
  69. #[macro_export]
  70. macro_rules! args_to_fn_pat {
  71. ( ( $name:ident : $ty:ty $(,)? ) ) => {
  72. ( $name ,)
  73. };
  74. ( ( mut $name:ident : $ty:ty $(,)? ) ) => {
  75. ( mut $name ,)
  76. };
  77. ( ( resource $name:ident : $ty:ty $(,)? ) ) => {
  78. compile_error!("Resources cannot come at the end of the argument block.")
  79. };
  80. ( ( resource mut $name:ident : $ty:ty $(,)? ) ) => {
  81. compile_error!("Resources cannot come at the end of the argument block.")
  82. };
  83. ( ( $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  84. ( $name, args_to_fn_pat!( ( $($tok)* ) ) )
  85. };
  86. ( ( mut $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  87. ( mut $name, args_to_fn_pat!( ( $($tok)* ) ) )
  88. };
  89. ( ( resource $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  90. ( $name, args_to_fn_pat!( ( $($tok)* ) ) )
  91. };
  92. ( ( resource mut $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  93. ( mut $name, args_to_fn_pat!( ( $($tok)* ) ) )
  94. };
  95. }
  96. #[macro_export]
  97. macro_rules! args_to_join_pat {
  98. ( ( $name:ident : $ty:ty $(,)? ) ) => {
  99. ( $name ,)
  100. };
  101. ( ( mut $name:ident : $ty:ty $(,)? ) ) => {
  102. ( mut $name ,)
  103. };
  104. ( ( resource $name:ident : $ty:ty $(,)? ) ) => {
  105. compile_error!("Resources cannot come at the end of the argument block.")
  106. };
  107. ( ( resource mut $name:ident : $ty:ty $(,)? ) ) => {
  108. compile_error!("Resources cannot come at the end of the argument block.")
  109. };
  110. ( ( $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  111. ( $name, args_to_join_pat!( ( $($tok)* ) ) )
  112. };
  113. ( ( mut $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  114. ( mut $name, args_to_join_pat!( ( $($tok)* ) ) )
  115. };
  116. ( ( resource $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  117. args_to_join_pat!( ( $($tok)* ) )
  118. };
  119. ( ( resource mut $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  120. args_to_join_pat!( ( $($tok)* ) )
  121. };
  122. }
  123. #[macro_export]
  124. macro_rules! args_to_join {
  125. ( ( $name:ident : $ty:ty $(,)? ) ) => {
  126. ( & $name ,)
  127. };
  128. ( ( mut $name:ident : $ty:ty $(,)? ) ) => {
  129. ( &mut $name ,)
  130. };
  131. ( ( resource $name:ident : $ty:ty $(,)? ) ) => {
  132. compile_error!("Resources cannot come at the end of the argument block.")
  133. };
  134. ( ( resource mut $name:ident : $ty:ty $(,)? ) ) => {
  135. compile_error!("Resources cannot come at the end of the argument block.")
  136. };
  137. ( ( $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  138. ( & $name, args_to_join!( ( $($tok)* ) ) )
  139. };
  140. ( ( mut $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  141. ( &mut $name, args_to_join!( ( $($tok)* ) ) )
  142. };
  143. ( ( resource $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  144. args_to_join!( ( $($tok)* ) )
  145. };
  146. ( ( resource mut $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  147. args_to_join!( ( $($tok)* ) )
  148. };
  149. }
  150. #[cfg(test)]
  151. mod tests {
  152. pub struct Pos {
  153. x: usize,
  154. }
  155. impl specs::Component for Pos {
  156. type Storage = specs::VecStorage<Pos>;
  157. }
  158. pub struct Mov;
  159. impl specs::Component for Mov {
  160. type Storage = specs::VecStorage<Mov>;
  161. }
  162. system! {
  163. Foo (_x: Mov, mut y: Pos) {
  164. y.x += 1;
  165. }
  166. }
  167. system_impl! {
  168. FooAlt (x: Mov, mut y: Pos) {
  169. for (_, mut y) in (&x, &mut y).join() {
  170. y.x += 1;
  171. }
  172. }
  173. }
  174. system! {
  175. Bar (_x: Mov, mut y: Pos) {
  176. y.x += 1;
  177. } finally {
  178. println!("Done!");
  179. }
  180. }
  181. system_impl! {
  182. BarAlt (x: Mov, mut y: Pos) {
  183. for (_, mut y) in (&x, &mut y).join() {
  184. y.x += 1;
  185. }
  186. println!("Done!");
  187. }
  188. }
  189. system! {
  190. Baz (resource n: usize, _x: Mov, mut y: Pos) {
  191. y.x += *n;
  192. }
  193. }
  194. system_impl! {
  195. BazAlt (resource n: usize, x: Mov, mut y: Pos) {
  196. for (_, mut y) in (&x, &mut y).join() {
  197. y.x += *n;
  198. }
  199. }
  200. }
  201. system! {
  202. Quux (resource mut n: usize, _x: Mov, mut y: Pos) {
  203. y.x += *n;
  204. *n += 1;
  205. } finally {
  206. *n += 1;
  207. }
  208. }
  209. system_impl! {
  210. QuuxAlt (resource mut n: usize, x: Mov, mut y: Pos) {
  211. for (_, mut y) in (&x, &mut y).join() {
  212. y.x += *n;
  213. }
  214. *n += 1;
  215. }
  216. }
  217. }