Module description

fsm -- Finite State Machine
The fsm module implements a Finite State Machine. Use fsm-new-state to add states to the machine. Then use fsm-new-transition to add transitions between the states. fsm-new-transition returns the new transition. Use ftr-condition@ on this new transition to get a reference to the condition in the transition. This is actually a bit array, see bar. Use the words of the bar module to set the condition. When the whole FSM is built, start using the machine by calling fsm-start. By default the first created state is the start state, but this can be changed by fsm-start! After starting the machine, feed events to the machine by fsm-feed. This word returns the new, current state or nil if no transition matched. The machine can be converted to graphviz's dot files by fsm-to-dot. This word uses the labels of the states and transitions to build the dot representation. It also set the shape of the states &lb;double circle for start and end states, circles for the others&rb;. Use fst-attributes! and ftr-attributes! to set additional graphviz attributes. During the feeding of events, the optional actions are called. When a state is left, the exit action is called, when a state is entered the entry state is called. If a transition matched, the action of this transition is also called. The stack usage for those actions:
 
state entry action:  fst -- = State fst is entered                         
state exit action:   fst -- = State fst is left                            
transition action: n ftr -- = Transition fst matched for event n           

fsm structure

fsm% ( -- n )
Get the required space for a fsm variable

FSM creation, initialisation and destruction

fsm-init ( +n fsm -- )
Initialise the fsm with the number of events n
fsm-(free) ( fsm -- )
Free the internal, private variables from the heap
fsm-create ( "<spaces>name" +n -- ; -- fsm )
Create a named fsm in the dictionary with the number of events n
fsm-new ( +n -- fsm )
Create a new fsm on the heap with the number of events n
fsm-free ( fsm -- )
Free the fsm from the heap

Member words

fsm-start@ ( fsm -- fst )
Get the start state
fsm-start! ( fst fsm -- )
Set the start state

State words

fsm-new-state ( x xt1 xt2 c-addr1 u1 fsm -- fst )
Add a new state with label c-addr1 u1, entry action xt1, exit action xt2 and data x
fsm-start ( fsm -- )
Start the finite state machine
fsm-find-state ( c-addr u fsm -- fst | nil )
Find the state by its label c-addr u in the fsm

Transition words

fsm-new-transition ( x xt c-addr1 u1 fst1 fst2 fsm -- ftr )
Add a new transition from state fst1 to state fst2 with label c-addr1 u1, action xt and data x
fsm-any-transition ( x xt c-addr1 u1 fst1 fst2 fsm -- ftr )
Set the any transition for state fst1 to state fst2 with label c-addr1 u1, action xt and data x

Event words

fsm-feed ( n fsm -- fst | nil )
Feed the event to the current state, return the next state or nil if the event did not match any condition
fsm-try ( n fsm -- fst | nil )
Try the event for the current event, return the next state, but do not move to this state

Conversion words

fsm-to-dot ( c-addr u tos fsm -- )
Convert the fsm to a dot string using the stream, giving the graph the name c-addr u

Inspection

fsm-dump ( fsm -- )
Dump the fsm variable

Examples

\ ==============================================================================
\
\        fsm_test - the test words for the fsm module in the ffl
\
\               Copyright (C) 2008  Dick van Oudheusden
\  
\ This library is free software; you can redistribute it and/or
\ modify it under the terms of the GNU General Public
\ License as published by the Free Software Foundation; either
\ version 2 of the License, or (at your option) any later version.
\
\ This library is distributed in the hope that it will be useful,
\ but WITHOUT ANY WARRANTY; without even the implied warranty of
\ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
\ General Public License for more details.
\
\ You should have received a copy of the GNU General Public
\ License along with this library; if not, write to the Free
\ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
\
\ ==============================================================================
\ 
\  $Date: 2008-03-24 20:48:38 $ $Revision: 1.1 $
\
\ ==============================================================================

include ffl/fsm.fs
include ffl/enm.fs


\ Example: vending machine


\ Enumerate the events

begin-enumeration
enum: voilence
enum: coin
enum: choice
enum: refuse
enum: #events
end-enumeration


\ Create the finite state machine on the heap with #events events

#events fsm-new value machine


\ Create the entry and exit action words

: say-thank-you  ( fst -- = Say 'thank you' after a coin or choice )
  drop
  ." Thank you" cr
;

: say-choice?    ( fst -- = Ask for choice after the coin )
  drop
  ." Please make your choice" cr
;

: say-coin?      ( fst -- = Ask for coin after the choice )
  drop
  ." Please enter your coin" cr
;

: call-support   ( fst -- = Call support after voilence, states data contains the phone number )
  ." Voilence against the machine, calling: " fst-data@ . cr
;


\ Create the states in the state machine

0     nil            ' say-thank-you s" start"    machine fsm-new-state value start
0   ' say-choice?    ' say-thank-you s" choice?"  machine fsm-new-state value choice?
0   ' say-coin?      ' say-thank-you s" coin?"    machine fsm-new-state value coin?
112 ' call-support     nil           s" support"  machine fsm-new-state value support


\ Set extra dot attributes for the support state

s" color=red" support fst-attributes!


\ Create the transitions for state start, use the bit array to set the condition

0     nil             s" coin"      start choice? machine fsm-new-transition ftr-condition@ coin     swap bar-set-bit
0     nil             s" choice"    start coin?   machine fsm-new-transition ftr-condition@ choice   swap bar-set-bit
0     nil             s" voilence"  start support machine fsm-new-transition ftr-condition@ voilence swap bar-set-bit

s" voilence" start fst-find-transition s" color=yellow" rot ftr-attributes!


\ Create the transition actions for choice? and coin? states

: deliver-choice   ( n ftr -- = Deliver the choosen product )
  2drop
  ." Deliver choice" cr
;

: do-refund        ( n ftr -- = Refused the product, refund the coin )
  2drop
  ." Refund coin" cr
;


\ Create the transitions for state choice?

0   ' deliver-choice  s" choice"    choice? start   machine fsm-new-transition ftr-condition@ choice   swap bar-set-bit
0   ' do-refund       s" refuse"    choice? start   machine fsm-new-transition ftr-condition@ refuse   swap bar-set-bit
0     nil             s" voilence"  choice? support machine fsm-new-transition ftr-condition@ voilence swap bar-set-bit


\ Set extra dot attributes for the voilence transition

s" voilence" choice? fst-find-transition s" color=yellow" rot ftr-attributes!


\ Create the transitions for state coin?

0   ' deliver-choice  s" coin"      coin? start   machine fsm-new-transition ftr-condition@ coin     swap bar-set-bit
0     nil             s" refuse"    coin? start   machine fsm-new-transition ftr-condition@ refuse   swap bar-set-bit
0     nil             s" voilence"  coin? support machine fsm-new-transition ftr-condition@ voilence swap bar-set-bit

s" voilence" coin? fst-find-transition s" color=yellow" rot ftr-attributes!


\ Start the state machine and feed it events 

machine fsm-start

coin     machine fsm-feed drop
choice   machine fsm-feed drop
coin     machine fsm-feed drop
refuse   machine fsm-feed drop
choice   machine fsm-feed drop
coin     machine fsm-feed drop
voilence machine fsm-feed drop


\ Create a text output stream for writing the state machine to dot

tos-new value dot-tos


\ Create the writer word

: write-dot    ( c-addr u file-id -- flag = Write the string )
  write-line 
  0=
;


\ Create the output file

s" out.dot" w/o create-file throw value dot-file


\ Set the writer word and the file in the stream

dot-file  ' write-dot  dot-tos  tos-set-writer


\ Write the state machine to the dot-file with graph name "Machine"

s" Machine" dot-tos machine fsm-to-dot


\ Free the dot stream

dot-tos tos-free


\ Close the dot file

dot-file close-file throw


\ To generate an image, use for example: dot -Tpng -o fsm.png out.dot

\ ==============================================================================

Generated by fsdocgen 0.1.0