Skip to content

Instantly share code, notes, and snippets.

@timm
Created April 24, 2012 12:48
Show Gist options
  • Save timm/2479367 to your computer and use it in GitHub Desktop.
Save timm/2479367 to your computer and use it in GitHub Desktop.
ACTORY: a python-based domain-specific language (DSL) for finite-state-machines (FSM)
"""
Actory: a Python-based domain-specific language (DSL) for
specifying finite state machines (FSM).
In these machines, actions change state.
Copyright 2012, Tim Menzies,
Creative Commons Attribution 3.0 Unported License.
Share and enjoy.
:-)
"""
from pprint import pprint
import random
def val(x) :
def functionp(x) : return type(x).__name__ == 'function'
return x() if functionp(x) else x
def cycle(l,lives=10):
while True:
random.shuffle(l)
for i in l:
yield i
lives -= 1
if lives == 0:
break
def egs(*lst):
for i in lst:
print '\n----|',i.func_name,'|','-'*40,'\n'
i()
class World(object):
w=0
def __init__(self):
self.steps=0
World.w = self.id = 1+World.w
class Game(World):
def __init__self(self):
super(Game,self).__init__()
self.bored=False
class Act(object):
def __init__(self,here,there,tag,gaurd=True) :
self.there = there
self.here = here
self.tag = tag
self.gaurd = gaurd
def ready(self) :
return val(self.gaurd)
def __repr__(self):
return (str(self.here) + ' to ' +
str(self.there) + ' [' +
str(self.tag) + ']')
class State(object):
def __init__(self,name) :
self.name = name
def onEntry(self,act,w) :
w.steps += 1
print "Entering >> " + self.name + ' (' + act.tag + ')' + ("-" * w.steps)
def __repr__(self) :
return '<' + str(self.name) + '>'
class Machine(object):
def state(q,name) :
s = State(name)
if not q.start: q.start = s
if not q.states.has_key(name):
q.states[name] = s
q.outs[name] = q.outs.get(name,[])
return s
def act(q,before,after,tag) :
t = Act(before,after,tag)
q.actions.append(t)
q.outs[before.name].append(t)
return t
def create(q) :
return self
def walk(q,w=World()) :
return q.stagger(q.start,w)
def stagger(q,here,w) :
options = q.outs[here.name]
if options:
options = cycle(options,1)
for act in options:
if act.ready() :
act.there.onEntry(act,w)
return q.stagger(act.there,w)
return w
def __init__(q,str="") :
q.actions=[]
q.states={}
q.start= None
q.outs={}
global go
global at
go = gofn(q)
at = atfn(q)
q.create(str)
def atfn(machine) :
return (lambda x: machine.state(x))
def gofn(machine) :
return (lambda x,y,z: machine.act(x,y,z))
class Chess(Machine) :
def create(q,str="") :
# http://users.csc.calpoly.edu/~jdalbey/SWE/Design/STDexamples.html
# def at(x) : return q.state(x)
# def go(x,y,z) : return q.act(x,y,z)
w = at('whitesTurn')
b = at('blacksTurn')
bwin = at('blackWins')
draw = at('draw')
wwin = at('whiteWins')
go(w,b, 'white moves')
go(b,w, 'black moves')
go(w,bwin,'checkmate')
go(w,draw,'stalemate')
go(b,draw,'stalemate')
go(b,wwin,'checkmate')
class Easy(Machine) :
def create(self,str) :
lines=filter(None,lstrip(str.split('\n')))
last=None
states = []
for line in [lstrip(x.split('|')) for x in lines]:
if len(line) != 5:
print 'bad line ' + line
continue
comment = line[3]
here = at(line[0] or last)
there = at(line[4])
if line[0] : last = line[0]
go(here,there,comment)
def lstrip(lst) :
return [x.strip() for x in lst]
def eg1() :
m=Chess()
for i in range(10):
print '\n', i;
m.walk()
def eg2() :
m = Easy("""
whitesTurn|||white moves|blacksTurn
|||checkmate |blackWins
|?bored||stalemate |draw
blacksTurn|||black moves|whitesTurn
|||stalemate |draw
|||checkmate |whiteWins
""")
for i in range(10):
print '\n', i
out=m.walk(Game())
def eg3():
lst = cycle([1,2,3,4],2)
for x in lst:
print x
random.seed(1)
egs(eg2)
@timm
Copy link
Author

timm commented Apr 24, 2012

----| eg2 | ----------------------------------------

0
Entering >> draw (stalemate)-

1
Entering >> blackWins (checkmate)-

2
Entering >> blacksTurn (white moves)-
Entering >> whitesTurn (black moves)--
Entering >> blackWins (checkmate)---

3
Entering >> draw (stalemate)-

4
Entering >> blackWins (checkmate)-

5
Entering >> blackWins (checkmate)-

6
Entering >> draw (stalemate)-

7
Entering >> blacksTurn (white moves)-
Entering >> draw (stalemate)--

8
Entering >> draw (stalemate)-

9
Entering >> blacksTurn (white moves)-
Entering >> whiteWins (checkmate)--

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment