#state-machine

macro-machines

State machine macros with logging and graphviz DOT file generation

19 releases

0.10.6 Aug 25, 2024
0.10.3 Nov 26, 2023
0.10.2 Mar 22, 2022
0.10.1 Jul 14, 2020
0.8.4 May 18, 2018

#898 in Algorithms


Used in apis

MPL-2.0 license

105KB
2.5K SLoC

macro-machines

State machine macros with logging and graphviz dotfile generation

Documentation

Current features

  • Macros for creating state machines with and without Debug and Default:
    • def_machine! -- state machine implementing Default construction
    • def_machine_debug! -- state machine implementing Default construction and deriving Debug
    • def_machine_nodefault! -- state machine requiring initialization arguments
    • def_machine_nodefault_debug! -- state machine requiring initialization arguments and deriving Debug
  • Specified initial (required) and terminal (optional) states with (optional) initialization and termination actions
  • States may have local state variables and state machines may have extended state variables
  • Events with optional associated parameters and actions in which extended state variables may be modified:
    • External events -- transition from a specific source state to a specific target state
    • Internal events -- an event that is additionally allowed to modify local state variables and leaves the current state unchanged
    • Universal events -- transition from any source state to a specific target state
  • Syntax allowing use of constrained type parameters in the types of extended state variables
  • Logging using the log logging API
  • Graphviz DOT file generation of state machine transition diagrams

Usage

Define and use a minimal state machine:

use macro_machines::def_machine_debug;
def_machine_debug!{
  machine M {
    STATES [
      state S ()
      state T ()
    ]
    EVENTS [
      event A <S> => <T> ()
    ]
    EXTENDED []
    initial_state: S
  }
}

fn main () {
  use macro_machines::HandleEventException;

  let mut m = M::initial();
  m.handle_event (EventId::A.into()).unwrap();
  assert_eq!(m.handle_event (EventId::A.into()), Err (HandleEventException::WrongState));
}

Generate a dotfile and write to file:

  use std::io::Write;
  use macro_machines::MachineDotfile;
  let mut f = std::fs::File::create ("minimal.dot").unwrap();
  f.write_all (M::dotfile().as_bytes()).unwrap();
  drop (f);

Rendered as PNG with $ dot -Tpng minimal.dot > minimal.png:

For examples of more complex state machines, see the ./examples/ directory.

Dependencies

Dependencies

~2MB
~40K SLoC