Acme-FSM

 view release on metacpan or  search on metacpan

lib/FSM.pm  view on Meta::CPAN

Except when in special I<{state}> (see below) it's supplied with one argument:
I<$item>.
In special states I<$item> is missing.
B<switch()> returns two controls:  I<$rule> and processed I<$item>.
What to do with returned I<$item> is determined by I<$action> (see below).

=item various I<[turn]>s

Each I<[turn]> spec is an ARRAY with two elements (trailing elements are
ignored).
First element is I<$state> to change to.
Second is I<$action> that sets what to do with I<$item> upon changing to named
I<$state>.
Here are known I<[turn]>s in order of logical treating decreasing.

=over

=item C<eturn>

That I<[turn]> will be choosen by FSM itself when I<$item> at hands is
C<undef>
(as returned by B<source()>).
I<switch()> isn't invoked -- I<$item> is void, there's nothing to call
I<switch()> with.
However, I<$action> may change I<$item>.

=item C<uturn>

That I<[turn]> will be choosen by FSM if I<$rule> is C<undef>
(as returned by B<switch()>).
Idea behind this is to give an FST an option to bailout.
In original B<DMA::FSM> that's not possible (except B<croak>ing, you know).
Also, see L<B<BUGS AND CAVEATS>|/Perl FALSE, undef, and uturn>.

=item C<tturn> and/or C<fturn>

lib/FSM.pm  view on Meta::CPAN

I<$state> is treated as a key in FST hash, except when that's a special state.
Special states (in alphabetical order):

=over

=item C<BREAK>

Basically, it's just like C<STOP> I<$state>.
All comments there (see below) apply.
It's added to enable break out from loop, do something, then get back in loop.
I<$state> is changed to C<CONTINUE> just before returning to caller
(I<switch()> is called in C<BREAK> state).
The choice where to implicitly change state to C<CONTINUE> has been completely
arbitrary;
probably wrong.

=item C<CONTINUE>

Just like C<START> state (see below, all comments apply).
While C<BREAK> is turned to C<CONTINUE> implicitly no other handling is made.

=item C<START>

lib/FSM.pm  view on Meta::CPAN


=item anything else

No arguments or more then two is an non-fatal error.
Returns C<undef> (with B<carp>).

=back

=cut

# TODO:202202172011:whynot: As soon as supported perl is young enough change it to smartmatch, plz.
my %special_turns = map { $_ => 1 } qw| eturn uturn tturn fturn |;
# TODO:202202162030:whynot: Consider more elaborate (informative) returns.
sub turn {
    my $self = shift @_;
    unless( @_                                       ) {
        $self->carp( q|no args| );         return undef }
    elsif( 1 == @_ && !exists $self->{_}{fst}{$_[0]} ) {
        $self->carp( qq|($_[0]): no such {fst} record| );
                                           return undef }
    elsif( 1 == @_                                   ) {

lib/FSM.pm  view on Meta::CPAN

    return $item, $self->query_dumper( $item ) }

=item B<query_dumper()>

    $dump = $self->query_dumper( $item );

Seeks I<dumper> callback (L<configured at construction time|/dumper>).
If the callback wasn't configured uses simple hopefully informative and
C<undef> proof substitution.
Whatever the callback returns is checked to be B<defined>
(C<undef> is changed to C<"(unclear)">)
and then returned.

=cut

sub query_dumper                             {
    my $self = shift @_;
    return $self->verify(
      $self->query(
# TODO:202202210258:whynot: This is inefficient, defaulting should happen in B<connect()> instead.
        $self->{_}{dumper} // sub { sprintf q|(%s)|, $_[1] // q|undef| },

lib/FSM.pm  view on Meta::CPAN


=cut

=head1 DIAGNOSTICS

=over

=item C<[action]: changing action: (%s) (%s)>

B<(deep trace)>, L<B<action()> method|/action()>.
Exposes change of I<$action> from previous (former I<%s>)
to current (latter I<%s>).

=item C<[action]: too many args (%i)>

B<(warning)>, L<B<action()> method|/action()>.
Obvious.
None or one argument is supposed.

=item C<[connect]: (%s): unknow option, ignored>

lib/FSM.pm  view on Meta::CPAN

Named record (I<%s>) has been updated.

=item C<[fst]: updating {%s}{%s} entry>

B<(basic trace)>, L<B<fst()> method|/fst()>.
Named entry (I<%s>, the latter) in record I<%s> (the former) has been updated.

=item C<[process]: {%s}(%s): changing state: (CONTINUE)>

B<(basic trace)>, L<B<process()> method|/process()>.
Implicit change of state from C<BREAK> to C<CONTINUE> is about to happen.

=item C<[process]: {%s}(%s): entering>

B<(basic trace)>, L<B<process()> method|/process()>.
Entering state flow from I<$state> I<%s> (the former) with I<$action> I<%s>
(the latter).

=item C<[process]: {%s}(%s): going for>

B<(deep trace)>, L<B<process()> method|/process()>.

lib/FSM.pm  view on Meta::CPAN

=item C<< [query]: [query_source]: object of <%s> can't [%s] method >>

=item C<< [query]: [query_switch]: object of <%s> can't [%s] method >>

B<(croak)>, L<B<query()> method|/query()>.
The object of I<%s> (the former) class can't do I<%s> (the latter) method.

=item C<[state]: changing state: (%s) (%s)>

B<(deep trace)>, L<B<state()> method|/state()>.
Exposes change of state from previous (former I<%s>)
to current (latter I<%s>).

=item C<[state]: too many args (%i)>

B<(warning)>, L<B<state()> method|/state()>.
Obvious.
None or one argument is supposed.
B<state()> has returned C<undef> in this case,
most probably will bring havoc in a moment.

t/base/query_switch.t  view on Meta::CPAN

 [                      q|{switch} isa (CODE), {namespace} isa set|,
  [qw|                                                pass noise |],
  sub {                push_push( !0 ), { namespace => q|vesta| } },
  [                                                               ],
  sub {                       $bb->{RCS}, exists $bb->{CSSC}, $rc },
  [                                         q|dcvs|, '', q|tturn| ],
  { noted => qr.(?m)\Q[query_switch]: {START}{switch} isa (CODE). }   ],
 [    q|{switch} isa (CODE), {namespace} isa set, argument isa set|,
  [qw|                                                pass noise |],
  sub {                          undef, { namespace => q|vesta| } },
  [qw|                          allfusion_harvest_change_manager |],
  sub {                                @$bb{qw| RCS CSSC |}, @$rc },
  [qw|        so6 allfusion_harvest_change_manager tturn fastcst |],
  { noted => qr.(?m)\Q[query_switch]: {START}{switch} isa (CODE). }   ],
 [                 q|{switch} isa (), {namespace} !isa defined|,
  [qw|                                            fail noise |],
  sub {                                    q|snapshotcm|, { } },
  [                                                           ],
                                qr.\Q {namespace} !isa defined.,
  { noted => qr.(?m)\Q[query_switch]: {START}{switch} isa (). },      ],
 [    q|{switch} !isa defined method, {namespace} eq ()|,
  [qw|                               fail noise noise |],
  sub                                                 {



( run in 0.292 second using v1.01-cache-2.11-cpan-5dc5da66d9d )