Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/sysread/auto-mata

An easy to use finite state machine for Perl
https://github.com/sysread/auto-mata

Last synced: about 1 month ago
JSON representation

An easy to use finite state machine for Perl

Awesome Lists containing this project

README

        

=pod

=encoding UTF-8

=head1 NAME

Auto::Mata - A simple, reliable finite state machine

=head1 VERSION

version 0.09

=head1 SYNOPSIS

use strict;
use warnings;
use Auto::Mata;
use Types::Standard -types;

my $NoData = Undef,
my $HasFirst = Tuple[Str];
my $HasLast = Tuple[Str, Str];
my $Complete = Tuple[Str, Str, Int];

sub get_input {
my $query = shift;
print "\n$query ";
my $input = ;
chomp $input;
return $input;
}

my $fsm = machine {
ready 'READY';
term 'TERM';

transition 'READY', to 'FIRST',
on $NoData,
with { return [get_input("What is your first name? ")] };

transition 'FIRST', to 'LAST',
on $HasFirst,
with { return [@$_, get_input("What is your last name? ")] };

transition 'LAST', to 'AGE',
on $HasLast,
with { return [@$_, get_input("What is your age? ")] };

transition 'AGE', to 'TERM',
on $Complete;
};

my $prog = $fsm->();
my $data = $prog->();

printf "Hello %s %s, aged %d years!\n", @$data;

=head1 DESCRIPTION

Finite state machines (or automata) are a technique for modeling the workflow
of a program as a series of dependent, programmable steps. State machines are
useful tools for building software whose behavior can be predicted with a high
degree of confidence.

Using a state machine to implement a program helps to ensure determinacy, where
the program state is known at all times. Designing software this way leads to
greater accuracy and testability.

=head1 WHAT IS A STATE MACHINE

A program can be described as a set of discrete I. Each state is
defined by the existence or value of a variable, the presence of a file, etc.
A state machine replaces the if/else clauses typically used to inspect and
branch based on run-time conditions.

Rather than performing ad hoc tests using if/else conditions, the program is
instead described as a set of I which move the program from an
initial state to a final state. The state machine begins in the "ready" state.
The initial state is described using an identifier and a type constraint (see
L and L). When input matches the transition's
initial state, the transition step is executed, after which the new initial
state is the final state described in the transition. This proceeds until the
"terminal" state is reached.

=head1 EXPORTED SUBROUTINES

C is an C. All subroutines are exported by default.

=head2 machine

Creates a lexical context in which a state machine is defined. Returns a
function that creates new instances of the defined automata.

The automata instance is itself a builder function. When called, it returns a
new function that accepts the initial program state as input and returns the
final state.

This instance function's input value in conjunction with the current state
label is matched (see L) against the transition table (defined with
L) to determine the next state.

Once a match has been made, the action defined for the transition (using
L) will be executed. During evaluation of the L function, C<$_>
is a reference to the input value.

Note that the input state is modified in place during the transition.

# Define the state machine
my $builder = machine { ... };

# Create an instance
my $instance = $builder->();

# Run the program to get the result
my $result = $instance->($state_data);

If the builder function is called with a true value as the first argument, it
will instead build an interactive iterator that performs a single transition
per call. It accepts a single value as input representing the program's current
state.

The return value is new state's label in scalar context, the label and state in
list context, and C after the terminal state has been reached.

# Define the state machine
my $builder = machine { ... };

# Create an instance of the machine
my $program = $builder->();

# Run the program
my $state = [];
while (my ($token, $data) = $program->($state)) {
print "Current state is $token\n"; # $token == label of current state (e.g. READY)
print "State data: @$data\n"; # $data == $state input to $program
}

=head2 ready

Sets the name given to the "ready" state. This is the initial state held by the
state machine.

=head2 terminal

Sets the name given to the "terminal" state. This is the final state held by
the state machine. Once in this state, the machine will cease to perform any
more work.

=head2 term

Alias for L.

=head2 transition

Defines a transition between two states by matching the symbol identifying the
state at the end of the most recent transition and the input passed into the
transition engine (see L) for the transition being performed.

The first argument to C is the symbol identifying the state at the
outset of the transition. A L constraint is used to identify the
expected input using L. When both of these match the current program
state, the return value of L replaces the current input in place.
L is permitted to the current input. If L is not specified, the
input remains unchanged. Once the transition is complete, the symbol supplied
by L will identify the current program state.

The first transition is always from the "ready" state. The final transition is
always to the "terminal" state. There may be no transitions from the "terminal"
state.

The following functions are used in concert with L.

=over

=item to

A name identifying the state held I the transition.

=item on

A L constraint that matches the state immediately I the
transition.

=item with

A code block whose return value is the mutable state used to determine the next
transition to perform. Within the code block C<$_> is a reference to the
program state.

=item using

Alias for L that may be used to avoid conflicts with other packages
exporting C. Prevent the export of C in the typical way (see
L).

use Auto::Mata '!with';

machine {
...

transition 'INITIAL_STATE', to 'THE_NEXT_STATE',
on Dict[command => Str, remember => Bool],
with {
if ($_->{command} eq 'fnord') {
return {command => undef, remember => 0};
}
else {
return {command => undef, remember => 1};
}
};
};

=back

=head1 DEBUGGING

If C<$ENV{DEBUG_AUTOMATA}> is true, helpful debugging messages will be emitted
to C.

=head1 AUTHOR

Jeff Ober

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2017 by Jeff Ober.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=cut