lib.rs 6.7 KB

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