macro_machines/
macro_def.rs

1/// State machines with a default `initial` state.
2///
3/// For each extended state field, either the type must implement `Default`, or
4/// else a default expression is provided following `=`.
5///
6/// For a state machine that requires runtime initialization, see
7/// `def_machine_nodefault!`.
8
9#[macro_export]
10macro_rules! def_machine {
11  //
12  //  main interface
13  //
14  ( machine $machine:ident
15      $(<$(
16        $type_var:ident $(: { $($type_constraint:path),+ })*
17      ),+>)*
18    {
19      STATES [
20        $(state $state:ident (
21          $($data_name:ident : $data_type:ty $(= $data_default:expr)*),*
22        ) $({
23          $(entry $entry:block)*
24          $(exit  $exit:block)*
25        })*)+
26      ]
27      EVENTS [
28        $(event $event:ident <$source:tt> $(=> <$target:ident>)*
29          ($($param_name:ident : $param_type:ty $(= $param_default:expr)*),*)
30          $({ $($state_data:ident),* } => $action:block)*
31        )*
32      ]
33      EXTENDED [
34        $($ext_name:ident : $ext_type:ty $(= $ext_default:expr)*),*
35      ]
36      $(self_reference: $self_reference:ident)*
37      initial_state: $initial:ident $({
38        $(initial_action: $initial_action:block)*
39      })*
40      $(terminal_state: $terminal:ident $({
41        $(terminate_success: $terminate_success:block)*
42        $(terminate_failure: $terminate_failure:block)*
43      })*)*
44    }
45
46  ) => {
47
48    $crate::def_machine!{
49      @base
50      machine $machine
51        $(<$($type_var $(: { $($type_constraint),+ })*),+>)*
52      {
53        STATES [
54          $(state $state ($($data_name : $data_type $(= $data_default)*),*)
55          $({
56            $(entry $entry)*
57            $(exit  $exit)*
58          })*)+
59        ]
60        EVENTS [
61          $(event $event <$source> $(=> <$target>)*
62            ($($param_name : $param_type $(= $param_default)*),*)
63            $({$($state_data),*} => $action)*
64          )*
65        ]
66        EXTENDED [
67          $($ext_name : $ext_type $(= $ext_default)*),*
68        ]
69        $(self_reference: $self_reference)*
70        initial_state: $initial $({
71          $(initial_action: $initial_action)*
72        })*
73        $(terminal_state: $terminal $({
74          $(terminate_success: $terminate_success)*
75          $(terminate_failure: $terminate_failure)*
76        })*)*
77      }
78    }
79
80    impl $(<$($type_var),+>)* $machine $(<$($type_var),+>)* where
81    $($(
82      $($($type_var : $type_constraint),+)*
83    ),+)*
84    {
85      pub fn initial() -> Self {
86        $crate::log::debug!(
87          machine=stringify!($machine), state=stringify!($initial);
88          "initialize state machine");
89        let mut extended_state = ExtendedState::initial();
90        let state = StateId::$initial.to_state (&mut extended_state);
91        let mut initial = Self { state, extended_state };
92        {
93          $(#[allow(unused_variables)]
94          let $self_reference = &mut initial;)*
95          $($($initial_action)*)*
96        }
97        initial.state_entry();
98        initial
99      }
100    }
101
102    impl $(<$($type_var),+>)* $crate::MachineDotfile
103      for $machine $(<$($type_var),+>)*
104    where
105    $($(
106      $($($type_var : $type_constraint),+)*
107    ),+)*
108    {
109      fn name() -> &'static str {
110        stringify!($machine)
111      }
112      fn type_vars() -> Vec <String> {
113        let mut _v = Vec::new();
114        $($(
115        _v.push (format!(
116          "{} = {}", stringify!($type_var), std::any::type_name::<$type_var>()));
117        )+)*
118        _v
119      }
120      fn extended_state_names() -> Vec <&'static str> {
121        vec![$(stringify!($ext_name)),*]
122      }
123      fn extended_state_types() -> Vec <&'static str> {
124        vec![$(stringify!($ext_type)),*]
125      }
126      fn extended_state_defaults() -> Vec <&'static str> {
127        let mut _v = Vec::new();
128        $(
129        _v.push ({
130          let default_expr = stringify!($($ext_default)*);
131          if !default_expr.is_empty() {
132            default_expr
133          } else {
134            concat!(stringify!($ext_type), "::default()")
135          }
136        });
137        )*
138        _v
139      }
140      fn self_reference() -> &'static str {
141        stringify!($($self_reference)*)
142      }
143      fn states() -> Vec <&'static str> {
144        vec![$(stringify!($state)),+]
145      }
146      fn state_initial() -> &'static str {
147        stringify!($initial)
148      }
149      fn state_terminal() -> &'static str {
150        stringify!($($terminal)*)
151      }
152      fn state_data_names() -> Vec <Vec <&'static str>> {
153        let mut v = Vec::new();
154        $({
155          let mut _w = Vec::new();
156          $(_w.push (stringify!($data_name));)*
157          v.push (_w);
158        })+
159        v
160      }
161      fn state_data_types() -> Vec <Vec <&'static str>> {
162        let mut v = Vec::new();
163        $({
164          let mut _w = Vec::new();
165          $(_w.push (stringify!($data_type));)*
166          v.push (_w);
167        })+
168        v
169      }
170      fn state_data_defaults() -> Vec <Vec <&'static str>> {
171        let mut v = Vec::new();
172        $({
173          let mut _w = Vec::new();
174          $(
175          _w.push ({
176            let default_expr = stringify!($($data_default)*);
177            if !default_expr.is_empty() {
178              default_expr
179            } else {
180              concat!(stringify!($data_type), "::default()")
181            }
182          });
183          )*
184          v.push (_w);
185        })+
186        v
187      }
188      /// &#9888; This function creates default values for each state data field
189      /// and creates a pretty printed string of the value
190      fn state_data_pretty_defaults() -> Vec <Vec <String>> {
191        let mut v = Vec::new();
192        $({
193          let mut _w = Vec::new();
194          $(
195          let default_val : $data_type
196            = $crate::def_machine!(@expr_default $($data_default)*);
197          _w.push (format!("{:#?}", default_val));
198          )*
199          v.push (_w);
200        })+
201        v
202      }
203      fn events() -> Vec <&'static str> {
204        vec![$(stringify!($event)),*]
205      }
206      fn event_sources() -> Vec <&'static str> {
207        vec![$(stringify!($source)),*]
208      }
209      fn event_targets() -> Vec <&'static str> {
210        vec![$(stringify!($($target)*)),*]
211      }
212      fn event_actions() -> Vec <&'static str> {
213        vec![$(stringify!($($action)*)),*]
214      }
215    } // end impl MachineDotfile
216
217    impl $(<$($type_var),+>)* ExtendedState $(<$($type_var),+>)* where
218    $($(
219      $($($type_var : $type_constraint),+)*
220    ),+)*
221    {
222      pub fn initial() -> Self {
223        Self {
224          $($ext_name: $crate::def_machine!(@expr_default $($ext_default)*)),*
225        }
226      }
227
228      /// Creation method that allows overriding defaults.
229      pub fn new ($($ext_name : Option <$ext_type>),*) -> Self {
230        Self {
231          $($ext_name: $ext_name.unwrap_or (
232            $crate::def_machine!(@expr_default $($ext_default)*))
233          ),*
234        }
235      }
236    }
237
238    impl <'event> From <EventId> for Event <'event> {
239      /// Construct an event with default parameters for the given ID
240      fn from (id : EventId) -> Self {
241        let _params = id.clone().into();
242        Event { id, params: _params }
243      }
244    }
245
246    impl <'event> From <EventId> for EventParams <'event> {
247      fn from (id : EventId) -> Self {
248        match id {
249          $(EventId::$event => EventParams::$event {
250            $($param_name:
251              $crate::def_machine!(@expr_default $($param_default)*)
252            ),*
253          }),*
254        }
255      }
256    }
257
258  };
259  //  end main interface
260
261  //
262  //  alternate syntax
263  //
264  ( $machine:ident
265    $(<$(
266      $type_var:ident $(: { $($type_constraint:path),+ })*
267    ),+>)*
268    $(($(
269      $ext_name:ident : $ext_type:ty $(= $ext_default:expr)*
270    ),*))*
271    $(@ $self_reference:ident)*
272    {
273      STATES [
274        $(state $state:ident (
275          $($data_name:ident : $data_type:ty $(= $data_default:expr)*),*
276        ) $({
277          $(entry $entry:block)*
278          $(exit  $exit:block)*
279        })*)+
280      ]
281      EVENTS [
282        $(event $event:ident <$source:tt> $(=> <$target:ident>)*
283          ($($param_name:ident : $param_type:ty $(= $param_default:expr)*),*)
284          $({ $($state_data:ident),* } => $action:block)*
285        )*
286      ]
287      initial_state: $initial:ident $({
288        $(initial_action: $initial_action:block)*
289      })*
290      $(terminal_state: $terminal:ident $({
291        $(terminate_success: $terminate_success:block)*
292        $(terminate_failure: $terminate_failure:block)*
293      })*)*
294    }
295
296  ) => {
297
298    $crate::def_machine!{
299      machine $machine $(<$($type_var $(: { $($type_constraint),+ })*),+>)* {
300        STATES [
301          $(state $state ($($data_name : $data_type $(= $data_default)*),*)
302          $({
303            $(entry $entry)*
304            $(exit  $exit)*
305          })*)+
306        ]
307        EVENTS [
308          $(event $event <$source> $(=> <$target>)*
309            ($($param_name : $param_type $(= $param_default)*),*)
310            $({$($state_data),*} => $action)*
311          )*
312        ]
313        EXTENDED [
314          $($($ext_name : $ext_type $(= $ext_default)*),*)*
315        ]
316        $(self_reference: $self_reference)*
317        initial_state: $initial $({
318          $(initial_action: $initial_action)*
319        })*
320        $(terminal_state: $terminal $({
321          $(terminate_success: $terminate_success)*
322          $(terminate_failure: $terminate_failure)*
323        })*)*
324      }
325    }
326
327  };
328
329  //
330  //  @impl_fn_handle_event
331  //
332  ( @impl_fn_handle_event
333    machine $machine:ident {
334      EVENTS [
335        $(event $event:ident <$source:tt> $(=> <$target:ident>)*
336          ($($param_name:ident),*)
337          $({ $($state_data:ident),* } => $action:block)*
338        )*
339      ]
340      EXTENDED [
341        $($ext_name:ident : $ext_type:ty $(= $ext_default:expr)*),*
342      ]
343      $(self_reference: $self_reference:ident)*
344    }
345
346  ) => {
347
348    pub fn handle_event (&mut self, mut _event : Event)
349      -> Result <(), $crate::HandleEventException>
350    {
351      // if only one kind of transition exists the following match expression
352      // will detect the other branch as "unreachable_code"
353      #[allow(unreachable_code)]
354      match _event.transition() {
355        Transition::Universal (target_id) => {
356          $crate::log::debug!(
357            machine=stringify!($machine), state:?=self.state.id,
358            event:?=_event.id, transition="Universal", target:?=target_id;
359            "handle state machine event");
360          self.state_exit();
361          { // event action
362            // bring extended state variables into scope
363            #[allow(unused_variables)]
364            match &mut self.extended_state {
365              &mut ExtendedState { $(ref mut $ext_name,)*.. } => {
366                // map each event to an action
367                match _event.params {
368                  $(EventParams::$event { $(mut $param_name,)*.. } => {
369                    // only expands universal actions, unreachable otherwise
370                    $crate::def_machine!{
371                      @event_action_universal
372                      event $event <$source> $(=> <$target>)* $($action)*
373                    }
374                  })*
375                  _ => unreachable!("unreachable phantom data variant")
376                }
377              }
378            }
379          }
380          let state  = target_id.to_state (&mut self.extended_state);
381          self.state = state;
382          self.state_entry();
383          Ok (())
384        }
385        Transition::Internal (source_id) => {
386          if self.state.id == source_id {
387            $crate::log::debug!(
388              machine=stringify!($machine), state:?=self.state.id,
389              event:?=_event.id, transition="Internal", source_state:?=source_id;
390              "handle state machine event");
391            // bring extended state variables into scope
392            #[allow(unused_variables)]
393            match &mut self.extended_state {
394              &mut ExtendedState { $(ref mut $ext_name,)*.. } => {
395                // map each event to an action
396                match _event.params {
397                  $(EventParams::$event { $(mut $param_name,)*.. } => {
398                    // for universal transitions there is no source state so
399                    // this produces a wildcard pattern resulting in the
400                    // last branch being unreachable
401                    // bring local state variables into scope
402                    #[allow(unreachable_patterns)]
403                    match &mut self.state.data {
404                      $crate::def_machine!{
405                        @event_internal_state_pattern
406                        $source { $($($state_data),*)* }
407                      } => {
408                        // only expands internal actions, unreachable otherwise
409                        $crate::def_machine!{
410                          @event_action_internal
411                          event $event <$source> $(=> <$target>)* $($action)*
412                        }
413                      }
414                      _ => unreachable!("current state should match event source")
415                    }
416                  })*
417                  _ => unreachable!("unreachable phantom data variant")
418                }
419              }
420            }
421            Ok (())
422          } else {
423            let exception = $crate::HandleEventException::WrongState;
424            $crate::log::warn!(
425              machine=stringify!($machine), state:?=self.state.id,
426              event:?=_event.id, transition="Internal", source:?=source_id,
427              exception:?;
428              "handle state machine event exception");
429            Err (exception)
430          }
431        }
432        Transition::External (source_id, target_id) => {
433          if self.state.id == source_id {
434            $crate::log::debug!(
435              machine=stringify!($machine), state:?=self.state.id,
436              event:?=_event.id, transition="External", source:?=source_id,
437              target:?=target_id;
438              "handle state machine event");
439            self.state_exit();
440            { // event action
441              // bring extended state variables into scope
442              #[allow(unused_variables)]
443              match &mut self.extended_state {
444                &mut ExtendedState { $(ref mut $ext_name,)*.. } => {
445                  // map each event to an action
446                  match _event.params {
447                    $(EventParams::$event { $(mut $param_name,)*.. } => {
448                      // only expands external actions, unreachable otherwise
449                      $crate::def_machine!{
450                        @event_action_external
451                        event $event <$source> $(=> <$target>)* $($action)*
452                      }
453                    })*
454                    _ => unreachable!("unreachable phantom data variant")
455                  }
456                }
457              }
458            }
459            let state  = target_id.to_state (&mut self.extended_state);
460            self.state = state;
461            self.state_entry();
462            Ok (())
463          } else {
464            let exception = $crate::HandleEventException::WrongState;
465            $crate::log::warn!(
466              machine=stringify!($machine), state:?=self.state.id,
467              event:?=_event.id, transition="External", source:?=source_id,
468              target:?=target_id, exception:?;
469              "handle state machine event exception");
470            Err (exception)
471          }
472        }
473      } // end match transition
474    } // end fn handle_event
475
476  };  // end @impl_fn_handle_event
477
478  //
479  //  @event_internal_state_pattern
480  //
481  ( @event_internal_state_pattern
482    $source:ident { $($state_data:ident),* }
483  ) => {
484    &mut StateData::$source {$(ref mut $state_data,)*..}
485  };
486
487  //
488  //  @event_internal_state_pattern: not an internal event
489  //
490  ( @event_internal_state_pattern
491    * { $($state_data:ident),* }
492  ) => {
493    _
494  };
495
496  //
497  //  @event_action_external
498  //
499  ( @event_action_external
500    event $event:ident <$source:ident> => <$target:ident> $($action:block)*
501  ) => {
502    $($action)*
503  };
504
505  //
506  //  @event_action_external: not an external event
507  //
508  ( @event_action_external
509    event $event:ident <$source:ident> $($action:block)*
510  ) => { unreachable!("not an external event") };
511
512  //
513  //  @event_action_external: not an external event
514  //
515  ( @event_action_external
516    event $event:ident <*> => <$target:ident> $($action:block)*
517  ) => { unreachable!("not an external event") };
518
519  //
520  //  @event_action_universal
521  //
522  ( @event_action_universal
523    event $event:ident <*> => <$target:ident> $($action:block)*
524  ) => {
525    $($action)*
526  };
527
528  //
529  //  @event_action_universal: not an universal event
530  //
531  ( @event_action_universal
532    event $event:ident <$source:ident> $(=> <$target:ident>)* $($action:block)*
533  ) => { unreachable!("not an universal event") };
534
535  //
536  //  @event_action_internal
537  //
538  ( @event_action_internal
539    event $event:ident <$source:ident> $($action:block)*
540  ) => {
541    $($action)*
542  };
543
544  //
545  //  @event_action_internal: not an internal event
546  //
547  ( @event_action_internal
548    event $event:ident <$source:tt> => <$target:ident> $($action:block)*
549  ) => { unreachable!("not an internal event") };
550
551  //
552  //  @event_transition: external
553  //
554  ( @event_transition <$source:ident> => <$target:ident> ) => {
555    Transition::External (StateId::$source, StateId::$target)
556  };
557
558  //
559  //  @event_transition: internal
560  //
561  ( @event_transition <$source:ident> ) => {
562    Transition::Internal (StateId::$source)
563  };
564
565  //
566  //  @event_transition: universal
567  //
568  ( @event_transition <*> => <$target:ident> ) => {
569    Transition::Universal (StateId::$target)
570  };
571
572  //
573  //  @expr_default: override default
574  //
575  ( @expr_default $default:expr ) => { $default };
576
577  //
578  //  @expr_default: use default
579  //
580  ( @expr_default ) => { Default::default() };
581
582  //
583  //  @expr_option: Some
584  //
585  ( @expr_option $default:expr ) => { Some ($default) };
586
587  //
588  //  @expr_option: None
589  //
590  ( @expr_option ) => { None };
591
592  //
593  //  @base implementation rule
594  //
595  ( @base
596    machine $machine:ident
597      $(<$(
598        $type_var:ident $(: { $($type_constraint:path),+ })*
599      ),+>)*
600    {
601      STATES [
602        $(state $state:ident (
603          $($data_name:ident : $data_type:ty $(= $data_default:expr)*),*
604        ) $({
605          $(entry $entry:block)*
606          $(exit  $exit:block)*
607        })*)+
608      ]
609      EVENTS [
610        $(event $event:ident <$source:tt> $(=> <$target:ident>)*
611          ($($param_name:ident : $param_type:ty $(= $param_default:expr)*),*)
612          $({ $($state_data:ident),* } => $action:block)*
613        )*
614      ]
615      EXTENDED [
616        $($ext_name:ident : $ext_type:ty $(= $ext_default:expr)*),*
617      ]
618      $(self_reference: $self_reference:ident)*
619      initial_state: $initial:ident $({
620        $(initial_action: $initial_action:block)*
621      })*
622      $(terminal_state: $terminal:ident $({
623        $(terminate_success: $terminate_success:block)*
624        $(terminate_failure: $terminate_failure:block)*
625      })*)*
626    }
627
628  ) => {
629
630    pub struct $machine $(<$($type_var),+>)* where
631    $($(
632      $($($type_var : $type_constraint),+)*
633    ),+)*
634    {
635      state          : State,
636      extended_state : ExtendedState $(<$($type_var),+>)*
637    }
638
639    pub struct State {
640      id   : StateId,
641      data : StateData
642    }
643
644    pub struct ExtendedState $(<$($type_var),+>)* where
645    $($(
646      $($($type_var : $type_constraint),+)*
647    ),+)*
648    {
649      $(pub $ext_name : $ext_type),*
650    }
651
652    pub struct Event <'event> {
653      id     : EventId,
654      params : EventParams <'event>
655    }
656
657    #[derive(Clone, Debug, Eq, PartialEq, $crate::VariantCount)]
658    pub enum StateId {
659      $($state),+
660    }
661
662    pub enum StateData {
663      $($state {
664        $($data_name : $data_type),*
665      }),+
666    }
667
668    #[derive(Debug, Eq, PartialEq)]
669    pub enum Transition {
670      Internal  (StateId),
671      External  (StateId, StateId),
672      Universal (StateId)
673    }
674
675    #[derive(Clone, Debug, Eq, PartialEq, $crate::VariantCount)]
676    pub enum EventId {
677      $($event),*
678    }
679
680    pub enum EventParams <'event> {
681      $($event {
682        $($param_name : $param_type),*
683      },)*
684      _PhantomData (::std::marker::PhantomData <&'event ()>)
685    }
686
687    impl $(<$($type_var),+>)* $machine $(<$($type_var),+>)* where
688    $($(
689      $($($type_var : $type_constraint),+)*
690    ),+)*
691    {
692      pub fn report_sizes() where $($($type_var : 'static),+)* {
693        let machine_name = stringify!($machine);
694        let machine_type = std::any::type_name::<Self>();
695        println!("{}::report_sizes...", machine_name);
696        println!("  size of {}: {}", machine_type,
697          std::mem::size_of::<Self>());
698        println!("...{}::report_sizes", machine_name);
699      }
700
701      pub fn new (mut extended_state : ExtendedState $(<$($type_var),+>)*)
702        -> Self
703      {
704        let state   = StateId::$initial.to_state (&mut extended_state);
705        let mut new = Self { state, extended_state };
706        {
707          $(#[allow(unused_variables)]
708          let $self_reference = &mut new;)*
709          $($($initial_action)*)*
710        }
711        new.state_entry();
712        new
713      }
714
715      #[allow(dead_code)]
716      #[inline]
717      pub fn state (&self) -> &State {
718        &self.state
719      }
720
721      #[allow(dead_code)]
722      #[inline]
723      pub fn state_id (&self) -> StateId {
724        self.state().id().clone()
725      }
726
727      #[allow(dead_code)]
728      #[inline]
729      pub fn state_data (&self) -> &StateData {
730        self.state().data()
731      }
732
733      #[allow(dead_code)]
734      #[inline]
735      pub fn extended_state (&self) -> &ExtendedState $(<$($type_var),+>)* {
736        &self.extended_state
737      }
738
739      #[allow(dead_code)]
740      #[inline]
741      pub fn extended_state_mut (&mut self)
742        -> &mut ExtendedState $(<$($type_var),+>)*
743      {
744        &mut self.extended_state
745      }
746
747      $crate::def_machine!{
748        @impl_fn_handle_event
749        machine $machine {
750          EVENTS [
751            $(event $event <$source> $(=> <$target>)*
752              ($($param_name),*)
753              $({$($state_data),*} => $action)*
754            )*
755          ]
756          EXTENDED [
757            $($ext_name : $ext_type $(= $ext_default)*),*
758          ]
759          $(self_reference: $self_reference)*
760        }
761      }
762
763      fn state_entry (&mut self) {
764        // bring extended state variables into scope
765        #[allow(unused_variables)]
766        match &mut self.extended_state {
767          &mut ExtendedState { $(ref mut $ext_name,)*.. } => {
768            match self.state.data {
769              // bring local state variables into scope
770              $(StateData::$state { $(ref mut $data_name,)*.. } => {
771                $($($entry)*)*
772              })+
773            }
774          }
775        }
776      }
777      fn state_exit (&mut self) {
778        // bring extended state variables into scope
779        #[allow(unused_variables)]
780        match &mut self.extended_state {
781          &mut ExtendedState { $(ref mut $ext_name,)*.. } => {
782            match self.state.data {
783              // bring local state variables into scope
784              $(StateData::$state { $(ref mut $data_name,)*.. } => {
785                $($($exit)*)*
786              })+
787            }
788          }
789        }
790      }
791
792    } // end impl $machine
793
794    impl $(<$($type_var),+>)* AsRef <ExtendedState $(<$($type_var),+>)*>
795      for $machine $(<$($type_var),+>)*
796    where
797    $($(
798      $($($type_var : $type_constraint),+)*
799    ),+)*
800    {
801      #[inline]
802      fn as_ref (&self) -> &ExtendedState $(<$($type_var),+>)* {
803        &self.extended_state
804      }
805    }
806
807    impl $(<$($type_var),+>)* AsMut <ExtendedState $(<$($type_var),+>)*>
808      for $machine $(<$($type_var),+>)*
809    where
810    $($(
811      $($($type_var : $type_constraint),+)*
812    ),+)*
813    {
814      #[inline]
815      fn as_mut (&mut self) -> &mut ExtendedState $(<$($type_var),+>)* {
816        &mut self.extended_state
817      }
818    }
819
820    impl $(<$($type_var),+>)* Drop for $machine $(<$($type_var),+>)* where
821    $($(
822      $($($type_var : $type_constraint),+)*
823    ),+)*
824    {
825      fn drop (&mut self) {
826        self.state_exit();
827        let _state_id = self.state.id.clone();
828        $(#[allow(unused_variables)]
829        let $self_reference = &mut *self;)*
830        $(
831        if _state_id != StateId::$terminal {
832          $crate::log::warn!(
833            machine=stringify!($machine), state:?=_state_id,
834            terminal:?=StateId::$terminal;
835            "terminate state machine failure: not in terminal state");
836          $($($terminate_failure)*)*
837        } else {
838          $crate::log::debug!(
839            machine=stringify!($machine), state:?=_state_id;
840            "terminate state machine success");
841          $($($terminate_success)*)*
842        }
843        )*
844      }
845    }
846
847    impl State {
848      #[inline]
849      pub fn id (&self) -> &StateId {
850        &self.id
851      }
852
853      #[inline]
854      pub fn data (&self) -> &StateData {
855        &self.data
856      }
857    }
858
859    impl StateId {
860      #[inline]
861      pub const fn initial() -> Self {
862        StateId::$initial
863      }
864      $(
865      #[inline]
866      pub const fn terminal() -> Self {
867        StateId::$terminal
868      }
869      )*
870      #[expect(clippy::wrong_self_convention)]
871      pub fn to_state $(<$($type_var),+>)* (self,
872        extended_state : &mut ExtendedState$(<$($type_var),+>)*) -> State
873      where
874      $($(
875        $($($type_var : $type_constraint),+)*
876      ),+)*
877      {
878        // bring extended state variables into scope
879        #[allow(unused_variables)]
880        match extended_state {
881          &mut ExtendedState { $(ref mut $ext_name,)*.. } => {
882            match self {
883              $(StateId::$state => {
884                State {
885                  id:   self,
886                  data: StateData::$state {
887                    $($data_name:
888                      $crate::def_machine!(@expr_default $($data_default)*)
889                    ),*
890                  }
891                }
892              })+
893            }
894          }
895        }
896      }
897    }
898
899    impl EventId {
900      pub fn transition (&self) -> Transition {
901        #[allow(clippy::uninhabited_references)]
902        match *self {
903          $(
904          EventId::$event =>
905            $crate::def_machine!(@event_transition <$source> $(=> <$target>)*)
906          ),*
907        }
908      }
909    }
910
911    impl <'event> EventParams <'event> {
912      pub fn id (&self) -> EventId {
913        match *self {
914          $(EventParams::$event {..} => EventId::$event,)*
915          _ => unreachable!("unreachable phantom data variant")
916        }
917      }
918    }
919
920    impl <'event> Event <'event> {
921      #[inline]
922      pub fn transition (&self) -> Transition {
923        self.id.transition()
924      }
925
926      #[inline]
927      #[allow(clippy::uninhabited_references)]
928      pub fn id (&self) -> &EventId {
929        &self.id
930      }
931
932      #[inline]
933      #[expect(mismatched_lifetime_syntaxes)]
934      pub fn params (&self) -> &EventParams {
935        &self.params
936      }
937    }
938
939    impl <'event> From <EventParams <'event>> for Event <'event> {
940      fn from (params : EventParams <'event>) -> Self {
941        let _id = params.id();
942        Event { id: _id, params }
943      }
944    }
945
946  };  // end @base
947
948} // end def_machine!
949
950/// State machine that requires runtime initialization.
951#[macro_export]
952macro_rules! def_machine_nodefault {
953  //
954  //  main implementation rule
955  //
956  ( machine $machine:ident
957      $(<$(
958        $type_var:ident $(: { $($type_constraint:path),+ })*
959      ),+>)*
960    {
961      STATES [
962        $(state $state:ident (
963          $($data_name:ident : $data_type:ty $(= $data_default:expr)*),*
964        ) $({
965          $(entry $entry:block)*
966          $(exit  $exit:block)*
967        })*)+
968      ]
969      EVENTS [
970        $(event $event:ident <$source:tt> $(=> <$target:ident>)*
971          ($($param_name:ident : $param_type:ty $(= $param_default:expr)*),*)
972          $({ $($state_data:ident),* } => $action:block)*
973        )*
974      ]
975      EXTENDED [
976        $($ext_name:ident : $ext_type:ty $(= $ext_default:expr)*),*
977      ]
978      $(self_reference: $self_reference:ident)*
979      initial_state: $initial:ident $({
980        $(initial_action: $initial_action:block)*
981      })*
982      $(terminal_state: $terminal:ident $({
983        $(terminate_success: $terminate_success:block)*
984        $(terminate_failure: $terminate_failure:block)*
985      })*)*
986    }
987
988  ) => {
989
990    $crate::def_machine!{
991      @base
992      machine $machine
993        $(<$($type_var $(: { $($type_constraint),+ })*),+>)*
994      {
995        STATES [
996          $(state $state ($($data_name : $data_type $(= $data_default)*),*)
997          $({
998            $(entry $entry)*
999            $(exit  $exit)*
1000          })*)+
1001        ]
1002        EVENTS [
1003          $(event $event <$source> $(=> <$target>)*
1004            ($($param_name : $param_type $(= $param_default)*),*)
1005            $({$($state_data),*} => $action)*
1006          )*
1007        ]
1008        EXTENDED [
1009          $($ext_name : $ext_type $(= $ext_default)*),*
1010        ]
1011        $(self_reference: $self_reference)*
1012        initial_state: $initial $({
1013          $(initial_action: $initial_action)*
1014        })*
1015        $(terminal_state: $terminal $({
1016          $(terminate_success: $terminate_success)*
1017          $(terminate_failure: $terminate_failure)*
1018        })*)*
1019      }
1020    }
1021
1022    impl $(<$($type_var),+>)* $crate::MachineDotfile
1023      for $machine $(<$($type_var),+>)*
1024    where
1025    $($(
1026      $($($type_var : $type_constraint),+)*
1027    ),+)*
1028    {
1029      fn name() -> &'static str {
1030        stringify!($machine)
1031      }
1032      fn type_vars() -> Vec <String> {
1033        let mut _v = Vec::new();
1034        $($(
1035        _v.push (format!(
1036        "{} = {}", stringify!($type_var), std::any::type_name::<$type_var>()));
1037        )+)*
1038        _v
1039      }
1040      fn extended_state_names() -> Vec <&'static str> {
1041        let mut _v = Vec::new();
1042        $(
1043        _v.push (stringify!($ext_name));
1044        )*
1045        _v
1046      }
1047      fn extended_state_types() -> Vec <&'static str> {
1048        let mut _v = Vec::new();
1049        $(
1050        _v.push (stringify!($ext_type));
1051        )*
1052        _v
1053      }
1054      fn extended_state_defaults() -> Vec <&'static str> {
1055        let mut _v = Vec::new();
1056        $(
1057        _v.push (stringify!($($ext_default)*));
1058        )*
1059        _v
1060      }
1061      fn self_reference() -> &'static str {
1062        stringify!($($self_reference)*)
1063      }
1064      fn states() -> Vec <&'static str> {
1065        vec![$(stringify!($state)),+]
1066      }
1067      fn state_initial() -> &'static str {
1068        stringify!($initial)
1069      }
1070      fn state_terminal() -> &'static str {
1071        stringify!($($terminal)*)
1072      }
1073      fn state_data_names() -> Vec <Vec <&'static str>> {
1074        let mut v = Vec::new();
1075        $({
1076          let mut _w = Vec::new();
1077          $(_w.push (stringify!($data_name));)*
1078          v.push (_w);
1079        })+
1080        v
1081      }
1082      fn state_data_types() -> Vec <Vec <&'static str>> {
1083        let mut v = Vec::new();
1084        $({
1085          let mut _w = Vec::new();
1086          $(_w.push (stringify!($data_type));)*
1087          v.push (_w);
1088        })+
1089        v
1090      }
1091      fn state_data_defaults() -> Vec <Vec <&'static str>> {
1092        let mut v = Vec::new();
1093        $({
1094          let mut _w = Vec::new();
1095          $(_w.push (stringify!($($data_default)*));)*
1096          v.push (_w);
1097        })+
1098        v
1099      }
1100      /// This version does not evaluate expressions, only pretty prints them
1101      fn state_data_pretty_defaults() -> Vec <Vec <String>> {
1102        let mut v = Vec::new();
1103        $({
1104          let mut _w = Vec::new();
1105          $(
1106          _w.push (format!("{:#?}", stringify!($($data_default)*)));
1107          )*
1108          v.push (_w);
1109        })+
1110        v
1111      }
1112      fn events() -> Vec <&'static str> {
1113        vec![$(stringify!($event)),*]
1114      }
1115      fn event_sources() -> Vec <&'static str> {
1116        vec![$(stringify!($source)),*]
1117      }
1118      fn event_targets() -> Vec <&'static str> {
1119        vec![$(stringify!($($target)*)),*]
1120      }
1121      fn event_actions() -> Vec <&'static str> {
1122        vec![$(stringify!($($action)*)),*]
1123      }
1124    } // end impl MachineDotfile
1125
1126    impl $(<$($type_var),+>)* ExtendedState $(<$($type_var),+>)* where
1127    $($(
1128      $($($type_var : $type_constraint),+)*
1129    ),+)*
1130    {
1131      /// Creation method that allows overriding defaults. If a field does not
1132      /// have a default specified it is a required argument.
1133      // TODO: indicate which arguments are missing in case of failure
1134      // TODO: make required arguments non-Option types?
1135      pub fn new ($($ext_name : Option <$ext_type>),*) -> Option <Self> {
1136        Some (Self {
1137          $($ext_name: {
1138            if let Some ($ext_name) = $ext_name {
1139              $ext_name
1140            } else {
1141              $crate::def_machine!(@expr_option $($ext_default)*)?
1142            }
1143          }),*
1144        })
1145      }
1146    }
1147  };
1148
1149  //
1150  //  alternate syntax
1151  //
1152  ( $machine:ident
1153    $(<$(
1154      $type_var:ident $(: { $($type_constraint:path),+ })*
1155    ),+>)*
1156    $(($(
1157      $ext_name:ident : $ext_type:ty $(= $ext_default:expr)*
1158    ),*))*
1159    $(@ $self_reference:ident)*
1160    {
1161      STATES [
1162        $(state $state:ident (
1163          $($data_name:ident : $data_type:ty $(= $data_default:expr)*),*
1164        ) $({
1165          $(entry $entry:block)*
1166          $(exit  $exit:block)*
1167        })*)+
1168      ]
1169      EVENTS [
1170        $(event $event:ident <$source:tt> $(=> <$target:ident>)*
1171          ($($param_name:ident : $param_type:ty $(= $param_default:expr)*),*)
1172          $({ $($state_data:ident),* } => $action:block)*
1173        )*
1174      ]
1175      initial_state: $initial:ident $({
1176        $(initial_action: $initial_action:block)*
1177      })*
1178      $(terminal_state: $terminal:ident $({
1179        $(terminate_success: $terminate_success:block)*
1180        $(terminate_failure: $terminate_failure:block)*
1181      })*)*
1182    }
1183
1184  ) => {
1185
1186    $crate::def_machine_nodefault!{
1187      machine $machine $(<$($type_var $(: { $($type_constraint),+ })*),+>)* {
1188        STATES [
1189          $(state $state ($($data_name : $data_type $(= $data_default)*),*)
1190          $({
1191            $(entry $entry)*
1192            $(exit  $exit)*
1193          })*)+
1194        ]
1195        EVENTS [
1196          $(event $event <$source> $(=> <$target>)*
1197            ($($param_name : $param_type $(= $param_default)*),*)
1198            $({$($state_data),*} => $action)*
1199          )*
1200        ]
1201        EXTENDED [
1202          $($($ext_name : $ext_type $(= $ext_default)*),*)*
1203        ]
1204        $(self_reference: $self_reference)*
1205        initial_state: $initial $({
1206          $(initial_action: $initial_action)*
1207        })*
1208        $(terminal_state: $terminal $({
1209          $(terminate_success: $terminate_success)*
1210          $(terminate_failure: $terminate_failure)*
1211        })*)*
1212      }
1213    }
1214
1215  };
1216
1217} // end def_machine_nodefault!
1218
1219/// State machines with a default `initial` state and deriving `Debug`.
1220///
1221/// For each extended state field, either the type must implement `Default`, or
1222/// else a default expression is provided following `=`.
1223///
1224/// For a state machine that requires runtime initialization, see
1225/// `def_machine_nodefault_debug!`.
1226
1227#[macro_export]
1228macro_rules! def_machine_debug {
1229  //
1230  //  main interface
1231  //
1232  ( machine $machine:ident
1233      $(<$(
1234        $type_var:ident $(: { $($type_constraint:path),+ })*
1235      ),+>)*
1236    {
1237      STATES [
1238        $(state $state:ident (
1239          $($data_name:ident : $data_type:ty $(= $data_default:expr)*),*
1240        ) $({
1241          $(entry $entry:block)*
1242          $(exit  $exit:block)*
1243        })*)+
1244      ]
1245      EVENTS [
1246        $(event $event:ident <$source:tt> $(=> <$target:ident>)*
1247          ($($param_name:ident : $param_type:ty $(= $param_default:expr)*),*)
1248          $({ $($state_data:ident),* } => $action:block)*
1249        )*
1250      ]
1251      EXTENDED [
1252        $($ext_name:ident : $ext_type:ty $(= $ext_default:expr)*),*
1253      ]
1254      $(self_reference: $self_reference:ident)*
1255      initial_state: $initial:ident $({
1256        $(initial_action: $initial_action:block)*
1257      })*
1258      $(terminal_state: $terminal:ident $({
1259        $(terminate_success: $terminate_success:block)*
1260        $(terminate_failure: $terminate_failure:block)*
1261      })*)*
1262    }
1263
1264  ) => {
1265
1266    $crate::def_machine_debug!{
1267      @base
1268      machine $machine
1269        $(<$($type_var $(: { $($type_constraint),+ })*),+>)*
1270      {
1271        STATES [
1272          $(state $state ($($data_name : $data_type $(= $data_default)*),*)
1273          $({
1274            $(entry $entry)*
1275            $(exit  $exit)*
1276          })*)+
1277        ]
1278        EVENTS [
1279          $(event $event <$source> $(=> <$target>)*
1280            ($($param_name : $param_type $(= $param_default)*),*)
1281            $({$($state_data),*} => $action)*
1282          )*
1283        ]
1284        EXTENDED [
1285          $($ext_name : $ext_type $(= $ext_default)*),*
1286        ]
1287        $(self_reference: $self_reference)*
1288        initial_state: $initial $({
1289          $(initial_action: $initial_action)*
1290        })*
1291        $(terminal_state: $terminal $({
1292          $(terminate_success: $terminate_success)*
1293          $(terminate_failure: $terminate_failure)*
1294        })*)*
1295      }
1296    }
1297
1298    impl $(<$($type_var),+>)* $machine $(<$($type_var),+>)* where
1299    $($(
1300      $type_var : std::fmt::Debug,
1301      $($($type_var : $type_constraint),+)*
1302    ),+)*
1303    {
1304      pub fn initial() -> Self {
1305        $crate::log::debug!(
1306          machine=stringify!($machine), state=stringify!($initial);
1307          "initialize state machine");
1308        let mut extended_state = ExtendedState::initial();
1309        let state = StateId::$initial.to_state (&mut extended_state);
1310        let mut initial = Self { state, extended_state };
1311        {
1312          $(#[allow(unused_variables)]
1313          let $self_reference = &mut initial;)*
1314          $($($initial_action)*)*
1315        }
1316        initial.state_entry();
1317        initial
1318      }
1319    }
1320
1321    impl $(<$($type_var),+>)* $crate::MachineDotfile
1322      for $machine $(<$($type_var),+>)*
1323    where
1324    $($(
1325      $type_var : std::fmt::Debug,
1326      $($($type_var : $type_constraint),+)*
1327    ),+)*
1328    {
1329      fn name() -> &'static str {
1330        stringify!($machine)
1331      }
1332      fn type_vars() -> Vec <String> {
1333        let mut _v = Vec::new();
1334        $($(
1335        _v.push (format!(
1336          "{} = {}", stringify!($type_var), std::any::type_name::<$type_var>()));
1337        )+)*
1338        _v
1339      }
1340      fn extended_state_names() -> Vec <&'static str> {
1341        let mut _v = Vec::new();
1342        $(
1343        _v.push (stringify!($ext_name));
1344        )*
1345        _v
1346      }
1347      fn extended_state_types() -> Vec <&'static str> {
1348        let mut _v = Vec::new();
1349        $(
1350        _v.push (stringify!($ext_type));
1351        )*
1352        _v
1353      }
1354      fn extended_state_defaults() -> Vec <&'static str> {
1355        let mut _v = Vec::new();
1356        $(
1357        _v.push ({
1358          let default_expr = stringify!($($ext_default)*);
1359          if !default_expr.is_empty() {
1360            default_expr
1361          } else {
1362            concat!(stringify!($ext_type), "::default()")
1363          }
1364        });
1365        )*
1366        _v
1367      }
1368      fn self_reference() -> &'static str {
1369        stringify!($($self_reference)*)
1370      }
1371      fn states() -> Vec <&'static str> {
1372        vec![$(stringify!($state)),+]
1373      }
1374      fn state_initial() -> &'static str {
1375        stringify!($initial)
1376      }
1377      fn state_terminal() -> &'static str {
1378        stringify!($($terminal)*)
1379      }
1380      fn state_data_names() -> Vec <Vec <&'static str>> {
1381        let mut v = Vec::new();
1382        $({
1383          let mut _w = Vec::new();
1384          $(_w.push (stringify!($data_name));)*
1385          v.push (_w);
1386        })+
1387        v
1388      }
1389      fn state_data_types() -> Vec <Vec <&'static str>> {
1390        let mut v = Vec::new();
1391        $({
1392          let mut _w = Vec::new();
1393          $(_w.push (stringify!($data_type));)*
1394          v.push (_w);
1395        })+
1396        v
1397      }
1398      fn state_data_defaults() -> Vec <Vec <&'static str>> {
1399        let mut v = Vec::new();
1400        $({
1401          let mut _w = Vec::new();
1402          $(
1403          _w.push ({
1404            let default_expr = stringify!($($data_default)*);
1405            if !default_expr.is_empty() {
1406              default_expr
1407            } else {
1408              concat!(stringify!($data_type), "::default()")
1409            }
1410          });
1411          )*
1412          v.push (_w);
1413        })+
1414        v
1415      }
1416      /// &#9888; This function creates default values for each state data field
1417      /// and creates a pretty printed string of the value
1418      fn state_data_pretty_defaults() -> Vec <Vec <String>> {
1419        let mut v = Vec::new();
1420        $({
1421          let mut _w = Vec::new();
1422          $(
1423          let default_val : $data_type
1424            = $crate::def_machine_debug!(@expr_default $($data_default)*);
1425          _w.push (format!("{:#?}", default_val));
1426          )*
1427          v.push (_w);
1428        })+
1429        v
1430      }
1431      fn events() -> Vec <&'static str> {
1432        vec![$(stringify!($event)),*]
1433      }
1434      fn event_sources() -> Vec <&'static str> {
1435        vec![$(stringify!($source)),*]
1436      }
1437      fn event_targets() -> Vec <&'static str> {
1438        vec![$(stringify!($($target)*)),*]
1439      }
1440      fn event_actions() -> Vec <&'static str> {
1441        vec![$(stringify!($($action)*)),*]
1442      }
1443    } // end impl MachineDotfile
1444
1445    impl $(<$($type_var),+>)* ExtendedState $(<$($type_var),+>)* where
1446    $($(
1447      $type_var : std::fmt::Debug,
1448      $($($type_var : $type_constraint),+)*
1449    ),+)*
1450    {
1451      pub fn initial() -> Self {
1452        Self {
1453          $($ext_name: $crate::def_machine_debug!(@expr_default $($ext_default)*)),*
1454        }
1455      }
1456
1457      /// Creation method that allows overriding defaults.
1458      pub fn new ($($ext_name : Option <$ext_type>),*) -> Self {
1459        Self {
1460          $($ext_name: $ext_name.unwrap_or (
1461            $crate::def_machine_debug!(@expr_default $($ext_default)*))
1462          ),*
1463        }
1464      }
1465    }
1466
1467    impl <'event> From <EventId> for Event <'event> {
1468      /// Construct an event with default parameters for the given ID
1469      fn from (id : EventId) -> Self {
1470        let _params = id.clone().into();
1471        Event { id, params: _params }
1472      }
1473    }
1474
1475    impl <'event> From <EventId> for EventParams <'event> {
1476      fn from (id : EventId) -> Self {
1477        match id {
1478          $(EventId::$event => EventParams::$event {
1479            $($param_name:
1480              $crate::def_machine_debug!(@expr_default $($param_default)*)
1481            ),*
1482          }),*
1483        }
1484      }
1485    }
1486
1487  };
1488  //  end main interface
1489
1490  //
1491  //  alternate syntax
1492  //
1493  ( $machine:ident
1494    $(<$(
1495      $type_var:ident $(: { $($type_constraint:path),+ })*
1496    ),+>)*
1497    $(($(
1498      $ext_name:ident : $ext_type:ty $(= $ext_default:expr)*
1499    ),*))*
1500    $(@ $self_reference:ident)*
1501    {
1502      STATES [
1503        $(state $state:ident (
1504          $($data_name:ident : $data_type:ty $(= $data_default:expr)*),*
1505        ) $({
1506          $(entry $entry:block)*
1507          $(exit  $exit:block)*
1508        })*)+
1509      ]
1510      EVENTS [
1511        $(event $event:ident <$source:tt> $(=> <$target:ident>)*
1512          ($($param_name:ident : $param_type:ty $(= $param_default:expr)*),*)
1513          $({ $($state_data:ident),* } => $action:block)*
1514        )*
1515      ]
1516      initial_state: $initial:ident $({
1517        $(initial_action: $initial_action:block)*
1518      })*
1519      $(terminal_state: $terminal:ident $({
1520        $(terminate_success: $terminate_success:block)*
1521        $(terminate_failure: $terminate_failure:block)*
1522      })*)*
1523    }
1524
1525  ) => {
1526
1527    $crate::def_machine_debug!{
1528      machine $machine $(<$($type_var $(: { $($type_constraint),+ })*),+>)* {
1529        STATES [
1530          $(state $state ($($data_name : $data_type $(= $data_default)*),*)
1531          $({
1532            $(entry $entry)*
1533            $(exit  $exit)*
1534          })*)+
1535        ]
1536        EVENTS [
1537          $(event $event <$source> $(=> <$target>)*
1538            ($($param_name : $param_type $(= $param_default)*),*)
1539            $({$($state_data),*} => $action)*
1540          )*
1541        ]
1542        EXTENDED [
1543          $($($ext_name : $ext_type $(= $ext_default)*),*)*
1544        ]
1545        $(self_reference: $self_reference)*
1546        initial_state: $initial $({
1547          $(initial_action: $initial_action)*
1548        })*
1549        $(terminal_state: $terminal $({
1550          $(terminate_success: $terminate_success)*
1551          $(terminate_failure: $terminate_failure)*
1552        })*)*
1553      }
1554    }
1555
1556  };
1557
1558  //
1559  //  @impl_fn_handle_event
1560  //
1561  ( @impl_fn_handle_event
1562    machine $machine:ident {
1563      EVENTS [
1564        $(event $event:ident <$source:tt> $(=> <$target:ident>)*
1565          ($($param_name:ident),*)
1566          $({ $($state_data:ident),* } => $action:block)*
1567        )*
1568      ]
1569      EXTENDED [
1570        $($ext_name:ident : $ext_type:ty $(= $ext_default:expr)*),*
1571      ]
1572      $(self_reference: $self_reference:ident)*
1573    }
1574
1575  ) => {
1576
1577    pub fn handle_event (&mut self, mut _event : Event)
1578      -> Result <(), $crate::HandleEventException>
1579    {
1580      // if only one kind of transition exists the following match expression
1581      // will detect the other branch as "unreachable_code"
1582      #[allow(unreachable_code)]
1583      match _event.transition() {
1584        Transition::Universal (target_id) => {
1585          $crate::log::debug!(
1586            machine=stringify!($machine), state:?=self.state.id,
1587            event:?=_event.id, transition="Universal", target:?=target_id;
1588            "handle state machine event");
1589          self.state_exit();
1590          { // event action
1591            // bring extended state variables into scope
1592            #[allow(unused_variables)]
1593            match &mut self.extended_state {
1594              &mut ExtendedState { $(ref mut $ext_name,)*.. } => {
1595                // map each event to an action
1596                match _event.params {
1597                  $(EventParams::$event { $(mut $param_name,)*.. } => {
1598                    // only expands universal actions, unreachable otherwise
1599                    $crate::def_machine_debug!{
1600                      @event_action_universal
1601                      event $event <$source> $(=> <$target>)* $($action)*
1602                    }
1603                  })*
1604                  _ => unreachable!("unreachable phantom data variant")
1605                }
1606              }
1607            }
1608          }
1609          let state  = target_id.to_state (&mut self.extended_state);
1610          self.state = state;
1611          self.state_entry();
1612          Ok (())
1613        }
1614        Transition::Internal (source_id) => {
1615          if self.state.id == source_id {
1616            $crate::log::debug!(
1617              machine=stringify!($machine), state:?=self.state.id,
1618              event:?=_event.id, transition="Internal", source:?=source_id;
1619              "handle state machine event");
1620            // bring extended state variables into scope
1621            #[allow(unused_variables)]
1622            match &mut self.extended_state {
1623              &mut ExtendedState { $(ref mut $ext_name,)*.. } => {
1624                // map each event to an action
1625                match _event.params {
1626                  $(EventParams::$event { $(mut $param_name,)*.. } => {
1627                    // for universal transitions there is no source state so
1628                    // this produces a wildcard pattern resulting in the
1629                    // last branch being unreachable
1630                    // bring local state variables into scope
1631                    #[allow(unreachable_patterns)]
1632                    match &mut self.state.data {
1633                      $crate::def_machine_debug!{
1634                        @event_internal_state_pattern
1635                        $source { $($($state_data),*)* }
1636                      } => {
1637                        // only expands internal actions, unreachable otherwise
1638                        $crate::def_machine_debug!{
1639                          @event_action_internal
1640                          event $event <$source> $(=> <$target>)* $($action)*
1641                        }
1642                      }
1643                      _ => unreachable!("current state should match event source")
1644                    }
1645                  })*
1646                  _ => unreachable!("unreachable phantom data variant")
1647                }
1648              }
1649            }
1650            Ok (())
1651          } else {
1652            let exception = $crate::HandleEventException::WrongState;
1653            $crate::log::warn!(
1654              machine=stringify!($machine), state:?=self.state.id,
1655              event:?=_event.id, transition="Internal", source:?=source_id,
1656              exception:?;
1657              "handle state machine event exception");
1658            Err (exception)
1659          }
1660        }
1661        Transition::External (source_id, target_id) => {
1662          if self.state.id == source_id {
1663            $crate::log::debug!(
1664              machine=stringify!($machine), state:?=self.state.id,
1665              event:?=_event.id, transition="External", source:?=source_id,
1666              target:?=target_id;
1667              "handle state machine event");
1668            self.state_exit();
1669            { // event action
1670              // bring extended state variables into scope
1671              #[allow(unused_variables)]
1672              match &mut self.extended_state {
1673                &mut ExtendedState { $(ref mut $ext_name,)*.. } => {
1674                  // map each event to an action
1675                  match _event.params {
1676                    $(EventParams::$event { $(mut $param_name,)*.. } => {
1677                      // only expands external actions, unreachable otherwise
1678                      $crate::def_machine_debug!{
1679                        @event_action_external
1680                        event $event <$source> $(=> <$target>)* $($action)*
1681                      }
1682                    })*
1683                    _ => unreachable!("unreachable phantom data variant")
1684                  }
1685                }
1686              }
1687            }
1688            let state  = target_id.to_state (&mut self.extended_state);
1689            self.state = state;
1690            self.state_entry();
1691            Ok (())
1692          } else {
1693            let exception = $crate::HandleEventException::WrongState;
1694            $crate::log::warn!(
1695              machine=stringify!($machine), state:?=self.state.id,
1696              event:?=_event.id, transition="External", source:?=source_id,
1697              target:?=target_id, exception:?;
1698              "handle state machine event exception");
1699            Err ($crate::HandleEventException::WrongState)
1700          }
1701        }
1702      }
1703    } // end handle event
1704
1705  };  // end @impl_fn_handle_event
1706
1707  //
1708  //  @event_internal_state_pattern
1709  //
1710  ( @event_internal_state_pattern
1711    $source:ident { $($state_data:ident),* }
1712  ) => {
1713    &mut StateData::$source {$(ref mut $state_data,)*..}
1714  };
1715
1716  //
1717  //  @event_internal_state_pattern: not an internal event
1718  //
1719  ( @event_internal_state_pattern
1720    * { $($state_data:ident),* }
1721  ) => {
1722    _
1723  };
1724
1725  //
1726  //  @event_action_external
1727  //
1728  ( @event_action_external
1729    event $event:ident <$source:ident> => <$target:ident> $($action:block)*
1730  ) => {
1731    $($action)*
1732  };
1733
1734  //
1735  //  @event_action_external: not an external event
1736  //
1737  ( @event_action_external
1738    event $event:ident <$source:tt> $($action:block)*
1739  ) => { unreachable!("not an external event") };
1740
1741  //
1742  //  @event_action_external: not an external event
1743  //
1744  ( @event_action_external
1745    event $event:ident <*> => <$target:ident> $($action:block)*
1746  ) => { unreachable!("not an external event") };
1747
1748  //
1749  //  @event_action_universal
1750  //
1751  ( @event_action_universal
1752    event $event:ident <*> => <$target:ident> $($action:block)*
1753  ) => {
1754    $($action)*
1755  };
1756
1757  //
1758  //  @event_action_universal: not an universal event
1759  //
1760  ( @event_action_universal
1761    event $event:ident <$source:ident> $(=> <$target:ident>)* $($action:block)*
1762  ) => { unreachable!("not an universal event") };
1763
1764  //
1765  //  @event_action_internal
1766  //
1767  ( @event_action_internal
1768    event $event:ident <$source:ident> $($action:block)*
1769  ) => {
1770    $($action)*
1771  };
1772
1773  //
1774  //  @event_action_internal: not an internal event
1775  //
1776  ( @event_action_internal
1777    event $event:ident <$source:tt> => <$target:ident> $($action:block)*
1778  ) => { unreachable!("not an internal event") };
1779
1780  //
1781  //  @event_transition: external
1782  //
1783  ( @event_transition <$source:ident> => <$target:ident> ) => {
1784    Transition::External (StateId::$source, StateId::$target)
1785  };
1786
1787  //
1788  //  @event_transition: internal
1789  //
1790  ( @event_transition <$source:ident> ) => {
1791    Transition::Internal (StateId::$source)
1792  };
1793
1794  //
1795  //  @event_transition: universal
1796  //
1797  ( @event_transition <*> => <$target:ident> ) => {
1798    Transition::Universal (StateId::$target)
1799  };
1800
1801  //
1802  //  @expr_default: override default
1803  //
1804  ( @expr_default $default:expr ) => { $default };
1805
1806  //
1807  //  @expr_default: use default
1808  //
1809  ( @expr_default ) => { Default::default() };
1810
1811  //
1812  //  @expr_option: Some
1813  //
1814  ( @expr_option $default:expr ) => { Some ($default) };
1815
1816  //
1817  //  @expr_option: None
1818  //
1819  ( @expr_option ) => { None };
1820
1821  //
1822  //  @base implementation rule
1823  //
1824  ( @base
1825    machine $machine:ident
1826      $(<$(
1827        $type_var:ident $(: { $($type_constraint:path),+ })*
1828      ),+>)*
1829    {
1830      STATES [
1831        $(state $state:ident (
1832          $($data_name:ident : $data_type:ty $(= $data_default:expr)*),*
1833        ) $({
1834          $(entry $entry:block)*
1835          $(exit  $exit:block)*
1836        })*)+
1837      ]
1838      EVENTS [
1839        $(event $event:ident <$source:tt> $(=> <$target:ident>)*
1840          ($($param_name:ident : $param_type:ty $(= $param_default:expr)*),*)
1841          $({ $($state_data:ident),* } => $action:block)*
1842        )*
1843      ]
1844      EXTENDED [
1845        $($ext_name:ident : $ext_type:ty $(= $ext_default:expr)*),*
1846      ]
1847      $(self_reference: $self_reference:ident)*
1848      initial_state: $initial:ident $({
1849        $(initial_action: $initial_action:block)*
1850      })*
1851      $(terminal_state: $terminal:ident $({
1852        $(terminate_success: $terminate_success:block)*
1853        $(terminate_failure: $terminate_failure:block)*
1854      })*)*
1855    }
1856
1857  ) => {
1858
1859    #[derive(Debug)]
1860    pub struct $machine $(<$($type_var),+>)* where
1861    $($(
1862      $type_var : std::fmt::Debug,
1863      $($($type_var : $type_constraint),+)*
1864    ),+)*
1865    {
1866      state          : State,
1867      extended_state : ExtendedState $(<$($type_var),+>)*
1868    }
1869
1870    #[derive(Debug)]
1871    pub struct State {
1872      id   : StateId,
1873      data : StateData
1874    }
1875
1876    #[derive(Debug)]
1877    pub struct ExtendedState $(<$($type_var),+>)* where
1878    $($(
1879      $type_var : std::fmt::Debug,
1880      $($($type_var : $type_constraint),+)*
1881    ),+)*
1882    {
1883      $(pub $ext_name : $ext_type),*
1884    }
1885
1886    #[derive(Debug)]
1887    pub struct Event <'event> {
1888      id     : EventId,
1889      params : EventParams <'event>
1890    }
1891
1892    #[derive(Clone, Debug, Eq, PartialEq, $crate::VariantCount)]
1893    pub enum StateId {
1894      $($state),+
1895    }
1896
1897    #[derive(Debug)]
1898    pub enum StateData {
1899      $($state {
1900        $($data_name : $data_type),*
1901      }),+
1902    }
1903
1904    #[derive(Debug, Eq, PartialEq)]
1905    pub enum Transition {
1906      Internal  (StateId),
1907      External  (StateId, StateId),
1908      Universal (StateId)
1909    }
1910
1911    #[derive(Clone, Debug, Eq, PartialEq, $crate::VariantCount)]
1912    pub enum EventId {
1913      $($event),*
1914    }
1915
1916    #[derive(Debug)]
1917    pub enum EventParams <'event> {
1918      $($event {
1919        $($param_name : $param_type),*
1920      },)*
1921      _PhantomData (::std::marker::PhantomData <&'event ()>)
1922    }
1923
1924    impl $(<$($type_var),+>)* $machine $(<$($type_var),+>)* where
1925    $($(
1926      $type_var : std::fmt::Debug,
1927      $($($type_var : $type_constraint),+)*
1928    ),+)*
1929    {
1930      pub fn report_sizes() where $($($type_var : 'static),+)* {
1931        let machine_name = stringify!($machine);
1932        let machine_type = std::any::type_name::<Self>();
1933        println!("{} report sizes...", machine_name);
1934        println!("  size of {}: {}", machine_type, std::mem::size_of::<Self>());
1935        println!("...{} report sizes", machine_name);
1936      }
1937
1938      pub fn new (mut extended_state : ExtendedState $(<$($type_var),+>)*)
1939        -> Self
1940      {
1941        let state   = StateId::$initial.to_state (&mut extended_state);
1942        let mut new = Self { state, extended_state };
1943        {
1944          $(#[allow(unused_variables)]
1945          let $self_reference = &mut new;)*
1946          $($($initial_action)*)*
1947        }
1948        new.state_entry();
1949        new
1950      }
1951
1952      #[allow(dead_code)]
1953      #[inline]
1954      pub fn state (&self) -> &State {
1955        &self.state
1956      }
1957
1958      #[allow(dead_code)]
1959      #[inline]
1960      pub fn state_id (&self) -> StateId {
1961        self.state().id().clone()
1962      }
1963
1964      #[allow(dead_code)]
1965      #[inline]
1966      pub fn state_data (&self) -> &StateData {
1967        self.state().data()
1968      }
1969
1970      #[allow(dead_code)]
1971      #[inline]
1972      pub fn extended_state (&self) -> &ExtendedState $(<$($type_var),+>)* {
1973        &self.extended_state
1974      }
1975
1976      #[allow(dead_code)]
1977      #[inline]
1978      pub fn extended_state_mut (&mut self)
1979        -> &mut ExtendedState $(<$($type_var),+>)*
1980      {
1981        &mut self.extended_state
1982      }
1983
1984      $crate::def_machine_debug!{
1985        @impl_fn_handle_event
1986        machine $machine {
1987          EVENTS [
1988            $(event $event <$source> $(=> <$target>)*
1989              ($($param_name),*)
1990              $({$($state_data),*} => $action)*
1991            )*
1992          ]
1993          EXTENDED [
1994            $($ext_name : $ext_type $(= $ext_default)*),*
1995          ]
1996          $(self_reference: $self_reference)*
1997        }
1998      }
1999
2000      fn state_entry (&mut self) {
2001        // bring extended state variables into scope
2002        #[allow(unused_variables)]
2003        match &mut self.extended_state {
2004          &mut ExtendedState { $(ref mut $ext_name,)*.. } => {
2005            match self.state.data {
2006              // bring local state variables into scope
2007              $(StateData::$state { $(ref mut $data_name,)*.. } => {
2008                $($($entry)*)*
2009              })+
2010            }
2011          }
2012        }
2013      }
2014      fn state_exit (&mut self) {
2015        // bring extended state variables into scope
2016        #[allow(unused_variables)]
2017        match &mut self.extended_state {
2018          &mut ExtendedState { $(ref mut $ext_name,)*.. } => {
2019            match self.state.data {
2020              // bring local state variables into scope
2021              $(StateData::$state { $(ref mut $data_name,)*.. } => {
2022                $($($exit)*)*
2023              })+
2024            }
2025          }
2026        }
2027      }
2028
2029    } // end impl $machine
2030
2031    impl $(<$($type_var),+>)* AsRef <ExtendedState $(<$($type_var),+>)*>
2032      for $machine $(<$($type_var),+>)*
2033    where
2034    $($(
2035      $type_var : std::fmt::Debug,
2036      $($($type_var : $type_constraint),+)*
2037    ),+)*
2038    {
2039      #[inline]
2040      fn as_ref (&self) -> &ExtendedState $(<$($type_var),+>)* {
2041        &self.extended_state
2042      }
2043    }
2044
2045    impl $(<$($type_var),+>)* AsMut <ExtendedState $(<$($type_var),+>)*>
2046      for $machine $(<$($type_var),+>)*
2047    where
2048    $($(
2049      $type_var : std::fmt::Debug,
2050      $($($type_var : $type_constraint),+)*
2051    ),+)*
2052    {
2053      #[inline]
2054      fn as_mut (&mut self) -> &mut ExtendedState $(<$($type_var),+>)* {
2055        &mut self.extended_state
2056      }
2057    }
2058
2059    impl $(<$($type_var),+>)* Drop for $machine $(<$($type_var),+>)* where
2060    $($(
2061      $type_var : std::fmt::Debug,
2062      $($($type_var : $type_constraint),+)*
2063    ),+)*
2064    {
2065      fn drop (&mut self) {
2066        self.state_exit();
2067        let _state_id = self.state.id.clone();
2068        $(#[allow(unused_variables)]
2069        let $self_reference = &mut *self;)*
2070        $(
2071        if _state_id != StateId::$terminal {
2072          $crate::log::warn!(
2073            machine=stringify!($machine), state:?=_state_id,
2074            terminal:?=StateId::$terminal;
2075            "terminate state machine failure: not in terminal state");
2076          $($($terminate_failure)*)*
2077        } else {
2078          $crate::log::debug!(
2079            machine=stringify!($machine), state:?=_state_id;
2080            "terminate state machine success");
2081          $($($terminate_success)*)*
2082        }
2083        )*
2084      }
2085    }
2086
2087    impl State {
2088      #[inline]
2089      pub fn id (&self) -> &StateId {
2090        &self.id
2091      }
2092
2093      #[inline]
2094      pub fn data (&self) -> &StateData {
2095        &self.data
2096      }
2097    }
2098
2099    impl StateId {
2100      #[inline]
2101      pub const fn initial() -> Self {
2102        StateId::$initial
2103      }
2104      $(
2105      #[inline]
2106      pub const fn terminal() -> Self {
2107        StateId::$terminal
2108      }
2109      )*
2110      #[expect(clippy::wrong_self_convention)]
2111      pub fn to_state $(<$($type_var),+>)* (self,
2112        extended_state : &mut ExtendedState$(<$($type_var),+>)*) -> State
2113      where
2114      $($(
2115        $type_var : std::fmt::Debug,
2116        $($($type_var : $type_constraint),+)*
2117      ),+)*
2118      {
2119        // bring extended state variables into scope
2120        #[allow(unused_variables)]
2121        match extended_state {
2122          &mut ExtendedState { $(ref mut $ext_name,)*.. } => {
2123            match self {
2124              $(StateId::$state => {
2125                State {
2126                  id:   self,
2127                  data: StateData::$state {
2128                    $($data_name:
2129                      $crate::def_machine_debug!(@expr_default $($data_default)*)
2130                    ),*
2131                  }
2132                }
2133              })+
2134            }
2135          }
2136        }
2137      }
2138    }
2139
2140    impl EventId {
2141      pub fn transition (&self) -> Transition {
2142        #[allow(clippy::uninhabited_references)]
2143        match *self {
2144          $(
2145          EventId::$event =>
2146            $crate::def_machine_debug!(@event_transition <$source> $(=> <$target>)*)
2147          ),*
2148        }
2149      }
2150    }
2151
2152    impl <'event> EventParams <'event> {
2153      pub fn id (&self) -> EventId {
2154        match *self {
2155          $(EventParams::$event {..} => EventId::$event,)*
2156          _ => unreachable!("unreachable phantom data variant")
2157        }
2158      }
2159    }
2160
2161    impl <'event> Event <'event> {
2162      #[inline]
2163      pub fn transition (&self) -> Transition {
2164        self.id.transition()
2165      }
2166
2167      #[inline]
2168      #[allow(clippy::uninhabited_references)]
2169      pub fn id (&self) -> &EventId {
2170        &self.id
2171      }
2172
2173      #[inline]
2174      #[expect(mismatched_lifetime_syntaxes)]
2175      pub fn params (&self) -> &EventParams {
2176        &self.params
2177      }
2178    }
2179
2180    impl <'event> From <EventParams <'event>> for Event <'event> {
2181      fn from (params : EventParams <'event>) -> Self {
2182        let _id = params.id();
2183        Event { id: _id, params }
2184      }
2185    }
2186
2187  };  // end @base
2188
2189} // end def_machine_debug!
2190
2191/// State machine that requires runtime initialization and deriving `Debug`.
2192#[macro_export]
2193macro_rules! def_machine_nodefault_debug {
2194  //
2195  //  main implementation rule
2196  //
2197  ( machine $machine:ident
2198      $(<$(
2199        $type_var:ident $(: { $($type_constraint:path),+ })*
2200      ),+>)*
2201    {
2202      STATES [
2203        $(state $state:ident (
2204          $($data_name:ident : $data_type:ty $(= $data_default:expr)*),*
2205        ) $({
2206          $(entry $entry:block)*
2207          $(exit  $exit:block)*
2208        })*)+
2209      ]
2210      EVENTS [
2211        $(event $event:ident <$source:tt> $(=> <$target:ident>)*
2212          ($($param_name:ident : $param_type:ty $(=> $param_default:expr)*),*)
2213          $({ $($state_data:ident),* } => $action:block)*
2214        )*
2215      ]
2216      EXTENDED [
2217        $($ext_name:ident : $ext_type:ty $(= $ext_default:expr)*),*
2218      ]
2219      $(self_reference: $self_reference:ident)*
2220      initial_state: $initial:ident $({
2221        $(initial_action: $initial_action:block)*
2222      })*
2223      $(terminal_state: $terminal:ident $({
2224        $(terminate_success: $terminate_success:block)*
2225        $(terminate_failure: $terminate_failure:block)*
2226      })*)*
2227    }
2228
2229  ) => {
2230
2231    $crate::def_machine_debug!{
2232      @base
2233      machine $machine
2234        $(<$($type_var $(: { $($type_constraint),+ })*),+>)*
2235      {
2236        STATES [
2237          $(state $state ($($data_name : $data_type $(= $data_default)*),*)
2238          $({
2239            $(entry $entry)*
2240            $(exit  $exit)*
2241          })*)+
2242        ]
2243        EVENTS [
2244          $(event $event <$source> $(=> <$target>)*
2245            ($($param_name : $param_type $(=> $param_default)*),*)
2246            $({$($state_data),*} => $action)*
2247          )*
2248        ]
2249        EXTENDED [
2250          $($ext_name : $ext_type $(= $ext_default)*),*
2251        ]
2252        $(self_reference: $self_reference)*
2253        initial_state: $initial $({
2254          $(initial_action: $initial_action)*
2255        })*
2256        $(terminal_state: $terminal $({
2257          $(terminate_success: $terminate_success)*
2258          $(terminate_failure: $terminate_failure)*
2259        })*)*
2260      }
2261    }
2262
2263    impl $(<$($type_var),+>)* $crate::MachineDotfile
2264      for $machine $(<$($type_var),+>)*
2265    where
2266    $($(
2267      $type_var : std::fmt::Debug,
2268      $($($type_var : $type_constraint),+)*
2269    ),+)*
2270    {
2271      fn name() -> &'static str {
2272        stringify!($machine)
2273      }
2274      fn type_vars() -> Vec <String> {
2275        let mut _v = Vec::new();
2276        $($(
2277        _v.push (format!(
2278          "{} = {}", stringify!($type_var), std::any::type_name::<$type_var>()));
2279        )+)*
2280        _v
2281      }
2282      fn extended_state_names() -> Vec <&'static str> {
2283        vec![$(stringify!($ext_name)),*]
2284      }
2285      fn extended_state_types() -> Vec <&'static str> {
2286        vec![$(stringify!($ext_type)),*]
2287      }
2288      fn extended_state_defaults() -> Vec <&'static str> {
2289        vec![$(stringify!($($ext_default)*)),*]
2290      }
2291      fn self_reference() -> &'static str {
2292        stringify!($($self_reference)*)
2293      }
2294      fn states() -> Vec <&'static str> {
2295        vec![$(stringify!($state)),+]
2296      }
2297      fn state_initial() -> &'static str {
2298        stringify!($initial)
2299      }
2300      fn state_terminal() -> &'static str {
2301        stringify!($($terminal)*)
2302      }
2303      fn state_data_names() -> Vec <Vec <&'static str>> {
2304        let mut v = Vec::new();
2305        $({
2306          let mut _w = Vec::new();
2307          $(_w.push (stringify!($data_name));)*
2308          v.push (_w);
2309        })+
2310        v
2311      }
2312      fn state_data_types() -> Vec <Vec <&'static str>> {
2313        let mut v = Vec::new();
2314        $({
2315          let mut _w = Vec::new();
2316          $(_w.push (stringify!($data_type));)*
2317          v.push (_w);
2318        })+
2319        v
2320      }
2321      fn state_data_defaults() -> Vec <Vec <&'static str>> {
2322        let mut v = Vec::new();
2323        $({
2324          let mut _w = Vec::new();
2325          $(_w.push (stringify!($($data_default)*));)*
2326          v.push (_w);
2327        })+
2328        v
2329      }
2330      /// This version does not evaluate expressions, only pretty prints them
2331      fn state_data_pretty_defaults() -> Vec <Vec <String>> {
2332        let mut v = Vec::new();
2333        $({
2334          let mut _w = Vec::new();
2335          $(
2336          _w.push (format!("{:#?}", stringify!($($data_default)*)));
2337          )*
2338          v.push (_w);
2339        })+
2340        v
2341      }
2342
2343      fn events() -> Vec <&'static str> {
2344        vec![$(stringify!($event)),*]
2345      }
2346      fn event_sources() -> Vec <&'static str> {
2347        vec![$(stringify!($source)),*]
2348      }
2349      fn event_targets() -> Vec <&'static str> {
2350        vec![$(stringify!($($target)*)),*]
2351      }
2352      fn event_actions() -> Vec <&'static str> {
2353        vec![$(stringify!($($action)*)),*]
2354      }
2355    }
2356
2357    impl $(<$($type_var),+>)* ExtendedState $(<$($type_var),+>)* where
2358    $($(
2359      $type_var : std::fmt::Debug,
2360      $($($type_var : $type_constraint),+)*
2361    ),+)*
2362    {
2363      /// Creation method that allows overriding defaults. If a field does not
2364      /// have a default specified it is a required argument.
2365      // TODO: indicate which arguments are missing in case of failure
2366      // TODO: make required arguments non-Option types?
2367      pub fn new ($($ext_name : Option <$ext_type>),*) -> Option <Self> {
2368        Some (Self {
2369          $($ext_name: {
2370            if let Some ($ext_name) = $ext_name {
2371              $ext_name
2372            } else {
2373              $crate::def_machine_debug!(@expr_option $($ext_default)*)?
2374            }
2375          }),*
2376        })
2377      }
2378    }
2379
2380  };
2381
2382  //
2383  //  alternate syntax
2384  //
2385  ( $machine:ident
2386    $(<$(
2387      $type_var:ident $(: { $($type_constraint:path),+ })*
2388    ),+>)*
2389    $(($(
2390      $ext_name:ident : $ext_type:ty $(= $ext_default:expr)*
2391    ),*))*
2392    $(@ $self_reference:ident)*
2393    {
2394      STATES [
2395        $(state $state:ident (
2396          $($data_name:ident : $data_type:ty $(= $data_default:expr)*),*
2397        ) $({
2398          $(entry $entry:block)*
2399          $(exit  $exit:block)*
2400        })*)+
2401      ]
2402      EVENTS [
2403        $(event $event:ident <$source:tt> $(=> <$target:ident>)*
2404          ($($param_name:ident : $param_type:ty $(= $param_default:expr)*),*)
2405          $({ $($state_data:ident),* } => $action:block)*
2406        )*
2407      ]
2408      initial_state: $initial:ident $({
2409        $(initial_action: $initial_action:block)*
2410      })*
2411      $(terminal_state: $terminal:ident $({
2412        $(terminate_success: $terminate_success:block)*
2413        $(terminate_failure: $terminate_failure:block)*
2414      })*)*
2415    }
2416
2417  ) => {
2418
2419    $crate::def_machine_nodefault_debug!{
2420      machine $machine $(<$($type_var $(: { $($type_constraint),+ })*),+>)* {
2421        STATES [
2422          $(state $state ($($data_name : $data_type $(= $data_default)*),*)
2423          $({
2424            $(entry $entry)*
2425            $(exit  $exit)*
2426          })*)+
2427        ]
2428        EVENTS [
2429          $(event $event <$source> $(=> <$target>)*
2430            ($($param_name : $param_type $(= $param_default)*),*)
2431            $({$($state_data),*} => $action)*
2432          )*
2433        ]
2434        EXTENDED [
2435          $($($ext_name : $ext_type $(= $ext_default)*),*)*
2436        ]
2437        $(self_reference: $self_reference)*
2438        initial_state: $initial $({
2439          $(initial_action: $initial_action)*
2440        })*
2441        $(terminal_state: $terminal $({
2442          $(terminate_success: $terminate_success)*
2443          $(terminate_failure: $terminate_failure)*
2444        })*)*
2445      }
2446    }
2447
2448  };
2449
2450} // end def_machine_nodefault_debug!