lib.rs 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  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 : Entity $(,)* ) ) => {
  45. ( specs::Entities<'a>, )
  46. };
  47. ( ( $name:ident : $ty:ty $(,)* ) ) => {
  48. ( specs::ReadStorage<'a, $ty> ,)
  49. };
  50. ( ( mut $name:ident : $ty:ty $(,)* ) ) => {
  51. ( specs::WriteStorage<'a, $ty> ,)
  52. };
  53. ( ( resource $name:ident : $ty:ty $(,)* ) ) => {
  54. compile_error!("Resources cannot come at the end of the argument block.")
  55. };
  56. ( ( resource mut $name:ident : $ty:ty $(,)* ) ) => {
  57. compile_error!("Resources cannot come at the end of the argument block.")
  58. };
  59. ( ( $name:ident : Entity , $($tok:tt)* ) ) => {
  60. ( specs::Entities<'a>, args_to_systemdata!( ( $( $tok )* ) ) )
  61. };
  62. ( ( $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  63. ( specs::ReadStorage<'a, $ty>, args_to_systemdata!( ( $( $tok )* ) ) )
  64. };
  65. ( ( mut $name:ident : $ty:ty , $( $tok:tt )* ) ) => {
  66. ( specs::WriteStorage<'a, $ty>, args_to_systemdata!( ( $( $tok )* ) ) )
  67. };
  68. ( ( resource $name:ident : $ty:ty , $( $tok:tt )* ) ) => {
  69. ( specs::ReadExpect<'a, $ty>, args_to_systemdata!( ( $( $tok )* ) ) )
  70. };
  71. ( ( resource mut $name:ident : $ty:ty , $( $tok:tt )* ) ) => {
  72. ( specs::WriteExpect<'a, $ty>, args_to_systemdata!( ( $( $tok )* ) ) )
  73. };
  74. }
  75. #[macro_export]
  76. macro_rules! args_to_fn_pat {
  77. ( ( $name:ident : $ty:ty $(,)* ) ) => {
  78. ( $name ,)
  79. };
  80. ( ( mut $name:ident : $ty:ty $(,)* ) ) => {
  81. ( mut $name ,)
  82. };
  83. ( ( resource $name:ident : $ty:ty $(,)* ) ) => {
  84. compile_error!("Resources cannot come at the end of the argument block.")
  85. };
  86. ( ( resource mut $name:ident : $ty:ty $(,)* ) ) => {
  87. compile_error!("Resources cannot come at the end of the argument block.")
  88. };
  89. ( ( $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  90. ( $name, args_to_fn_pat!( ( $($tok)* ) ) )
  91. };
  92. ( ( mut $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  93. ( mut $name, args_to_fn_pat!( ( $($tok)* ) ) )
  94. };
  95. ( ( resource $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  96. ( $name, args_to_fn_pat!( ( $($tok)* ) ) )
  97. };
  98. ( ( resource mut $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  99. ( mut $name, args_to_fn_pat!( ( $($tok)* ) ) )
  100. };
  101. }
  102. #[macro_export]
  103. macro_rules! args_to_join_pat {
  104. ( ( $name:ident : $ty:ty $(,)* ) ) => {
  105. ( $name ,)
  106. };
  107. ( ( mut $name:ident : $ty:ty $(,)* ) ) => {
  108. ( mut $name ,)
  109. };
  110. ( ( resource $name:ident : $ty:ty $(,)* ) ) => {
  111. compile_error!("Resources cannot come at the end of the argument block.")
  112. };
  113. ( ( resource mut $name:ident : $ty:ty $(,)* ) ) => {
  114. compile_error!("Resources cannot come at the end of the argument block.")
  115. };
  116. ( ( $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  117. ( $name, args_to_join_pat!( ( $($tok)* ) ) )
  118. };
  119. ( ( mut $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  120. ( mut $name, args_to_join_pat!( ( $($tok)* ) ) )
  121. };
  122. ( ( resource $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  123. args_to_join_pat!( ( $($tok)* ) )
  124. };
  125. ( ( resource mut $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  126. args_to_join_pat!( ( $($tok)* ) )
  127. };
  128. }
  129. #[macro_export]
  130. macro_rules! args_to_join {
  131. ( ( $name:ident : $ty:ty $(,)* ) ) => {
  132. ( & $name ,)
  133. };
  134. ( ( mut $name:ident : $ty:ty $(,)* ) ) => {
  135. ( &mut $name ,)
  136. };
  137. ( ( resource $name:ident : $ty:ty $(,)? ) ) => {
  138. compile_error!("Resources cannot come at the end of the argument block.")
  139. };
  140. ( ( resource mut $name:ident : $ty:ty $(,)* ) ) => {
  141. compile_error!("Resources cannot come at the end of the argument block.")
  142. };
  143. ( ( $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  144. ( & $name, args_to_join!( ( $($tok)* ) ) )
  145. };
  146. ( ( mut $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  147. ( &mut $name, args_to_join!( ( $($tok)* ) ) )
  148. };
  149. ( ( resource $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  150. args_to_join!( ( $($tok)* ) )
  151. };
  152. ( ( resource mut $name:ident : $ty:ty , $($tok:tt)* ) ) => {
  153. args_to_join!( ( $($tok)* ) )
  154. };
  155. }
  156. #[cfg(test)]
  157. mod tests {
  158. pub struct Pos {
  159. x: usize,
  160. }
  161. impl specs::Component for Pos {
  162. type Storage = specs::VecStorage<Pos>;
  163. }
  164. pub struct Mov;
  165. impl specs::Component for Mov {
  166. type Storage = specs::VecStorage<Mov>;
  167. }
  168. system! {
  169. Foo (_x: Mov, mut y: Pos) {
  170. y.x += 1;
  171. }
  172. }
  173. system_impl! {
  174. FooAlt (x: Mov, mut y: Pos) {
  175. for (_, mut y) in (&x, &mut y).join() {
  176. y.x += 1;
  177. }
  178. }
  179. }
  180. system! {
  181. Bar (_x: Mov, mut y: Pos) {
  182. y.x += 1;
  183. } finally {
  184. println!("Done!");
  185. }
  186. }
  187. system_impl! {
  188. BarAlt (x: Mov, mut y: Pos) {
  189. for (_, mut y) in (&x, &mut y).join() {
  190. y.x += 1;
  191. }
  192. println!("Done!");
  193. }
  194. }
  195. system! {
  196. Baz (resource n: usize, _x: Mov, mut y: Pos) {
  197. y.x += *n;
  198. }
  199. }
  200. system_impl! {
  201. BazAlt (resource n: usize, x: Mov, mut y: Pos) {
  202. for (_, mut y) in (&x, &mut y).join() {
  203. y.x += *n;
  204. }
  205. }
  206. }
  207. system! {
  208. Quux (resource mut n: usize, _x: Mov, mut y: Pos) {
  209. y.x += *n;
  210. *n += 1;
  211. } finally {
  212. *n += 1;
  213. }
  214. }
  215. system_impl! {
  216. QuuxAlt (resource mut n: usize, x: Mov, mut y: Pos) {
  217. for (_, mut y) in (&x, &mut y).join() {
  218. y.x += *n;
  219. }
  220. *n += 1;
  221. }
  222. }
  223. system! {
  224. Pippo (_e: Entity, _x: Mov, mut y: Pos) {
  225. y.x += 1;
  226. }
  227. }
  228. system_impl! {
  229. PippoAlt (_e: Entity, x: Mov, mut y: Pos) {
  230. for (_, mut y) in (&x, &mut y).join() {
  231. y.x += 1;
  232. }
  233. }
  234. }
  235. }