Created
April 24, 2012 12:48
-
-
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)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
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) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
----| 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)--