1extern crate proc_macro;
2
3use heck::{ToSnakeCase, ToUpperCamelCase};
4use itertools::Itertools;
5use proc_macro::TokenStream;
6use syn::{
7 DeriveInput, Field, Fields, Ident, Type, TypePath,
8 parse::{Parse, Parser},
9 parse_macro_input,
10 spanned::Spanned,
11 visit_mut::VisitMut,
12};
13
14struct EventManagerArgs {
15 states: StateMapping,
16 events: Vec<EventMapping>,
17}
18
19struct StateMapping {
20 states: Vec<(syn::Type, syn::ExprClosure)>,
21 placeholder: syn::Ident,
22}
23
24#[derive(Clone)]
25struct EventMapping {
26 event_fn: Option<syn::Ident>,
27 event: syn::Type,
28 stackable: syn::Type,
29 resolution: syn::Type,
30 stackable_enum_types: Vec<IdentAndType>,
31 resolution_enum_types: Vec<IdentAndType>,
32}
33
34impl Parse for EventManagerArgs {
35 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
36 let mut states = None;
37 let mut events = None;
38
39 while !input.is_empty() {
40 let key: Ident = input.parse()?;
41 let _ = input.parse::<syn::Token![=]>()?;
42
43 match key.to_string().as_str() {
44 "states" => {
45 states = Some(input.parse()?);
46 }
47 "events" => {
48 let content;
49 syn::parenthesized!(content in input);
50 let parsed = content
51 .parse_terminated(EventMapping::parse, syn::Token![,])?
52 .into_iter()
53 .collect();
54 events = Some(parsed);
55 }
56 _ => {
57 return Err(syn::Error::new_spanned(key, "Unknown key"));
58 }
59 }
60
61 let _ = input.parse::<syn::Token![,]>();
62 }
63
64 Ok(EventManagerArgs {
65 states: states.ok_or_else(|| input.error("missing `states`"))?,
66 events: events.ok_or_else(|| input.error("missing `events`"))?,
67 })
68 }
69}
70
71impl Parse for StateMapping {
72 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
73 let content;
74 syn::parenthesized!(content in input);
75
76 let closures = content
77 .parse_terminated(syn::Expr::parse, syn::Token![,])?
78 .into_iter()
79 .collect::<Vec<_>>();
80
81 input.parse::<syn::Token![as]>()?;
82 let placeholder = input.parse::<Ident>()?;
83
84 let mut states = Vec::new();
85
86 for expr in closures {
87 let closure = match expr {
88 syn::Expr::Closure(closure) => closure,
89 _ => {
90 return Err(syn::Error::new_spanned(
91 expr,
92 "expected a closure like `|state: Type| ...`",
93 ));
94 }
95 };
96
97 if closure.inputs.len() != 1 {
98 return Err(syn::Error::new_spanned(
99 &closure.inputs,
100 "closure must have exactly one parameter",
101 ));
102 }
103
104 let state_ty = match closure.inputs.first().unwrap() {
106 syn::Pat::Type(syn::PatType { ty, .. }) => match ty.as_ref() {
107 Type::Reference(syn::TypeReference { elem, .. }) => (**elem).clone(),
108 _ => {
109 return Err(syn::Error::new_spanned(
110 ty,
111 "expected a reference type like `&StateType`",
112 ));
113 }
114 },
115 _ => {
116 return Err(syn::Error::new_spanned(
117 &closure.inputs,
118 "closure parameter must be typed: `|state: Type|`",
119 ));
120 }
121 };
122
123 states.push((state_ty, closure));
124 }
125
126 Ok(StateMapping {
127 states,
128 placeholder,
129 })
130 }
131}
132
133fn closure_to_item_fn(
134 closure: syn::ExprClosure,
135 fn_name: &str,
136 event_manager_name: Type,
137) -> syn::Result<syn::ItemFn> {
138 if closure.capture.is_some() {
140 return Err(syn::Error::new(
141 closure.span(),
142 "cannot convert capturing closure into function",
143 ));
144 }
145
146 let inputs = closure
148 .inputs
149 .into_iter()
150 .map(|pat| match pat {
151 syn::Pat::Type(pat_ty) => Ok(syn::FnArg::Typed(pat_ty)),
152 _ => Err(syn::Error::new_spanned(
153 pat,
154 "closure parameters must be typed",
155 )),
156 })
157 .collect::<syn::Result<_>>()?;
158
159 let sig = syn::Signature {
160 constness: closure.constness,
161 asyncness: closure.asyncness,
162 unsafety: None,
163 abi: None,
164 fn_token: Default::default(),
165 ident: Ident::new(fn_name, proc_macro2::Span::call_site()),
166 generics: Default::default(),
167 paren_token: Default::default(),
168 inputs,
169 variadic: None,
170 output: syn::ReturnType::Type(
171 syn::token::RArrow::default(),
172 Box::new(syn::parse_quote!(&#event_manager_name)),
173 ),
174 };
175
176 Ok(syn::ItemFn {
177 attrs: Vec::new(),
178 vis: syn::Visibility::Inherited,
179 sig,
180 block: Box::new(match *closure.body {
181 syn::Expr::Block(block) => block.block,
182 expr => syn::Block {
183 brace_token: syn::token::Brace::default(),
184 stmts: vec![syn::Stmt::Expr(expr, None)],
185 },
186 }),
187 })
188}
189
190impl Parse for EventMapping {
191 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
192 let event_fn = if input.peek2(syn::Token![->]) {
193 let event_fn = input.parse::<syn::Ident>()?;
194 let _ = input.parse::<syn::Token![->]>()?;
195 Some(event_fn)
196 } else {
197 None
198 };
199
200 let event = input.parse::<syn::Type>()?;
201 let _ = input.parse::<syn::Token![^]>()?;
202
203 let stackable = input.parse::<syn::Type>()?;
204
205 let stackable_enum_types = if input.peek(syn::token::Brace) {
206 let content;
207 syn::braced!(content in input);
208 content
209 .parse_terminated(IdentAndType::parse, syn::Token![,])?
210 .into_iter()
211 .collect::<Vec<_>>()
212 } else {
213 Vec::new()
214 };
215
216 let _ = input.parse::<syn::Token![=>]>()?;
217 let resolution = input.parse::<syn::Type>()?;
218
219 let resolution_enum_types = if input.peek(syn::token::Brace) {
220 let content;
221 syn::braced!(content in input);
222 content
223 .parse_terminated(IdentAndType::parse, syn::Token![,])?
224 .into_iter()
225 .collect::<Vec<_>>()
226 } else {
227 Vec::new()
228 };
229
230 Ok(EventMapping {
231 event_fn,
232 event,
233 stackable,
234 resolution,
235 stackable_enum_types,
236 resolution_enum_types,
237 })
238 }
239}
240
241#[derive(Clone)]
242struct IdentAndType {
243 ident: Option<Ident>,
244 ty: Type,
245}
246impl Parse for IdentAndType {
247 fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
248 if input.peek2(syn::Token![:]) {
249 let ident = input.parse()?;
250 let _ = input.parse::<syn::Token![:]>()?;
251 let ty = input.parse()?;
252 Ok(IdentAndType {
253 ident: Some(ident),
254 ty,
255 })
256 } else {
257 Ok(IdentAndType {
258 ident: None,
259 ty: input.parse()?,
260 })
261 }
262 }
263}
264
265#[proc_macro_attribute]
266pub fn event_manager(args: TokenStream, input: TokenStream) -> TokenStream {
267 let args = parse_macro_input!(args as EventManagerArgs);
268 let mut ast = parse_macro_input!(input as syn::ItemStruct);
269 let struct_name = &ast.ident;
270 let mut impls = Vec::new();
271 if let Fields::Named(ref mut fields) = ast.fields {
272 let mut i: usize = 0;
273 for (state, get_event_manager) in args.states.states.iter() {
274 let get_event_manager = closure_to_item_fn(
275 get_event_manager.clone(),
276 "get_event_manager",
277 syn::parse_quote!(#struct_name),
278 )
279 .expect("failed to make function from closure");
280 let original_state = &state;
281 for event in args.events.iter() {
282 {
283 let state_str = quote::quote!(#state).to_string();
284 let state = syn::parse_quote!(card_game::stack::priority::Priority<#state>);
285 let event_resolution =
286 substitute_type(&event.resolution, &args.states.placeholder, &state);
287 let stackable =
288 substitute_type(&event.stackable, &args.states.placeholder, &state);
289 let event = &event.event;
290 let event_name = quote::quote!(#event).to_string();
291 let field_name = quote::format_ident!(
292 "{}_during_{}",
293 event_name.to_snake_case(),
294 state_str.to_snake_case(),
295 );
296 let field_id_name = quote::format_ident!("{}_id", field_name.to_string());
297 let return_ty: syn::Type = syn::parse_quote!(
298 card_game::events::EventManager<
299 #state,
300 #event,
301 #event_resolution<#state>,
302 >
303 );
304 let new_field = Field {
305 attrs: Vec::new(),
306 mutability: syn::FieldMutability::None,
307 vis: syn::Visibility::Inherited,
308 ident: Some(field_name.clone()),
309 colon_token: Some(<syn::Token![:]>::default()),
310 ty: return_ty.clone(),
311 };
312 fields.named.push(new_field);
313 impls.push(quote::quote! {
314 impl #struct_name {
315 pub fn #field_name(&self) -> &#return_ty {
316 &self.#field_name
317 }
318 pub fn #field_id_name(&self) -> card_game::cards::EventManagerID {
319 card_game::cards::EventManagerID::new(#i)
320 }
321 }
322 impl card_game::events::Event<#original_state> for #event {
323 type Stackable = #stackable<#original_state, card_game::events::EventAction<#state, Self, #event_resolution<#state>>>;
324 }
325 impl card_game::events::GetEventManager<#event> for #original_state {
326 type Output = #event_resolution<#state>;
327 fn event_manager_id(&self) -> card_game::cards::EventManagerID {
328 #get_event_manager
329 let event_manager = get_event_manager(self);
330 event_manager.#field_id_name()
331 }
332 fn event_manager(
333 &self,
334 ) -> card_game::events::EventManager<card_game::stack::priority::Priority<Self>, #event, Self::Output> {
335 #get_event_manager
336 let event_manager = get_event_manager(self);
337 event_manager
338 .#field_name()
339 .clone()
340 }
341 }
342 impl card_game::events::AddEventListener<#state, #event> for #struct_name {
343 type Output = #event_resolution<#state>;
344 fn add_listener<
345 Listener: card_game::events::EventListener<#state, #event>,
346 >(
347 &mut self,
348 event_action_id: card_game::events::EventActionID,
349 listener: Listener,
350 ) -> (card_game::cards::EventManagerID, card_game::cards::EventManagerIndex) where
351 <Listener::Action as card_game::events::EventValidAction<
352 card_game::stack::priority::PriorityMut<#state>,
353 Listener::ActionInput,
354 >>::Output: Into<Self::Output>,
355 {
356 (self.#field_id_name(), self.#field_name.add_listener(event_action_id, listener))
357 }
358 }
359 impl ::std::convert::From<#state> for #event_resolution<#state> {
360 fn from(value: #state) -> Self {
361 Self::State(value)
362 }
363 }
364 });
365 }
366 i += 1;
367 {
368 let state_str = quote::quote!(#state).to_string().to_snake_case();
369 let priority_state =
370 syn::parse_quote!(card_game::stack::priority::Priority<#state>);
371 let original_event = &event.event;
372 let original_event_name =
373 quote::quote!(#original_event).to_string().to_snake_case();
374 let original_priority_event_resolution = substitute_type(
375 &event.resolution,
376 &args.states.placeholder,
377 &priority_state,
378 );
379 let state = syn::parse_quote!(card_game::events::EventPriorityStack<#state, #original_event, #original_priority_event_resolution<#priority_state>>);
380 for ev in args.events.iter() {
381 let event_name = {
382 let event = &ev.event;
383 quote::quote!(#event).to_string().to_snake_case()
384 };
385 let event_resolution = &ev.resolution;
386 let field_name = if *event_resolution == event.resolution {
387 quote::format_ident!("{}_stack_during_{}", event_name, state_str)
388 } else {
389 quote::format_ident!(
390 "{}_stack_during_{}_{}",
391 event_name,
392 state_str,
393 original_event_name,
394 )
395 };
396 let field_id_name = quote::format_ident!("{}_id", field_name.to_string());
397 let event = &ev.event;
398 let event_resolution = substitute_type(
399 event_resolution,
400 &args.states.placeholder,
401 &priority_state,
402 );
403 let event_resolution = substitute_type(
404 &ev.resolution,
405 &args.states.placeholder,
406 &syn::parse_quote!(card_game::events::EventAction<
407 #priority_state,
408 #event,
409 #event_resolution,
410 >),
411 );
412 let stack_event_resolution =
413 substitute_type(&ev.resolution, &args.states.placeholder, &state);
414 let stackable =
415 substitute_type(&ev.stackable, &args.states.placeholder, &state);
416 let return_ty: syn::Type = syn::parse_quote!(
417 card_game::events::EventManager<
418 #state,
419 #event,
420 #stack_event_resolution<#state>,
421 >
422 );
423 let new_field = Field {
424 attrs: Vec::new(),
425 mutability: syn::FieldMutability::None,
426 vis: syn::Visibility::Inherited,
427 ident: Some(field_name.clone()),
428 colon_token: Some(<syn::Token![:]>::default()),
429 ty: return_ty.clone(),
430 };
431 fields.named.push(new_field);
432 impls.push(quote::quote! {
433 impl #struct_name {
434 pub fn #field_name(&self) -> &#return_ty {
435 &self.#field_name
436 }
437 pub fn #field_id_name(&self) -> card_game::cards::EventManagerID {
438 card_game::cards::EventManagerID::new(#i)
439 }
440 }
441 impl card_game::events::Event<
442 #state
443 > for #event {
444 type Stackable = #stackable<#original_state, card_game::events::EventAction<#priority_state, #original_event, #original_priority_event_resolution<#priority_state>>>;
445 }
446 impl card_game::events::GetStackEventManager<
447 #event,
448 card_game::events::EventAction<card_game::stack::priority::Priority<#original_state>, #original_event, #original_priority_event_resolution<#priority_state>>,
449 > for #original_state {
450 type Output = #stack_event_resolution<#state>;
451 fn event_manager_id(&self) -> card_game::cards::EventManagerID {
452 #get_event_manager
453 let event_manager = get_event_manager(self);
454 event_manager.#field_id_name()
455 }
456 fn stack_event_manager(
457 &self,
458 ) -> card_game::events::EventManager<#state, #event, Self::Output> {
459 #get_event_manager
460 let event_manager = get_event_manager(self);
461 event_manager
462 .#field_name()
463 .clone()
464 }
465 }
466 impl card_game::events::AddEventListener<#state, #event> for #struct_name {
467 type Output = #stack_event_resolution<#state>;
468 fn add_listener<
469 Listener: card_game::events::EventListener<#state, #event>,
470 >(
471 &mut self,
472 event_action_id: card_game::events::EventActionID,
473 listener: Listener,
474 ) -> (card_game::cards::EventManagerID, card_game::cards::EventManagerIndex) where
475 <Listener::Action as card_game::events::EventValidAction<
476 card_game::stack::priority::PriorityMut<#state>,
477 Listener::ActionInput,
478 >>::Output: Into<Self::Output>,
479 {
480 (self.#field_id_name(), self.#field_name.add_listener(event_action_id, listener))
481 }
482 }
483 impl ::std::convert::From<#state> for #stack_event_resolution<#state> {
484 fn from(value: #state) -> Self {
485 Self::State(value)
486 }
487 }
488 });
489 }
490 }
491 i += 1;
492 }
493 }
494 for event in args.events.iter() {
495 let stackable = &event.stackable;
496 let stackable_enum_types = event
497 .stackable_enum_types
498 .iter()
499 .map(|ty| substitute_type(&ty.ty, &args.states.placeholder, &syn::parse_quote!(card_game::stack::priority::PriorityStack<State, IncitingAction>)))
500 .collect::<Vec<_>>();
501 let stackable_enum_variant_names = event
502 .stackable_enum_types
503 .iter()
504 .map(|ty| {
505 let ident = if let Some(ref ident) = ty.ident {
506 ident
507 } else {
508 type_to_ident(&ty.ty)
509 };
510 quote::format_ident!("{}", ident.to_string().to_upper_camel_case())
511 })
512 .collect::<Vec<_>>();
513 let stackable_enum_variant_names_str = stackable_enum_variant_names
514 .iter()
515 .map(|ident| ident.to_string().to_upper_camel_case())
516 .collect::<Vec<_>>();
517 let stackable_enum_variants = event.stackable_enum_types
518 .iter()
519 .map(|ty| {
520 let ident = if let Some(ref ident) = ty.ident {
521 ident
522 } else {
523 type_to_ident(&ty.ty)
524 };
525 let ident = quote::format_ident!("{}", ident.to_string().to_upper_camel_case());
526 let ty = substitute_type(
527 &ty.ty,
528 &args.states.placeholder,
529 &syn::parse_quote!(card_game::stack::priority::PriorityStack<State, IncitingAction>));
530 quote::quote!(#ident(#ty))
531 })
532 .collect::<Vec<_>>();
533 let resolution = &event.resolution;
534 let resolution_enum_types = event
535 .resolution_enum_types
536 .iter()
537 .map(|ty| {
538 substitute_type(&ty.ty, &args.states.placeholder, &syn::parse_quote!(State))
539 })
540 .collect::<Vec<_>>();
541 let resolution_enum_variant_names_str = event
542 .resolution_enum_types
543 .iter()
544 .map(|ty| {
545 let ident = if let Some(ref ident) = ty.ident {
546 ident.to_string()
547 } else {
548 type_to_ident(&ty.ty).to_string()
549 };
550 format!("{}", ident.to_upper_camel_case())
551 })
552 .collect::<Vec<_>>();
553 let resolution_enum_variant_names = resolution_enum_variant_names_str
554 .iter()
555 .map(|name| quote::format_ident!("{name}"))
556 .collect::<Vec<_>>();
557 let resolution_enum_variants = event
558 .resolution_enum_types
559 .iter()
560 .map(|ty| {
561 let ident = if let Some(ref ident) = ty.ident {
562 ident.to_string()
563 } else {
564 type_to_ident(&ty.ty).to_string()
565 };
566 let enum_ty = quote::format_ident!("{}", ident.to_upper_camel_case());
567 let ty = substitute_type(
568 &ty.ty,
569 &args.states.placeholder,
570 &syn::parse_quote!(State),
571 );
572 quote::quote!(#enum_ty(#ty))
573 })
574 .collect::<Vec<_>>();
575 let (
576 events,
577 (
578 event_resolutions,
579 (
580 stackable_event_names,
581 (
582 stackable_event_names_str,
583 (
584 resolution_triggered_event_variant_names,
585 (resolution_triggered_event_variant_names_str,
586 resolution_triggered_event_variant_types),
587 ),
588 ),
589 ),
590 ),
591 ): (Vec<_>, (Vec<_>, (Vec<_>, (Vec<_>, (Vec<_>, (Vec<_>, Vec<_>)))))) = args
592 .events
593 .iter()
594 .map(|args| {
595 let event = &args.event;
596 let event_name = quote::quote!(#event).to_string();
597 let stackable_event_name_str = format!("{}Event", event_name.to_upper_camel_case());
598 let stackable_event_name = quote::format_ident!("{stackable_event_name_str}");
599 let resolution_triggered_event_variant_name_str = format!(
600 "Triggered{}Event",
601 quote::quote!(#event).to_string().to_upper_camel_case()
602 );
603 let resolution_triggered_event_variant_name= quote::format_ident!("{resolution_triggered_event_variant_name_str}");
604 (
605 event,
606 (
607 &args.resolution,
608 (
609 stackable_event_name,
610 (stackable_event_name_str,
611 (
612 resolution_triggered_event_variant_name,
613 (
614 resolution_triggered_event_variant_name_str,
615 quote::quote!(card_game::events::TriggeredEvent<State, #event>),
616 )
617 )),
618 ),
619 ),
620 )
621 })
622 .unzip();
623 let stackable_event_constraints = quote::quote! {
624 #(
625 #events: card_game::events::Event<card_game::stack::priority::PriorityMut<
626 card_game::stack::priority::PriorityStack<State, IncitingAction>,
627 >>,
628 )*
629 };
630 let resolution_event_constraints = quote::quote! {
631 #(
632 #events: card_game::events::Event<card_game::stack::priority::PriorityMut<State>>,
633 )*
634 };
635 impls.push(quote::quote! {
636 pub enum #stackable<State, IncitingAction: card_game::stack::actions::IncitingActionInfo<State>>
637 where #stackable_event_constraints
638 {
639 #(
640 #stackable_event_names(card_game::events::EventAction<
641 card_game::stack::priority::PriorityStack<State, IncitingAction>,
642 #events,
643 #event_resolutions<
644 card_game::stack::priority::PriorityStack<State, IncitingAction>,
645 >,
646 >),
647 )*
648 #(#stackable_enum_variants),*
649 }
650 impl<State, IncitingAction: card_game::stack::actions::IncitingActionInfo<State>> ::std::fmt::Debug for #stackable<State, IncitingAction>
651 where #stackable_event_constraints
652 {
653 fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::result::Result<(), ::std::fmt::Error> {
654 match self {
655 #(
656 Self::#stackable_event_names(_) => f.debug_tuple(#stackable_event_names_str).finish_non_exhaustive(),
657 )*
658 #(
659 Self::#stackable_enum_variant_names(_) => f.debug_tuple(#stackable_enum_variant_names_str).finish_non_exhaustive(),
660 )*
661 }
662 }
663 }
664 impl<State, IncitingAction: card_game::stack::actions::IncitingActionInfo<State>> ::std::clone::Clone for #stackable<State, IncitingAction>
665 where #stackable_event_constraints
666 #(
667 #stackable_enum_types: ::std::clone::Clone,
668 )*
669 {
670 fn clone(&self) -> Self {
671 match self {
672 #(
673 Self::#stackable_event_names(value) => Self::#stackable_event_names(value.clone()),
674 )*
675 #(
676 Self::#stackable_enum_variant_names(value) => Self::#stackable_enum_variant_names(value.clone()),
677 )*
678 }
679 }
680 }
681 #(
682 impl<
683 State,
684 IncitingAction: card_game::stack::actions::IncitingActionInfo<State>,
685 > ::std::convert::From<card_game::events::EventAction<
686 card_game::stack::priority::PriorityStack<State, IncitingAction>,
687 #events,
688 #event_resolutions<
689 card_game::stack::priority::PriorityStack<State, IncitingAction>,
690 >,
691 >> for #stackable<State, IncitingAction>
692 where #stackable_event_constraints
693 {
694 fn from(value: card_game::events::EventAction<
695 card_game::stack::priority::PriorityStack<State, IncitingAction>,
696 #events,
697 #event_resolutions<
698 card_game::stack::priority::PriorityStack<State, IncitingAction>,
699 >,
700 >) -> Self {
701 Self::#stackable_event_names(value)
702 }
703 }
704 )*
705 #(
706 impl<State, IncitingAction: card_game::stack::actions::IncitingActionInfo<State>> ::std::convert::From<#stackable_enum_types> for #stackable<State, IncitingAction>
707 where #stackable_event_constraints
708 {
709 fn from(value: #stackable_enum_types) -> Self {
710 Self::#stackable_enum_variant_names(value)
711 }
712 }
713 )*
714 #[derive(Clone)]
715 pub enum #resolution<State>
716 where #resolution_event_constraints
717 {
718 State(State),
719 #(#resolution_triggered_event_variant_names(#resolution_triggered_event_variant_types),)*
720 #(#resolution_enum_variants),*
721 }
722 impl<State> ::std::fmt::Debug for #resolution<State>
723 where #resolution_event_constraints
724 {
725 fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::result::Result<(), ::std::fmt::Error> {
726 match self {
727 Self::State(_) => f.debug_tuple("State").finish_non_exhaustive(),
728 #(
729 Self::#resolution_triggered_event_variant_names(_) => f.debug_tuple(#resolution_triggered_event_variant_names_str).finish_non_exhaustive(),
730 )*
731 #(
732 Self::#resolution_enum_variant_names(_) => f.debug_tuple(#resolution_enum_variant_names_str).finish_non_exhaustive(),
733 )*
734 }
735 }
736 }
737 #(
738 impl<State> ::std::convert::From<#resolution_triggered_event_variant_types> for #resolution<State>
739 where #resolution_event_constraints
740 {
741 fn from(value: #resolution_triggered_event_variant_types) -> Self {
742 Self::#resolution_triggered_event_variant_names(value)
743 }
744 }
745 )*
746 #(
747 impl<State> ::std::convert::From<#resolution_enum_types> for #resolution<State>
748 where #resolution_event_constraints
749 {
750 fn from(value: #resolution_enum_types) -> Self {
751 Self::#resolution_enum_variant_names(value)
752 }
753 }
754 )*
755 });
756 if let Some(ref event_fn) = event.event_fn {
757 let (mut states, mut priority_resolutions): (Vec<_>, Vec<_>) = args
758 .states
759 .states
760 .iter()
761 .map(|(ty, _)| {
762 let priority_state: syn::Type =
763 syn::parse_quote!(card_game::stack::priority::Priority<#ty>);
764 (
765 ty,
766 substitute_type(
767 &event.resolution,
768 &args.states.placeholder,
769 &priority_state,
770 ),
771 )
772 })
773 .unzip();
774 let (stack_states, (stack_events, stack_priority_resolutions)): (
775 Vec<_>,
776 (Vec<_>, Vec<_>),
777 ) = args
778 .states
779 .states
780 .iter()
781 .cartesian_product(args.events.iter().cloned())
782 .map(|((ty, _), event): (_, EventMapping)| {
783 let priority_state: syn::Type =
784 syn::parse_quote!(card_game::stack::priority::Priority<#ty>);
785 (
786 ty,
787 (
788 event.event,
789 substitute_type(
790 &event.resolution,
791 &args.states.placeholder,
792 &priority_state,
793 ),
794 ),
795 )
796 })
797 .unzip();
798 let first_state = states.pop().unwrap();
799 let first_priority_resolutions = priority_resolutions.pop().unwrap();
800 let event = &event.event;
801 let listener_constraints = quote::quote! {
802 card_game::events::EventListenerConstructor<card_game::stack::priority::Priority<#first_state>, #event> +
803 card_game::events::EventListenerConstructor<
804 card_game::events::EventPriorityStack<#first_state, #event, #first_priority_resolutions<card_game::stack::priority::Priority<#first_state>>>,
805 #event,
806 Input = <Listener as card_game::events::EventListenerConstructor<card_game::stack::priority::Priority<#first_state>, #event>>::Input,
807 >
808 #(
809 + card_game::events::EventListenerConstructor<
810 card_game::stack::priority::Priority<#states>,
811 #event,
812 Input = <Listener as card_game::events::EventListenerConstructor<card_game::stack::priority::Priority<#first_state>, #event>>::Input,
813 >
814 )*
815 #(
816 + card_game::events::EventListenerConstructor<
817 card_game::events::EventPriorityStack<#stack_states, #stack_events, #stack_priority_resolutions<card_game::stack::priority::Priority<#stack_states>>>,
818 #event,
819 Input = <Listener as card_game::events::EventListenerConstructor<card_game::stack::priority::Priority<#first_state>, #event>>::Input,
820 >
821 )*
822 };
823 let trait_constraints = quote::quote! {
824 <<Listener as card_game::events::EventListener<card_game::stack::priority::Priority<#first_state>, #event>>::Action as card_game::events::EventValidAction<
825 card_game::stack::priority::PriorityMut<card_game::stack::priority::Priority<#first_state>>,
826 <Listener as card_game::events::EventListener<card_game::stack::priority::Priority<#first_state>, #event>>::ActionInput,
827 >>::Output: std::convert::Into<<#struct_name as card_game::events::AddEventListener<card_game::stack::priority::Priority<#first_state>, #event>>::Output>
828 #(,
829 <<Listener as card_game::events::EventListener<card_game::stack::priority::Priority<#states>, #event>>::Action as card_game::events::EventValidAction<
830 card_game::stack::priority::PriorityMut<card_game::stack::priority::Priority<#states>>,
831 <Listener as card_game::events::EventListener<card_game::stack::priority::Priority<#states>, #event>>::ActionInput,
832 >>::Output: std::convert::Into<<#struct_name as card_game::events::AddEventListener<card_game::stack::priority::Priority<#states>, #event>>::Output>
833 )*,
834 <<Listener as card_game::events::EventListener<
835 card_game::events::EventPriorityStack<#first_state, #event, #first_priority_resolutions<card_game::stack::priority::Priority<#first_state>>>,
836 #event,
837 >>::Action as card_game::events::EventValidAction<
838 card_game::stack::priority::PriorityMut<card_game::events::EventPriorityStack<#first_state, #event, #first_priority_resolutions<card_game::stack::priority::Priority<#first_state>>>>,
839 <Listener as card_game::events::EventListener<
840 card_game::events::EventPriorityStack<#first_state, #event, #first_priority_resolutions<card_game::stack::priority::Priority<#first_state>>>,
841 #event,
842 >>::ActionInput,
843 >>::Output: Into<
844 <#struct_name as card_game::events::AddEventListener<
845 card_game::events::EventPriorityStack<#first_state, #event, #first_priority_resolutions<card_game::stack::priority::Priority<#first_state>>>,
846 #event,
847 >>::Output,
848 >
849 #(,
850 <<Listener as card_game::events::EventListener<
851 card_game::events::EventPriorityStack<#stack_states, #stack_events, #stack_priority_resolutions<card_game::stack::priority::Priority<#stack_states>>>,
852 #event,
853 >>::Action as card_game::events::EventValidAction<
854 card_game::stack::priority::PriorityMut<card_game::events::EventPriorityStack<#stack_states, #stack_events, #stack_priority_resolutions<card_game::stack::priority::Priority<#stack_states>>>>,
855 <Listener as card_game::events::EventListener<
856 card_game::events::EventPriorityStack<#stack_states, #stack_events, #stack_priority_resolutions<card_game::stack::priority::Priority<#stack_states>>>,
857 #event,
858 >>::ActionInput,
859 >>::Output: Into<
860 <#struct_name as card_game::events::AddEventListener<
861 card_game::events::EventPriorityStack<#stack_states, #stack_events, #stack_priority_resolutions<card_game::stack::priority::Priority<#stack_states>>>,
862 #event,
863 >>::Output,
864 >
865 )*
866 };
867 let trait_name =
868 quote::format_ident!("{}Event", event_fn.to_string().to_upper_camel_case());
869 impls.push(quote::quote! {
870 pub trait #trait_name {
871 fn #event_fn<
872 Listener: #listener_constraints
873 >(
874 self,
875 input: <Listener as card_game::events::EventListenerConstructor<card_game::stack::priority::Priority<#first_state>, #event>>::Input,
876 ) -> Self
877 where #trait_constraints;
878 }
879 impl<'a, Kind> #trait_name for card_game::cards::CardKindBuilder<'a, #struct_name, Kind> {
880 fn #event_fn<
881 Listener: #listener_constraints
882 >(
883 self,
884 input: <Listener as card_game::events::EventListenerConstructor<card_game::stack::priority::Priority<#first_state>, #event>>::Input,
885 ) -> Self
886 where #trait_constraints
887 {
888 self
889 .with_event()
890 .listen_for::<card_game::stack::priority::Priority<#first_state>, #event, Listener>(input.clone())
891 #(
892 .listen_for::<card_game::stack::priority::Priority<#states>, #event, Listener>(input.clone())
893 )*
894 #(
898 .listen_for::<card_game::events::EventPriorityStack<#stack_states, #stack_events, #stack_priority_resolutions<card_game::stack::priority::Priority<#stack_states>>>, #event, Listener>(
899 input.clone(),
900 )
901 )*
902 .finish_event()
903 }
904 }
905 });
906 }
907 }
908 quote::quote! {
918 #ast
919 #(#impls)*
934 }
935 .into()
936 } else {
937 panic!("`event_manager` can only be used with named structs");
938 }
939}
940
941fn substitute_type(ty: &Type, from: &Ident, to: &Type) -> Type {
942 let mut out = ty.clone();
943 TypeSubstituter { from, to }.visit_type_mut(&mut out);
944 out
945}
946
947struct TypeSubstituter<'a> {
948 from: &'a Ident,
949 to: &'a Type,
950}
951
952impl<'a> syn::visit_mut::VisitMut for TypeSubstituter<'a> {
953 fn visit_type_mut(&mut self, node: &mut Type) {
954 match node {
955 Type::Path(TypePath { path, .. })
956 if path.segments.len() == 1 && &path.segments[0].ident == self.from =>
957 {
958 *node = self.to.clone();
959 }
960 _ => {
961 syn::visit_mut::visit_type_mut(self, node);
962 }
963 }
964 }
965}
966
967fn type_to_ident(ty: &Type) -> &Ident {
968 match ty {
969 Type::Path(type_path) => type_path
970 .path
971 .segments
972 .last()
973 .map(|seg| &seg.ident)
974 .unwrap(),
975 _ => unimplemented!(),
976 }
977}