Name
    FSA::Rules - Build simple rules-based state machines in Perl

Synopsis
      my $fsa = FSA::Rules->new(
         ping => {
             do => sub {
                 print "ping!\n";
                 my $state = shift;
                 $state->result('pong');
                 $state->machine->{count}++;
             },
             rules => [
                 game_over => sub { shift->machine->{count} >= 20 },
                 pong      => sub { shift->result eq 'pong' },
             ],
         },

         pong => {
             do => sub { print "pong!\n" },
             rules => [ ping => 1, ], # always goes back to ping
         },
         game_over => { do => sub { print "Game Over\n" } }
      );

      $fsa->start;
      $fsa->switch until $fsa->at('game_over');

Description
    This class implements a simple state machine pattern, allowing you to
    quickly build rules-based state machines in Perl. As a simple
    implementation of a powerful concept, it differs slightly from an ideal
    DFA model in that it does not enforce a single possible switch from one
    state to another. Rather, it short circuits the evaluation of the rules
    for such switches, so that the first rule to return a true value will
    trigger its switch and no other switch rules will be checked. (But see
    the `strict' attribute and parameter to `new()'.) It differs from an NFA
    model in that it offers no back-tracking. But in truth, you can use it
    to build a state machine that adheres to either model--hence the more
    generic FSA moniker.

    FSA::Rules uses named states so that it's easy to tell what state you're
    in and what state you want to go to. Each state may optionally define
    actions that are triggered upon entering the state, after entering the
    state, and upon exiting the state. They may also define rules for
    switching to other states, and these rules may specify the execution of
    switch-specific actions. All actions are defined in terms of anonymous
    subroutines that should expect an FSA::State object itself to be passed
    as the sole argument.

    FSA::Rules objects and the FSA::State objects that make them up are all
    implemented as empty hash references. This design allows the action
    subroutines to use the FSA::State object passed as the sole argument, as
    well as the FSA::Rules object available via its `machine()' method, to
    stash data for other states to access, without the possibility of
    interfering with the state or the state machine itself.

  Serialization

    As of version 0.24, FSA::Rules supports serialization by Storable 2.05
    and later. In other words, FSA::Rules can function as a persistent state
    machine.

    However, FSA::Rules stores data outside of FSA::Rules objects, in
    private data structures inside the FSA::Rules module itself. Therefore,
    unless you want to clone your FSA::Rules object, you must let it fall
    out of scope after you serialize it, so that its data will be cleared
    from memory. Otherwise, if you freeze and thaw an FSA::Rules object in a
    single process without `undef'ing the original, there will be *two*
    copies of the object stored by FSA::Rules.

    So how does it work? Because the rules are defined as code references,
    you must use Storable 2.05 or later and set its `$Deparse' and `$Eval'
    variables to true values:

      use Storable qw(freeze thaw);

      local $Storable::Deparse = 1;
      local $Storable::Eval    = 1;

      my $frozen = freeze($fsa);
      $fsa = thaw($frozen);

    The only caveat is that, while Storable can serialize code references,
    it doesn't properly reference closure variables. So if your rules code
    references are closures, you'll have to serialize the data that they
    refer to yourself.

Class Interface
  Constructor

