Using the State Machine Compiler with Python

Today I learned about a state machine compiler and code generator. It provides a small DSL that you can use to describe a state machine and the transitions between the states, which will be compiled to create a number of classes, and then all you have to do is provide the code for the actions. Here, actions, states, and transitions are defined terms that are described in the documentation for the smc tool.

All you need to do is download the source code from SourceForge here. The jar file you’re looking for is located in smc/bin/Smc.jar. I’ll walk through the example in the SMC documentation. Copy the following snippet and save it as Turnstile.sm

%class Turnstile
%package turnstile
%start MainMap::Locked
%map MainMap
%%
Locked
{
 coin Unlocked { unlock(); }
 passs nil { alarm(); }
}
Unlocked
{
 passs Locked { lock(); }
 coin nil { thankyou(); }
}
%%

Great. Now compile that state machine script as:

java -jar Smc.jar -python Turnstile.sm

This should produce a Turnstile_sm.py in your working directory.

VERY IMPORTANT: Put smc/lib/Python/statemap.py in your PYTHONPATH or your working directory, you’ll need to import it in the next snippet.

import Turnstile_sm

class Turnstile:
    def __init__(self):
        self._fsm = Turnstile_sm.Turnstile_sm(self)
    def alarm(self):
        print("Alarming!")
    def thankyou(self):
        print("Thanks!")
    def lock(self):
        print("Locked!")
    def unlock(self):
        print("Unlocked!")

if __name__ == '__main__':
    ts = Turnstile()
    ts._fsm.coin()
    ts._fsm.passs()

Why does “pass” have an extra “s”? Because pass is reserved in Python, and I couldn’t think of a better variable name. So this doesn’t do much besides print stuff out when different actions are triggered by changes in state, but it’s still pretty cool. For more motivation for state machines, read this Robert Martin article.

Leave a Reply

Your email address will not be published. Required fields are marked *