Jordan de la Houssaye

integrates andy's frontend and backend

1 +# entities: tuple of name of the entities, initial level, tuple of decays 0
2 +# denotes unbounded decay (omega)
3 +# examples:
4 +# entities = ( ('B',4, (0,2,2,2,3)), ('P',0, (0,0)), ('C',0, (0,0)),
5 +# ('G',0, (0,0)) )
6 +# entities = ( ('Sugar',1, (0,2)), ('Aspartame',0, (0,2)),
7 +# ('Glycemia',2, (0,2,2,2)), ('Glucagon',0, (0,2)),
8 +# ('Insulin',0,(0,2,2)) )
9 +
10 +entities = ( ('s1',0, (0,1)), ('s2',0, (0,1)), ('s3',0, (0,1)) )
11 +
12 +# Activities: Tuple of (activators, inhibitors, results, duration)
13 +# activators, inhibitors are dictionaries of pairs
14 +# (entity, level)
15 +# results are dictionaries of pairs (entity, +z)
16 +
17 +# potential activities examples:
18 +# potential = ( (dict([('P',0)]),dict([('P',1)]),dict([('P',1)]),0),
19 +# (dict([('P',1)]),dict(),dict([('P',-1)]),0),
20 +# (dict([('C',0)]),dict([('C',1)]),dict([('C',1)]),0),
21 +# (dict([('C',1)]),dict(),dict([('C',-1)]),0),
22 +# (dict([('G',0)]),dict([('G',1)]),dict([('G',1)]),0),
23 +# (dict([('G',1)]),dict(),dict([('G',-1)]),0) )
24 +# potential = ( (dict([('Sugar',1)]),dict(),
25 +# dict([('Insulin',1),('Glycemia',1)]),0),
26 +# (dict([('Aspartame',1)]),dict(),dict([('Insulin',1)]),0),
27 +# (dict(),dict([('Glycemia',1)]),dict([('Glucagon',1)]),0),
28 +# (dict([('Glycemia',3)]),dict(),dict([('Insulin',1)]),0),
29 +# (dict([('Insulin',2)]),dict(),dict([('Glycemia',-1)]),0),
30 +# (dict([('Insulin',1),('Glycemia',3)]), dict(),
31 +# dict([('Glycemia',-1)]),0),
32 +# (dict([('Insulin',1)]),dict([('Glycemia',2)]),
33 +# dict([('Glycemia',-1)]),0),
34 +# (dict([('Glucagon',1)]),dict(),dict([('Glycemia',+1)]),0)
35 +# )
36 +
37 +potential = ( (dict(), dict([('s1',1)]), dict([('s2',1)]), 1),
38 + (dict(), dict([('s2',1)]), dict([('s3',1)]), 1),
39 + (dict(), dict([('s3',1)]), dict([('s1',1)]), 1) )
40 +
41 +# obligatory activities examples:
42 +# obligatory = ( (dict([('P',1)]),dict(),dict([('B',1)]),1),
43 +# (dict([('C',1)]),dict(),dict([('B',-1)]),3),
44 +# (dict([('G',1)]),dict(),dict([('B',-2)]),3))
45 +
46 +obligatory = ()
47 +
1 -"""This package features the ABCD compiler, this is mainly a 1 +"""This package features the Andy compiler, this is mainly a
2 command-line tool but it can be called also from Python. The API is 2 command-line tool but it can be called also from Python. The API is
3 very simple and mimics the command line interface 3 very simple and mimics the command line interface
4 4
5 -### Function `snakes.utils.abcd.main.main` ### 5 +### Function `snakes.utils.andy.main.main` ###
6 6
7 :::python 7 :::python
8 - def main (args=sys.argv[1:], src=None) : ... 8 + def main (args=sys.argv[1:]) : ...
9 9
10 Entry point of the compiler 10 Entry point of the compiler
11 11
12 ##### Call API ##### 12 ##### Call API #####
13 13
14 * `list args`: 14 * `list args`:
15 - * `str src`:
16 * `return PetriNet`: 15 * `return PetriNet`:
17 16
18 ##### Exceptions ##### 17 ##### Exceptions #####
......
1 -import snakes.plugins
2 -snakes.plugins.load(['gv', 'ops'], 'snakes.nets', 'nets')
3 -from nets import *
4 -
5 -
6 ############################################################################### 1 ###############################################################################
7 ## AUXILIARY FUNCTIONS ######################################################## 2 ## AUXILIARY FUNCTIONS ########################################################
8 3
...@@ -132,14 +127,14 @@ def potentialt (name, lp, up, lambdap, R) : ...@@ -132,14 +127,14 @@ def potentialt (name, lp, up, lambdap, R) :
132 127
133 ############################################################################### 128 ###############################################################################
134 ## MAIN ####################################################################### 129 ## MAIN #######################################################################
135 -def andy2snakes(entities, potential, obligatory): 130 +def andy2snakes(snk, entities, potential, obligatory):
136 # compute maximal duration of activities 131 # compute maximal duration of activities
137 D=0 132 D=0
138 for alpha in potential : D = max(D, alpha[3]) 133 for alpha in potential : D = max(D, alpha[3])
139 134
140 for alpha in obligatory : D = max(D, alpha[3]) 135 for alpha in obligatory : D = max(D, alpha[3])
141 136
142 - n = PetriNet('andy') 137 + n = snk.PetriNet('andy')
143 138
144 n.globals["obligatory"] = obligatory 139 n.globals["obligatory"] = obligatory
145 n.globals["D"] = D 140 n.globals["D"] = D
...@@ -153,13 +148,13 @@ def andy2snakes(entities, potential, obligatory): ...@@ -153,13 +148,13 @@ def andy2snakes(entities, potential, obligatory):
153 level = entities[i][1] 148 level = entities[i][1]
154 deltas = entities[i][2] 149 deltas = entities[i][2]
155 vector = [0]*len(deltas) 150 vector = [0]*len(deltas)
156 - n.add_place(Place(name, [(level,0, tuple(vector))])) 151 + n.add_place(snk.Place(name, [(level,0, tuple(vector))]))
157 152
158 ################# clock transition 153 ################# clock transition
159 inputlist = dict() 154 inputlist = dict()
160 n.globals["inputlist"] = inputlist 155 n.globals["inputlist"] = inputlist
161 156
162 - n.add_transition(Transition('tc')) 157 + n.add_transition(snk.Transition('tc'))
163 158
164 159
165 # connect all obligatory clocks 160 # connect all obligatory clocks
...@@ -167,7 +162,7 @@ def andy2snakes(entities, potential, obligatory): ...@@ -167,7 +162,7 @@ def andy2snakes(entities, potential, obligatory):
167 # transition name 162 # transition name
168 obname = 'ob'+str(i) 163 obname = 'ob'+str(i)
169 # for every obligatory activity connect corresponding place to clock 164 # for every obligatory activity connect corresponding place to clock
170 - n.add_place(Place('p'+obname, [0])) 165 + n.add_place(snk.Place('p'+obname, [0]))
171 n.add_input('p'+obname, 'tc', Variable('w'+obname)) 166 n.add_input('p'+obname, 'tc', Variable('w'+obname))
172 inputlist.update({obname:'w'+obname}) 167 inputlist.update({obname:'w'+obname})
173 168
...@@ -178,20 +173,20 @@ def andy2snakes(entities, potential, obligatory): ...@@ -178,20 +173,20 @@ def andy2snakes(entities, potential, obligatory):
178 deltas = entities[i][2] 173 deltas = entities[i][2]
179 n.globals["deltas"+name] = deltas 174 n.globals["deltas"+name] = deltas
180 n.globals[name] = name 175 n.globals[name] = name
181 - n.add_input(name, 'tc', Tuple([Variable('l'+name), Variable('u'+name), Variable('lambda'+name) ])) 176 + n.add_input(name, 'tc', snk.Tuple([snk.Variable('l'+name), snk.Variable('u'+name), snk.Variable('lambda'+name) ]))
182 inputlist.update({name:['l'+name, 'u'+name, 'lambda'+name ]}) 177 inputlist.update({name:['l'+name, 'u'+name, 'lambda'+name ]})
183 178
184 179
185 180
186 for i in range(0,len(entities)): 181 for i in range(0,len(entities)):
187 name=entities[i][0] 182 name=entities[i][0]
188 - n.add_output(name, 'tc', Expression("clockt(obligatory,"+name+",l"+name+',u'+name+',lambda'+name+',deltas'+name+',inputlist,D)')) 183 + n.add_output(name, 'tc', snk.Expression("clockt(obligatory,"+name+",l"+name+',u'+name+',lambda'+name+',deltas'+name+',inputlist,D)'))
189 184
190 185
191 for i in range(0,len(obligatory)): 186 for i in range(0,len(obligatory)):
192 obname = 'ob'+str(i) 187 obname = 'ob'+str(i)
193 # for every obligatory activity connect corresponding place to clock 188 # for every obligatory activity connect corresponding place to clock
194 - n.add_output('p'+obname, 'tc', Expression("clockbetat(obligatory,"+str(i)+',w'+obname+',inputlist,D)')) 189 + n.add_output('p'+obname, 'tc', snk.Expression("clockbetat(obligatory,"+str(i)+',w'+obname+',inputlist,D)'))
195 190
196 191
197 ## potential activities 192 ## potential activities
...@@ -200,15 +195,15 @@ def andy2snakes(entities, potential, obligatory): ...@@ -200,15 +195,15 @@ def andy2snakes(entities, potential, obligatory):
200 trname = 'tr'+str(i) 195 trname = 'tr'+str(i)
201 196
202 # for every potential activity connect corresponding place to clock 197 # for every potential activity connect corresponding place to clock
203 - n.add_place(Place('p'+trname, [0])) 198 + n.add_place(snk.Place('p'+trname, [0]))
204 - n.add_input('p'+trname, 'tc', Variable('w'+trname)) 199 + n.add_input('p'+trname, 'tc', snk.Variable('w'+trname))
205 - n.add_output('p'+trname, 'tc', Expression('min(D,w'+trname+'+1)')) 200 + n.add_output('p'+trname, 'tc', snk.Expression('min(D,w'+trname+'+1)'))
206 201
207 202
208 activators = potential[i][0] 203 activators = potential[i][0]
209 inhibitors = potential[i][1] 204 inhibitors = potential[i][1]
210 results = potential[i][2] 205 results = potential[i][2]
211 - print results 206 + #print results
212 n.globals["results"+trname] = results 207 n.globals["results"+trname] = results
213 duration = potential[i][3] 208 duration = potential[i][3]
214 209
...@@ -240,14 +235,14 @@ def andy2snakes(entities, potential, obligatory): ...@@ -240,14 +235,14 @@ def andy2snakes(entities, potential, obligatory):
240 level = str(inhibitors[nameinhib[j]]) 235 level = str(inhibitors[nameinhib[j]])
241 guard += ' and l'+spec+'< '+ level + ' and lambda' +spec+'['+level+']>='+str(duration) 236 guard += ' and l'+spec+'< '+ level + ' and lambda' +spec+'['+level+']>='+str(duration)
242 237
243 - n.add_transition(Transition(trname, Expression(guard))) 238 + n.add_transition(snk.Transition(trname, snk.Expression(guard)))
244 - n.add_input('p'+trname, trname, Variable('w')) 239 + n.add_input('p'+trname, trname, snk.Variable('w'))
245 - n.add_output('p'+trname, trname, Expression('0')) 240 + n.add_output('p'+trname, trname, snk.Expression('0'))
246 241
247 # arcs of the transition from and to involved entities 242 # arcs of the transition from and to involved entities
248 for j in range(0,len(names)) : 243 for j in range(0,len(names)) :
249 - n.add_input(names[j], trname, Tuple([Variable('l'+names[j]), Variable('u'+names[j]), Variable('lambda'+names[j]) ])) 244 + n.add_input(names[j], trname, snk.Tuple([snk.Variable('l'+names[j]), snk.Variable('u'+names[j]), snk.Variable('lambda'+names[j]) ]))
250 - n.add_output(names[j], trname, Expression("potentialt(" +names[j]+",l"+names[j]+',u'+names[j]+',lambda'+names[j]+', results'+trname+')')) 245 + n.add_output(names[j], trname, snk.Expression("potentialt(" +names[j]+",l"+names[j]+',u'+names[j]+',lambda'+names[j]+', results'+trname+')'))
251 246
252 return n 247 return n
253 248
...@@ -255,7 +250,7 @@ def andy2snakes(entities, potential, obligatory): ...@@ -255,7 +250,7 @@ def andy2snakes(entities, potential, obligatory):
255 def draw_net(net, out_name='repress'): 250 def draw_net(net, out_name='repress'):
256 net.draw(out_name+'.ps') 251 net.draw(out_name+'.ps')
257 252
258 -def draw_stategraph(net, entities_names, out_name='repressgraph', 253 +def draw_stategraph(snk, net, entities_names, out_name='repressgraph',
259 with_dot=True): 254 with_dot=True):
260 def node_attr (state, graph, attr) : 255 def node_attr (state, graph, attr) :
261 marking = graph[state] 256 marking = graph[state]
...@@ -264,7 +259,7 @@ def draw_stategraph(net, entities_names, out_name='repressgraph', ...@@ -264,7 +259,7 @@ def draw_stategraph(net, entities_names, out_name='repressgraph',
264 def edge_attr (trans, mode, attr) : 259 def edge_attr (trans, mode, attr) :
265 attr["label"] = trans.name 260 attr["label"] = trans.name
266 261
267 - s = StateGraph(net) 262 + s = snk.StateGraph(net)
268 s.build() 263 s.build()
269 264
270 s.draw(out_name+'.ps', node_attr=node_attr, edge_attr=edge_attr, 265 s.draw(out_name+'.ps', node_attr=node_attr, edge_attr=edge_attr,
...@@ -278,6 +273,9 @@ def draw_stategraph(net, entities_names, out_name='repressgraph', ...@@ -278,6 +273,9 @@ def draw_stategraph(net, entities_names, out_name='repressgraph',
278 g.render(out_name+"-layout.dot", engine="dot") 273 g.render(out_name+"-layout.dot", engine="dot")
279 274
280 if __name__=='__main__': 275 if __name__=='__main__':
276 + import snakes.plugins
277 + snakes.plugins.load(['gv', 'ops'], 'snakes.nets', 'snk')
278 +
281 # entities: tuple of name of the entities, initial level, tuple of decays 0 279 # entities: tuple of name of the entities, initial level, tuple of decays 0
282 # denotes unbounded decay (omega) 280 # denotes unbounded decay (omega)
283 # examples: 281 # examples:
...@@ -325,7 +323,7 @@ if __name__=='__main__': ...@@ -325,7 +323,7 @@ if __name__=='__main__':
325 323
326 obligatory = () 324 obligatory = ()
327 325
328 - net = andy2snakes(entities, potential, obligatory) 326 + net = andy2snakes(snk, entities, potential, obligatory)
329 draw_net(net, out_name="repress") 327 draw_net(net, out_name="repress")
330 - draw_stategraph(net, ("s1", "s2", "s3"), out_name="repressgraph") 328 + draw_stategraph(snk, net, ("s1", "s2", "s3"), out_name="repressgraph")
331 329
......
1 -import sys, operator, inspect, re, collections
2 -from snakes.utils.abcd import CompilationError, DeclarationError
3 -from snakes.lang.abcd.parser import ast
4 -from snakes.lang import unparse
5 -import snakes.utils.abcd.transform as transform
6 -from snakes.data import MultiSet
7 -from snakes import *
8 -
9 -class Decl (object) :
10 - OBJECT = "object"
11 - TYPE = "type"
12 - BUFFER = "buffer"
13 - SYMBOL = "symbol"
14 - CONST = "const"
15 - NET = "net"
16 - TASK = "task"
17 - IMPORT = "import"
18 - def __init__ (self, node, kind=None, **data) :
19 - self.node = node
20 - classname = node.__class__.__name__
21 - if kind is not None :
22 - self.kind = kind
23 - elif classname == "AbcdTypedef" :
24 - self.kind = self.TYPE
25 - elif classname == "AbcdBuffer" :
26 - self.kind = self.BUFFER
27 - elif classname == "AbcdSymbol" :
28 - self.kind = self.SYMBOL
29 - elif classname == "AbcdConst" :
30 - self.kind = self.CONST
31 - elif classname == "AbcdNet" :
32 - self.kind = self.NET
33 - elif classname == "AbcdTask" :
34 - self.kind = self.TASK
35 - elif classname in ("Import", "ImportFrom") :
36 - self.kind = self.IMPORT
37 - else :
38 - self.kind = self.OBJECT
39 - for key, val in data.items() :
40 - setattr(self, key, val)
41 -
42 -class GetInstanceArgs (object) :
43 - """Bind arguments for a net instance
44 - """
45 - def __init__ (self, node) :
46 - self.argspec = []
47 - self.arg = {}
48 - self.buffer = {}
49 - self.net = {}
50 - self.task = {}
51 - seen = set()
52 - for a in node.args.args + node.args.kwonlyargs :
53 - if a.arg in seen :
54 - self._raise(CompilationError,
55 - "duplicate argument %r" % a.arg)
56 - seen.add(a.arg)
57 - if a.annotation is None :
58 - self.argspec.append((a.arg, "arg"))
59 - else :
60 - self.argspec.append((a.arg, a.annotation.id))
61 - def __call__ (self, *args) :
62 - self.arg.clear()
63 - self.buffer.clear()
64 - self.net.clear()
65 - self.task.clear()
66 - for (name, kind), value in zip(self.argspec, args) :
67 - getattr(self, kind)[name] = value
68 - return self.arg, self.buffer, self.net, self.task
69 -
70 -class Builder (object) :
71 - def __init__ (self, snk, path=[], up=None) :
72 - self.snk = snk
73 - self.path = path
74 - self.up = up
75 - self.env = {"True": Decl(None, kind=Decl.CONST, value=True),
76 - "False": Decl(None, kind=Decl.CONST, value=False),
77 - "None": Decl(None, kind=Decl.CONST, value=None),
78 - "dot": Decl(None, kind=Decl.CONST, value=self.snk.dot),
79 - "BlackToken": Decl(None, kind=Decl.TYPE,
80 - type=self.snk.Instance(self.snk.BlackToken))}
81 - self.stack = []
82 - if up :
83 - self.globals = up.globals
84 - else :
85 - self.globals = snk.Evaluator(dot=self.snk.dot,
86 - BlackToken=self.snk.BlackToken)
87 - self.instances = MultiSet()
88 - # utilities
89 - def _raise (self, error, message) :
90 - """raise an exception with appropriate location
91 - """
92 - if self.stack :
93 - pos = "[%s:%s]: " % (self.stack[-1].lineno,
94 - self.stack[-1].col_offset)
95 - else :
96 - pos = ""
97 - raise error(pos+message)
98 - def _eval (self, expr, *largs, **kwargs) :
99 - env = self.globals.copy()
100 - if isinstance(expr, ast.AST) :
101 - expr = unparse(expr)
102 - return env(expr, dict(*largs, **kwargs))
103 - # declarations management
104 - def __setitem__ (self, name, value) :
105 - if name in self.env :
106 - self._raise(DeclarationError, "duplicated declaration of %r" % name)
107 - self.env[name] = value
108 - def __getitem__ (self, name) :
109 - if name in self.env :
110 - return self.env[name]
111 - elif self.up is None :
112 - self._raise(DeclarationError, "%r not declared" % name)
113 - else :
114 - return self.up[name]
115 - def __contains__ (self, name) :
116 - if name in self.env :
117 - return True
118 - elif self.up is None :
119 - return False
120 - else :
121 - return name in self.up
122 - def goto (self, name) :
123 - if name in self.env :
124 - return self
125 - elif self.up is None :
126 - self._raise(DeclarationError, "%r not declared" % name)
127 - else :
128 - return self.up.goto(name)
129 - def get_buffer (self, name) :
130 - if name not in self :
131 - self._raise(DeclarationError,
132 - "buffer %r not declared" % name)
133 - decl = self[name]
134 - if decl.kind != Decl.BUFFER :
135 - self._raise(DeclarationError,
136 - "%r declared as %s but used as buffer"
137 - % (name, decl.kind))
138 - elif decl.capacity is not None :
139 - pass
140 - #self._raise(NotImplementedError, "capacities not (yet) supported")
141 - return decl
142 - def get_net (self, name) :
143 - if name not in self :
144 - self._raise(DeclarationError,
145 - "net %r not declared" % name)
146 - decl = self[name]
147 - if decl.kind != Decl.NET :
148 - self._raise(DeclarationError,
149 - "%r declared as %s but used as net"
150 - % (name, decl.kind))
151 - return decl
152 - def get_task (self, name) :
153 - if name not in self :
154 - self._raise(DeclarationError,
155 - "task %r not declared" % name)
156 - decl = self[name]
157 - if decl.kind != Decl.TASK :
158 - self._raise(DeclarationError,
159 - "%r declared as %s but used as task"
160 - % (name, decl.kind))
161 - return decl
162 - # main compiler entry point
163 - def build (self, node, prefix="", fallback=None) :
164 - self.stack.append(node)
165 - if prefix :
166 - prefix += "_"
167 - method = "build_" + prefix + node.__class__.__name__
168 - visitor = getattr(self, method, fallback or self.build_fail)
169 - try :
170 - return visitor(node)
171 - finally :
172 - self.stack.pop(-1)
173 - def build_fail (self, node) :
174 - self._raise(CompilationError, "do not know how to compile %s"
175 - % node.__class__.__name__)
176 - def build_arc (self, node) :
177 - return self.build(node, "arc", self.build_arc_expr)
178 - # specification
179 - def build_AbcdSpec (self, node) :
180 - for decl in node.context :
181 - self.build(decl)
182 - tasks = [self._build_TaskNet(decl.node)
183 - for name, decl in self.env.items()
184 - if decl.kind == Decl.TASK and decl.used]
185 - net = reduce(operator.or_, tasks, self.build(node.body))
186 - # set local buffers marking, and hide them
187 - for name, decl in ((n, d) for n, d in self.env.items()
188 - if d.kind == Decl.BUFFER) :
189 - status = self.snk.buffer(name)
190 - for place in net.status(status) :
191 - place = net.place(place)
192 - try :
193 - place.reset(decl.marking)
194 - except ValueError as err :
195 - self._raise(CompilationError,
196 - "invalid initial marking (%s)" % err)
197 - if decl.capacity is None :
198 - cap = None
199 - else :
200 - #cap = [c.n if c else None for c in decl.capacity]
201 - # TODO: accept more than integers as capacities
202 - cap = []
203 - for c in decl.capacity :
204 - if c is None :
205 - cap.append(None)
206 - else :
207 - try :
208 - cap.append(self._eval(c))
209 - except :
210 - err = sys.exc_info()[1]
211 - self._raise(CompilationError,
212 - "could not evaluate %r, %s"
213 - % (unparse(c), err))
214 - place.label(path=self.path,
215 - capacity=cap)
216 - # TODO: check capacity
217 - net.hide(status)
218 - if self.up is None :
219 - # set entry marking
220 - for place in net.status(self.snk.entry) :
221 - net.place(place).reset(self.snk.dot)
222 - # rename nodes
223 - self._rename_nodes(net)
224 - # copy global declarations
225 - net.globals.update(self.globals)
226 - # add info about source file
227 - net.label(srcfile=str(node.st.text.filename))
228 - # add assertions
229 - net.label(asserts=node.asserts)
230 - return net
231 - def _build_TaskNet (self, node) :
232 - self._raise(NotImplementedError, "tasks not (yet) supported")
233 - def _rename_nodes (self, net) :
234 - # generate unique names
235 - total = collections.defaultdict(int)
236 - count = collections.defaultdict(int)
237 - def ren (node) :
238 - if net.has_transition(node.name) :
239 - status = node.label("srctext")
240 - else :
241 - if node.status == self.snk.entry :
242 - status = "e"
243 - elif node.status == self.snk.internal :
244 - status = "i"
245 - elif node.status == self.snk.exit :
246 - status = "x"
247 - else :
248 - status = node.label("buffer")
249 - name = ".".join(node.label("path") + [status])
250 - if total[name] > 1 :
251 - count[name] += 1
252 - name = "%s#%s" % (name, count[name])
253 - return name
254 - # count occurrences of each name base
255 - _total = collections.defaultdict(int)
256 - for node in net.node() :
257 - _total[ren(node)] += 1
258 - total = _total
259 - # rename nodes using a depth-first traversal
260 - done = set(net.status(self.snk.entry))
261 - todo = [net.node(n) for n in done]
262 - while todo :
263 - node = todo.pop(-1)
264 - new = ren(node)
265 - if new != node.name :
266 - net.rename_node(node.name, new)
267 - done.add(new)
268 - for n in net.post(new) - done :
269 - todo.append(net.node(n))
270 - done.add(n)
271 - # rename isolated nodes
272 - for letter, method in (("p", net.place), ("t", net.transition)) :
273 - for node in method() :
274 - if node.name not in done :
275 - net.rename_node(node.name, ren(node))
276 - # declarations
277 - def build_AbcdTypedef (self, node) :
278 - """
279 - >>> import snakes.nets
280 - >>> b = Builder(snakes.nets)
281 - >>> b.build(ast.AbcdTypedef(name='number', type=ast.UnionType(types=[ast.NamedType(name='int'), ast.NamedType(name='float')])))
282 - >>> b.env['number'].type
283 - (Instance(int) | Instance(float))
284 - >>> b.build(ast.ImportFrom(module='inspect', names=[ast.alias(name='isbuiltin')]))
285 - >>> b.build(ast.AbcdTypedef(name='builtin', type=ast.NamedType(name='isbuiltin')))
286 - >>> b.env['builtin'].type
287 - TypeCheck(inspect.isbuiltin)
288 - """
289 - self[node.name] = Decl(node, type=self.build(node.type))
290 - def build_AbcdBuffer (self, node) :
291 - self[node.name] = Decl(node,
292 - type=self.build(node.type),
293 - capacity=node.capacity,
294 - marking=self._eval(node.content))
295 - def build_AbcdSymbol (self, node) :
296 - for name in node.symbols :
297 - value = self.snk.Symbol(name, False)
298 - self[name] = Decl(node, value=value)
299 - self.globals[name] = value
300 - def build_AbcdConst (self, node) :
301 - value = self._eval(node.value)
302 - self[node.name] = Decl(node, value=value)
303 - self.globals[node.name] = value
304 - def build_AbcdNet (self, node) :
305 - self[node.name] = Decl(node, getargs=GetInstanceArgs(node))
306 - def build_AbcdTask (self, node) :
307 - self._raise(NotImplementedError, "tasks not (yet) supported")
308 - self[node.name] = Decl(node, used=False)
309 - def build_Import (self, node) :
310 - for alias in node.names :
311 - self[alias.asname or alias.name] = Decl(node)
312 - self.globals.declare(unparse(node))
313 - def build_ImportFrom (self, node) :
314 - self.build_Import(node)
315 - # processes
316 - def build_AbcdAction (self, node) :
317 - if node.guard is True :
318 - return self._build_True(node)
319 - elif node.guard is False :
320 - return self._build_False(node)
321 - else :
322 - return self._build_action(node)
323 - def _build_True (self, node) :
324 - net = self.snk.PetriNet("true")
325 - e = self.snk.Place("e", [], self.snk.tBlackToken,
326 - status=self.snk.entry)
327 - e.label(path=self.path)
328 - net.add_place(e)
329 - x = self.snk.Place("x", [], self.snk.tBlackToken,
330 - status=self.snk.exit)
331 - x.label(path=self.path)
332 - net.add_place(x)
333 - t = self.snk.Transition("t")
334 - t.label(srctext=node.st.source(),
335 - srcloc=(node.st.srow, node.st.scol,
336 - node.st.erow, node.st.ecol),
337 - path=self.path)
338 - net.add_transition(t)
339 - net.add_input("e", "t", self.snk.Value(self.snk.dot))
340 - net.add_output("x", "t", self.snk.Value(self.snk.dot))
341 - return net
342 - def _build_False (self, node) :
343 - net = self.snk.PetriNet("false")
344 - e = self.snk.Place("e", [], self.snk.tBlackToken,
345 - status=self.snk.entry)
346 - e.label(path=self.path)
347 - net.add_place(e)
348 - x = self.snk.Place("x", [], self.snk.tBlackToken,
349 - status=self.snk.exit)
350 - x.label(path=self.path)
351 - net.add_place(x)
352 - return net
353 - def _build_action (self, node) :
354 - net = self.snk.PetriNet("flow")
355 - e = self.snk.Place("e", [], self.snk.tBlackToken,
356 - status=self.snk.entry)
357 - e.label(path=self.path)
358 - net.add_place(e)
359 - x = self.snk.Place("x", [], self.snk.tBlackToken,
360 - status=self.snk.exit)
361 - x.label(path=self.path)
362 - net.add_place(x)
363 - t = self.snk.Transition("t", self.snk.Expression(unparse(node.guard)),
364 - status=self.snk.tick("action"))
365 - t.label(srctext=node.st.source(),
366 - srcloc=(node.st.srow, node.st.scol,
367 - node.st.erow, node.st.ecol),
368 - path=self.path)
369 - net.add_transition(t)
370 - net.add_input("e", "t", self.snk.Value(self.snk.dot))
371 - net.add_output("x", "t", self.snk.Value(self.snk.dot))
372 - net = reduce(operator.or_, [self.build(a) for a in node.accesses],
373 - net)
374 - net.hide(self.snk.tick("action"))
375 - return net
376 - def build_AbcdFlowOp (self, node) :
377 - return self.build(node.op)(self.build(node.left),
378 - self.build(node.right))
379 - def _get_instance_arg (self, arg) :
380 - if arg.__class__.__name__ == "Name" and arg.id in self :
381 - return self[arg.id]
382 - else :
383 - try :
384 - self._eval(arg)
385 - except :
386 - self._raise(CompilationError,
387 - "could not evaluate argument %r"
388 - % arg.st.source())
389 - return arg
390 - def build_AbcdInstance (self, node) :
391 - if node.net not in self :
392 - self._raise(DeclarationError, "%r not declared" % node.net)
393 - elif node.starargs :
394 - self._raise(CompilationError, "* argument not allowed here")
395 - elif node.kwargs :
396 - self._raise(CompilationError, "** argument not allowed here")
397 - decl = self[node.net]
398 - if decl.kind != Decl.NET :
399 - self._raise(DeclarationError,
400 - "%r declared as %s but used as net"
401 - % (name, decl.kind))
402 - # unpack args
403 - posargs, kwargs = [], {}
404 - for arg in node.args :
405 - posargs.append(self._get_instance_arg(arg))
406 - for kw in node.keywords :
407 - kwargs[kw.arg] = self._get_instance_arg(kw.value)
408 - # bind args
409 - try :
410 - args, buffers, nets, tasks = decl.getargs(*posargs, **kwargs)
411 - except TypeError :
412 - c, v, t = sys.exc_info()
413 - self._raise(CompilationError, str(v))
414 - for d, kind in ((buffers, Decl.BUFFER),
415 - (nets, Decl.NET),
416 - (tasks, Decl.TASK)) :
417 - for k, v in d.items() :
418 - if v.kind != kind :
419 - self._raise(DeclarationError,
420 - "%r declared as %s but used as %s"
421 - % (k, v.kind, kind))
422 - d[k] = v.node.name
423 - # build sub-net
424 - binder = transform.ArgsBinder(args, buffers, nets, tasks)
425 - spec = binder.visit(decl.node.body)
426 - if node.asname :
427 - name = str(node.asname)
428 - else :
429 - name = node.st.source()
430 - if name in self.instances :
431 - name = "%s#%s" % (name, self.instances(name))
432 - self.instances.add(name)
433 - path = self.path + [name]
434 - builder = self.__class__(self.snk, path, self)
435 - net = builder.build(spec)
436 - src = (node.st.source(),
437 - node.st.srow, node.st.scol,
438 - node.st.erow, node.st.ecol)
439 - for trans in net.transition() :
440 - try :
441 - lbl = trans.label("instances")
442 - trans.label(instances=[src] + lbl)
443 - except KeyError :
444 - trans.label(instances=[src])
445 - for place in net.place() :
446 - if place.status == self.snk.Status(None) :
447 - try :
448 - lbl = place.label("instances")
449 - place.label(instances=[src] + lbl)
450 - except KeyError :
451 - place.label(instances=[src])
452 - return net
453 - # control flow operations
454 - def build_Sequence (self, node) :
455 - return self.snk.PetriNet.__and__
456 - def build_Choice (self, node) :
457 - return self.snk.PetriNet.__add__
458 - def build_Parallel (self, node) :
459 - return self.snk.PetriNet.__or__
460 - def build_Loop (self, node) :
461 - return self.snk.PetriNet.__mul__
462 - # accesses :
463 - def build_SimpleAccess (self, node) :
464 - decl = self.get_buffer(node.buffer)
465 - net = self.snk.PetriNet("access")
466 - net.add_transition(self.snk.Transition("t", status=self.snk.tick("action")))
467 - b = self.snk.Place(str(node.buffer), [], decl.type,
468 - status=self.snk.buffer(node.buffer))
469 - b.label(path=self.path,
470 - buffer=str(node.buffer),
471 - srctext=decl.node.st.source(),
472 - srcloc=(decl.node.st.srow, decl.node.st.scol,
473 - decl.node.st.erow, decl.node.st.ecol))
474 - net.add_place(b)
475 - self.build(node.arc)(net, node.buffer, "t", self.build_arc(node.tokens))
476 - return net
477 - def build_FlushAccess (self, node) :
478 - decl = self.get_buffer(node.buffer)
479 - net = self.snk.PetriNet("access")
480 - net.add_transition(self.snk.Transition("t", status=self.snk.tick("action")))
481 - b = self.snk.Place(str(node.buffer), [], decl.type,
482 - status=self.snk.buffer(node.buffer))
483 - b.label(path=self.path,
484 - buffer=str(node.buffer),
485 - srctext=decl.node.st.source(),
486 - srcloc=(decl.node.st.srow, decl.node.st.scol,
487 - decl.node.st.erow, decl.node.st.ecol))
488 - net.add_place(b)
489 - net.add_input(node.buffer, "t", self.snk.Flush(node.target))
490 - return net
491 - def build_SwapAccess (self, node) :
492 - decl = self.get_buffer(node.buffer)
493 - net = self.snk.PetriNet("access")
494 - net.add_transition(self.snk.Transition("t", status=self.snk.tick("action")))
495 - b = self.snk.Place(node.buffer, [], decl.type,
496 - status=self.snk.buffer(node.buffer))
497 - b.label(path=self.path,
498 - buffer=str(node.buffer),
499 - srctext=decl.node.st.source(),
500 - srcloc=(decl.node.st.srow, decl.node.st.scol,
501 - decl.node.st.erow, decl.node.st.ecol))
502 - net.add_place(b)
503 - net.add_input(node.buffer, "t", self.build_arc(node.target))
504 - net.add_output(node.buffer, "t", self.build_arc(node.tokens))
505 - return net
506 - def build_Spawn (self, node) :
507 - self._raise(NotImplementedError, "tasks not (yet) supported")
508 - def build_Wait (self, node) :
509 - self._raise(NotImplementedError, "tasks not (yet) supported")
510 - def build_Suspend (self, node) :
511 - self._raise(NotImplementedError, "tasks not (yet) supported")
512 - def build_Resume (self, node) :
513 - self._raise(NotImplementedError, "tasks not (yet) supported")
514 - # arc labels
515 - def build_arc_Name (self, node) :
516 - if node.id in self :
517 - decl = self[node.id]
518 - if decl.kind in (Decl.CONST, Decl.SYMBOL) :
519 - return self.snk.Value(decl.value)
520 - return self.snk.Variable(node.id)
521 - def build_arc_Num (self, node) :
522 - return self.snk.Value(node.n)
523 - def build_arc_Str (self, node) :
524 - return self.snk.Value(node.s)
525 - def build_arc_Tuple (self, node) :
526 - return self.snk.Tuple([self.build_arc(elt) for elt in node.elts])
527 - def build_arc_expr (self, node) :
528 - return self.snk.Expression(unparse(node))
529 - # arcs
530 - def build_Produce (self, node) :
531 - def arc (net, place, trans, label) :
532 - net.add_output(place, trans, label)
533 - return arc
534 - def build_Test (self, node) :
535 - def arc (net, place, trans, label) :
536 - net.add_input(place, trans, self.snk.Test(label))
537 - return arc
538 - def build_Consume (self, node) :
539 - def arc (net, place, trans, label) :
540 - net.add_input(place, trans, label)
541 - return arc
542 - def build_Fill (self, node) :
543 - def arc (net, place, trans, label) :
544 - net.add_output(place, trans, self.snk.Flush(str(label)))
545 - return arc
546 - # types
547 - def build_UnionType (self, node) :
548 - return reduce(operator.or_, (self.build(child)
549 - for child in node.types))
550 - def build_IntersectionType (self, node) :
551 - return reduce(operator.and_, (self.build(child)
552 - for child in node.types))
553 - def build_CrossType (self, node) :
554 - return self.snk.CrossProduct(*(self.build(child)
555 - for child in node.types))
556 - def build_ListType (self, node) :
557 - return self.snk.List(self.build(node.items))
558 - def build_TupleType (self, node) :
559 - return self.snk.Collection(self.snk.Instance(tuple),
560 - (self.build(node.items)))
561 - def build_SetType (self, node) :
562 - return self.snk.Set(self.build(node.items))
563 - def build_DictType (self, node) :
564 - return self.snk.Mapping(keys=self.build(node.keys),
565 - items=self.build(node.items),
566 - _dict=self.snk.Instance(self.snk.hdict))
567 - def build_EnumType (self, node) :
568 - return self.snk.OneOf(*(self._eval(child) for child in node.items))
569 - def build_NamedType (self, node) :
570 - name = node.name
571 - if name in self and self[name].kind == Decl.TYPE :
572 - return self[name].type
573 - elif name in self.globals :
574 - obj = self.globals[name]
575 - if inspect.isclass(obj) :
576 - return self.snk.Instance(obj)
577 - elif inspect.isroutine(obj) :
578 - return self.snk.TypeCheck(obj)
579 - elif hasattr(sys.modules["__builtin__"], name) :
580 - obj = getattr(sys.modules["__builtin__"], name)
581 - if inspect.isclass(obj) :
582 - return self.snk.Instance(obj)
583 - elif inspect.isroutine(obj) :
584 - return self.snk.TypeCheck(obj)
585 - self._raise(CompilationError,
586 - "invalid type %r" % name)
587 -
588 -if __name__ == "__main__" :
589 - import doctest
590 - doctest.testmod(optionflags=doctest.NORMALIZE_WHITESPACE
591 - | doctest.REPORT_ONLY_FIRST_FAILURE
592 - | doctest.ELLIPSIS)
593 - from snakes.lang.abcd.parser import parse
594 - node = parse(open(sys.argv[1]).read())
595 - import snakes.plugins
596 - snk = snakes.plugins.load(["ops", "gv", "labels"], "snakes.nets", "snk")
597 - build = Builder(snk)
598 - net = build.build(node)
599 - net.draw(sys.argv[1] + ".png")
1 -import heapq
2 -from snakes.nets import StateGraph
3 -import snakes.lang
4 -import snkast as ast
5 -
6 -class Checker (object) :
7 - def __init__ (self, net) :
8 - self.g = StateGraph(net)
9 - self.f = [self.build(f) for f in net.label("asserts")]
10 - def build (self, tree) :
11 - src = """
12 -def check (_) :
13 - return %s
14 -""" % tree.st.source()[7:]
15 - ctx = dict(self.g.net.globals)
16 - ctx["bounded"] = self.bounded
17 - exec(src, ctx)
18 - fun = ctx["check"]
19 - fun.lineno = tree.lineno
20 - return fun
21 - def bounded (self, marking, max) :
22 - return all(len(marking(p)) == 1 for p in marking)
23 - def run (self) :
24 - for state in self.g :
25 - marking = self.g.net.get_marking()
26 - for place in marking :
27 - if max(marking(place).values()) > 1 :
28 - return None, self.trace(state)
29 - for check in self.f :
30 - try :
31 - if not check(marking) :
32 - return check.lineno, self.trace(state)
33 - except :
34 - pass
35 - return None, None
36 - def path (self, tgt, src=0) :
37 - q = [(0, src, ())]
38 - visited = set()
39 - while True :
40 - (c, v1, path) = heapq.heappop(q)
41 - if v1 not in visited :
42 - path = path + (v1,)
43 - if v1 == tgt :
44 - return path
45 - visited.add(v1)
46 - for v2 in self.g.successors(v1) :
47 - if v2 not in visited :
48 - heapq.heappush(q, (c+1, v2, path))
49 - def trace (self, state) :
50 - path = self.path(state)
51 - return tuple(self.g.successors(i)[j]
52 - for i, j in zip(path[:-1], path[1:]))
1 -from snakes.compat import io
2 -from snakes.lang.abcd.parser import ast, parse
3 -import os, tempfile, re, codecs, collections
4 -try :
5 - from cgi import escape
6 -except :
7 - from html import escape
8 -
9 -template_css = u"""/* ABCD source code */
10 - .abcd { border:solid 1px #DDD; border-radius:5px; padding:5px 10px; margin:5px; background-color:#F4F4F4; overflow:auto; }
11 - .abcd .comment { color:#888; }
12 - .abcd .ident { color:#808; }
13 - .abcd .string { color:#088; }
14 - .abcd .kw { color:#800; font-weight:bold; }
15 - .abcd .flow { color:#800; font-weight:bold; }
16 - .abcd .buffer .decl { color:#080; font-weight:bold; }
17 - .abcd .net .decl { color:#008; font-weight:bold; }
18 - .abcd .instance .name { color:#008; }
19 - .abcd .action .delim { font-weight:bold; }
20 - .abcd .action .name { color:#080; }
21 - .abcd .highlight { background-color:yellow; }
22 -/* Petri net picture */
23 - .petrinet { border:solid 1px #DDD; border-radius:5px; padding:5px 10px; margin:5px; background-color:#FFF; overflow:auto; clear:both; }
24 -/* Objects tree */
25 - .tree { border:solid 1px #DDD; border-radius:5px; padding:5px 10px; margin:5px; background-color:#F4F4F4; overflow:auto; font-family:monospace; }
26 - .tree .kw { color:#800; font-weight:bold; }
27 - .tree .buffer { color:#080; font-weight:bold; }
28 - .tree .ident { color:#808; }
29 - .tree .instance .name { color:#008; }
30 - .tree .action .delim { font-weight:bold; }
31 - .tree .action .name { color:#080; }
32 - .tree .string { color:#088; }
33 - .tree .highlight { background-color:yellow; }
34 -"""
35 -
36 -template_html = u'''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
37 -<html xmlns="http://www.w3.org/1999/xhtml">
38 -<head><title>%(filename)s</title>
39 -<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
40 -<style type="text/css">%(css)s</style>
41 -%(headers)s
42 -%(jscode)s
43 -</head><body>
44 -<h1><tt>%(filename)s</tt></h1>
45 -%(abcd)s
46 -%(tree)s
47 -%(svg)s
48 -</body></html>
49 -'''
50 -
51 -template_tree = '''<div class="tree">%(tree)s</div>'''
52 -
53 -template_headers = '''<script src="http://code.jquery.com/jquery-1.11.0.min.js" type="text/javascript"></script>'''
54 -
55 -template_jscode = '''<script type="text/javascript">
56 -var nodeColor;
57 -function abcdon () {
58 - obj = jQuery(this);
59 - if (obj.attr("class") == "node") {
60 - node = obj.children().children().first();
61 - nodeColor = node.attr("fill");
62 - node.attr("fill", "yellow");
63 - } else {
64 - obj.addClass("highlight");
65 - }
66 - jQuery(obj.attr("data-abcd")).addClass("highlight");
67 -};
68 -function abcdoff () {
69 - obj = jQuery(this);
70 - if (obj.attr("class") == "node") {
71 - node = obj.children().children().first();
72 - node.attr("fill", nodeColor);
73 - } else {
74 - obj.removeClass("highlight");
75 - }
76 - jQuery(obj.attr("data-abcd")).removeClass("highlight");
77 -};
78 -function treeon () {
79 - obj = jQuery(this);
80 - if (obj.attr("class") != "node") {
81 - obj.addClass("highlight");
82 - }
83 - jQuery(obj.attr("data-tree")).addClass("highlight");
84 -};
85 -function treeoff () {
86 - obj = jQuery(this);
87 - if (obj.attr("class") != "node") {
88 - obj.removeClass("highlight");
89 - }
90 - jQuery(obj.attr("data-tree")).removeClass("highlight");
91 -};
92 -function neton () {
93 - obj = jQuery(this);
94 - jQuery(obj.attr("data-net")).each(function () {
95 - node = jQuery(this).children().children().first();
96 - nodeColor = node.attr("fill");
97 - node.attr("fill", "yellow");
98 - });
99 - obj.addClass("highlight");
100 -};
101 -function netoff () {
102 - obj = jQuery(this);
103 - jQuery(obj.attr("data-net")).each(function () {
104 - node = jQuery(this).children().children().first();
105 - node.attr("fill", nodeColor);
106 - });
107 - obj.removeClass("highlight");
108 -};
109 -function setwidth () {
110 - abcd = jQuery(".abcd");
111 - tree = jQuery(".tree");
112 - width = (jQuery(".petrinet").outerWidth(true) / 2) - 35;
113 - console.log(width);
114 - height = Math.max(abcd.height(), tree.height());
115 - abcd.css({float: "left", width: width, height: height});
116 - tree.css({float: "right", width: width, height: height});
117 -}
118 -jQuery(document).ready(function() {
119 - jQuery("[data-abcd]").hover(abcdon, abcdoff);
120 - jQuery("[data-tree]").hover(treeon, treeoff);
121 - jQuery("[data-net]").hover(neton, netoff);
122 - jQuery(".tree .instance, .tree .action").each(function () {
123 - obj = jQuery(this);
124 - obj.html(jQuery(obj.attr("data-abcd")).html());
125 - });
126 - setwidth();
127 - jQuery(window).resize(setwidth);
128 -});
129 -</script>'''
130 -
131 -class Span (object) :
132 - def __init__ (self, cls=[], id=None, net=[], abcd=[], tree=[]) :
133 - self.cls = set([cls]) if isinstance(cls, str) else set(cls)
134 - self.id = id
135 - self.net = set([net]) if isinstance(net, str) else set(net)
136 - self.abcd = set([abcd]) if isinstance(abcd, str) else set(abcd)
137 - self.tree = set([tree]) if isinstance(tree, str) else set(tree)
138 - def copy (self, **attr) :
139 - span = self.__class__(cls=self.cls, id=self.id, net=self.net,
140 - abcd=self.abcd, tree=self.tree)
141 - for k, v in attr.items() :
142 - if isinstance(getattr(span, k), set) :
143 - v = set(v)
144 - setattr(span, k, v)
145 - return span
146 - def __bool__ (self) :
147 - return self.__nonzero__()
148 - def __nonzero__ (self) :
149 - return bool(self.cls or self.id or self.net or self.abcd
150 - or self.tree)
151 - def span (self) :
152 - attr = []
153 - for src, dst in (("cls", "class"), ("id", "id"),
154 - ("net", "data-net"), ("abcd", "data-abcd"),
155 - ("tree", "data-tree")) :
156 - val = getattr(self, src)
157 - if not val :
158 - continue
159 - elif isinstance(val, str) :
160 - attr.append("%s=%r" % (dst, val))
161 - elif dst.startswith("data-") :
162 - attr.append("%s=%r" % (dst, ", ".join("#" + v for v in val)))
163 - else :
164 - attr.append("%s=%r" % (dst, ", ".join(val)))
165 - return "<span %s>" % " ".join(attr)
166 - def __str__ (self) :
167 - return self.span()
168 -
169 -keywords = {"False", "True", "and", "as", "assert", "buffer", "const",
170 - "else", "enum", "for", "from", "if", "import", "in", "is",
171 - "lambda", "net", "not", "or", "symbol", "task", "typedef"}
172 -
173 -class ABCD2HTML (ast.NodeVisitor) :
174 - def __init__ (self, tree) :
175 - self.tree = tree
176 - self.x = "%%0%uX" % len("%x" % (tree.st.erow + 1))
177 - self.st = {}
178 - self.path = []
179 - self.nets = {}
180 - self.visit(tree)
181 - def __getitem__ (self, id) :
182 - cls = id.__class__.__name__
183 - if cls in ("Place", "Transition") :
184 - x, y, _, _ = id.label("srcloc")
185 - c = "B" if cls == "Place" else "A"
186 - id = self.newid(c, x, y)
187 - elif isinstance(id, tuple) :
188 - id = self.newid(*id)
189 - if isinstance(self.st[id], Span) :
190 - return self.st[id]
191 - else :
192 - return self.st[id].span
193 - def newid (self, c, x, y) :
194 - return "".join([c[0].upper(), self.x % x, "%X" % y])
195 - def setspan (self, cls, node, **args) :
196 - if isinstance(node, ast.AST) :
197 - node = node.st
198 - if cls in ("action", "buffer", "instance", "net") :
199 - x, y = node.srow, node.scol
200 - ident = self.newid(cls, x, y)
201 - ident = args.pop("id", ident)
202 - span = node.span = Span(cls=cls.lower(), id=ident, **args)
203 - self.st[ident] = node
204 - elif node is None :
205 - span = Span(cls=cls.lower(), **args)
206 - if "id" in args :
207 - self.st[args["id"]] = span
208 - else :
209 - span = node.span = Span(cls=cls.lower(), **args)
210 - if "id" in args :
211 - self.st[args["id"]] = node
212 - return span
213 - def visit_AbcdBuffer (self, node) :
214 - t = node.st
215 - while t.symbol != "abcd_buffer" :
216 - t = t[0]
217 - self.setspan("decl", t[1])
218 - self.setspan("buffer", node)
219 - self.generic_visit(node)
220 - def visit_AbcdNet (self, node) :
221 - t = node.st
222 - while t.symbol != "abcd_net" :
223 - t = t[0]
224 - self.setspan("decl", t[1])
225 - self.setspan("body", node.body)
226 - span = self.setspan("net", node)
227 - self.setspan("proto", None, id="P" + span.id)
228 - self.nets[".".join(self.path + [node.name])] = span.id
229 - self.path.append(node.name)
230 - self.generic_visit(node)
231 - self.path.pop(-1)
232 - def visit_AbcdInstance (self, node) :
233 - t = node.st
234 - while t.symbol != "abcd_instance" :
235 - t = t[0]
236 - self.setspan("name", t[0])
237 - pid = "P" + self.nets[".".join(self.path + [node.net])]
238 - span = self.setspan("instance", node, abcd=[pid])
239 - self[pid].abcd.add(span.id)
240 - self.generic_visit(node)
241 - def visit_AbcdAction (self, node) :
242 - t = node.st
243 - while t[0].text != '[' :
244 - t = t[0]
245 - span = self.setspan("action", node)
246 - self.setspan("delim", t[0], id="L" + span.id)
247 - self.setspan("delim", t[-1], id="R" + span.id)
248 - self.generic_visit(node)
249 - def visit_AbcdFlowOp (self, node) :
250 - t = node.st
251 - while len(t) == 1 :
252 - t = t[0]
253 - while t[0].text == '(' :
254 - t = t[1]
255 - for op in t[1::2] :
256 - self.setspan("flow", op)
257 - self.generic_visit(node)
258 - def visit_SimpleAccess (self, node) :
259 - self.setspan("name", node.st[0])
260 - self.setspan("access", node)
261 - self.generic_visit(node)
262 - def visit_FlushAccess (self, node) :
263 - self.visit_SimpleAccess(node)
264 - def visit_SwapAccess (self, node) :
265 - self.visit_SimpleAccess(node)
266 - def escape (self, text) :
267 - return escape(text)
268 - def build (self, st) :
269 - # collect text skipped during parsing (blanks and comments)
270 - output = io.StringIO()
271 - if st.srow > self.row :
272 - for line in st.text.lexer.lines[self.row-1:st.srow-1] :
273 - output.write(line[self.col:])
274 - self.col = 0
275 - output.write(st.text.lexer.lines[st.srow-1][:st.scol])
276 - elif st.scol > self.col :
277 - output.write(st.text.lexer.lines[self.row-1][self.col:st.scol])
278 - # insert skipped text with comments rendering
279 - for line in output.getvalue().splitlines(True) :
280 - if "#" in line :
281 - left, right = line.split("#", 1)
282 - self.output.write("%s<span class=%r>%s</span>"
283 - % (self.escape(left),
284 - "comment",
285 - self.escape("#" + right)))
286 - else :
287 - self.output.write(self.escape(line))
288 - # adjust current position in source code
289 - self.row, self.col = st.srow, st.scol
290 - # close span for net declaration
291 - span = getattr(st, "span", Span())
292 - if "body" in (c.lower() for c in span.cls) :
293 - self.output.write("</span>")
294 - # generate <span ...> if necessary
295 - if span :
296 - self.output.write(str(span))
297 - # generate span for net declaration
298 - if (span.id or "").startswith("N") :
299 - self.output.write(str(self["P" + span.id]))
300 - # render tree or its children
301 - if len(st) :
302 - for child in st :
303 - # add span tags on special elements
304 - if not hasattr(child, "span") :
305 - if child.symbol == "NAME" :
306 - if child.text in keywords :
307 - self.setspan("kw", child)
308 - else :
309 - self.setspan("ident", child)
310 - elif child.symbol == "STRING" :
311 - self.setspan("string", child)
312 - elif child.symbol == "COLON" :
313 - self.setspan("kw", child)
314 - self.build(child)
315 - else :
316 - if st.symbol not in ("DEDENT", "ENDMARKER") :
317 - self.output.write(self.escape(st.text))
318 - self.row, self.col = st.erow, st.ecol
319 - # generate </span> if necessary
320 - if span :
321 - self.output.write("</span>")
322 - def html (self) :
323 - self.output = io.StringIO()
324 - self.indent, self.row, self.col = False, 1, 0
325 - self.build(self.tree.st)
326 - return "<pre class='abcd'>%s</pre>" % self.output.getvalue()
327 -
328 -def Tree () :
329 - return collections.defaultdict(Tree)
330 -
331 -class TreeInfo (object) :
332 - def __init__ (self, span, name) :
333 - self.span, self.name = span, name
334 - def __hash__ (self) :
335 - return hash(self.name)
336 - def __eq__ (self, other) :
337 - try :
338 - return self.name == other.name
339 - except :
340 - return False
341 - def __ne__ (self, other) :
342 - return not self.__eq__(other)
343 - def __iter__ (self) :
344 - yield self.span
345 - yield self.name
346 -
347 -_svgclean = [(re.compile(r, re.I), s) for r, s in
348 - [(r"<[?!][^>]*>\n*", ""),
349 - (r"<title>[^<>]*</title>\n*", ""),
350 - (r"<g [^<>]*></g>\n*", ""),
351 - ]]
352 -
353 -class Net2HTML (object) :
354 - def __init__ (self, net, gv, abcd) :
355 - self.gv = gv
356 - self.abcd = abcd
357 - self.tree = Tree()
358 - self.n2a = collections.defaultdict(set)
359 - self.n2t = {}
360 - snk = net.label("snakes")
361 - self.count = collections.defaultdict(int)
362 - for place in net.place() :
363 - nid = gv.nodemap[place.name]
364 - if place.status in (snk.entry, snk.internal, snk.exit) :
365 - for char, trans in ([("R", net.transition(t))
366 - for t in place.pre]
367 - + [("L", net.transition(t))
368 - for t in place.post]) :
369 - span = abcd[trans]
370 - self.n2a[nid].add(char + span.id)
371 - else :
372 - self.addtree(0, "buffer", place)
373 - for trans in net.transition() :
374 - self.addtree(10, "action", trans)
375 - def addtree (self, weight, kind, node) :
376 - nid = self.gv.nodemap[node.name]
377 - aid = self.abcd[node]
378 - tid = aid.copy(id=("T%X" % self.count[aid.id]) + aid.id,
379 - tree=[], abcd=[aid.id], net=[nid])
380 - self.count[aid.id] += 1
381 - aid.tree.add(tid.id)
382 - aid.net.add(nid)
383 - self.n2a[nid].add(aid.id)
384 - self.n2t[nid] = tid.id
385 - pos = self.tree
386 - path = node.label("path")
387 - try :
388 - inst = node.label("instances")
389 - except :
390 - inst = [None] * len(path)
391 - for name, (_, srow, scol, _, _) in zip(path, inst) :
392 - a = self.abcd["I", srow, scol]
393 - t = a.copy(id=("T%X" % self.count[a.id]) + a.id,
394 - tree=[], abcd=[a.id], net=[])
395 - self.count[a.id] += 1
396 - a.tree.add(t.id)
397 - pos = pos[((20, srow, scol), "instance", TreeInfo(t, name))]
398 - prefix = sum(len(p) for p in path) + len(path)
399 - srow, scol, _, _ = node.label("srcloc")
400 - pos[((weight, srow, scol), kind, (node, node.name[prefix:]))] = tid
401 - def _tree (self, tree, indent="") :
402 - yield indent + "<ul>"
403 - for (_, kind, data), child in sorted(tree.items()) :
404 - if kind == "instance" :
405 - yield indent + "<li>%s%s</span>" % tuple(data)
406 - for item in self._tree(child, indent + " ") :
407 - yield item
408 - yield indent + "</li>"
409 - else :
410 - node, name = data
411 - if kind == "buffer" :
412 - content = ("<span class='kw'>buffer</span> "
413 - "<span class='name'>%s</span> = "
414 - "<span class='content'>%s</span>"
415 - % (name, node.tokens))
416 - yield indent + "<li>%s%s</span></li>" % (child, content)
417 - elif kind == "action" :
418 - content = name
419 - yield (indent + "<li>%s%s</span><ul class='modes'>"
420 - + "</ul></li>") % (child, content)
421 - else :
422 - raise ValueError("unexpected data %r" % kind)
423 - yield indent + "</ul>"
424 - def html (self) :
425 - return template_tree % {"tree" : "\n".join(self._tree(self.tree))}
426 - def svg (self) :
427 - # load SVG file
428 - with tempfile.NamedTemporaryFile(suffix=".svg") as tmp :
429 - self.gv.render(tmp.name)
430 - with codecs.open(tmp.name, "r", "utf-8") as infile :
431 - svg = infile.read()
432 - for r, s in _svgclean :
433 - svg = r.sub(s, svg)
434 - for node, abcd in self.n2a.items() :
435 - abcd = ", ".join("#" + t for t in abcd)
436 - if node in self.n2t :
437 - svg = svg.replace(' id="%s" ' % node,
438 - ' id="%s" data-abcd="%s" data-tree="#%s" '
439 - % (node, abcd, self.n2t[node]))
440 - else :
441 - svg = svg.replace(' id="%s" ' % node,
442 - ' id="%s" data-abcd="%s" ' % (node, abcd))
443 - return u"<div class='petrinet'>%s</div>" % svg
444 -
445 -def build (abcd, node, net, gv, outfile, tpl=template_html, **args) :
446 - abcd = ABCD2HTML(node)
447 - pnet = Net2HTML(net, gv, abcd)
448 - d = {"filename" : node.st.filename,
449 - "css" : template_css,
450 - "jscode" : template_jscode,
451 - "headers" : template_headers,
452 - "abcd" : abcd.html(),
453 - "tree" : pnet.html(),
454 - "svg" : pnet.svg()}
455 - d.update(args)
456 - if tpl is not None and outfile :
457 - with codecs.open(outfile, "w", "utf-8") as out :
458 - out.write(tpl % d)
459 - return d
1 import sys, optparse, os.path, webbrowser 1 import sys, optparse, os.path, webbrowser
2 import pdb, traceback 2 import pdb, traceback
3 import snakes.plugins 3 import snakes.plugins
4 -from snakes.utils.abcd.build import Builder 4 +from snakes.utils.andy import CompilationError, DeclarationError
5 -from snakes.lang.abcd.parser import parse 5 +from snakes.utils.andy.simul import Simulator, AndySimulator
6 -from snakes.lang.pgen import ParseError 6 +from snakes.utils.andy.andy import andy2snakes
7 -from snakes.utils.abcd import CompilationError, DeclarationError
8 -from snakes.utils.abcd.simul import Simulator, ABCDSimulator
9 -from snakes.utils.abcd.checker import Checker
10 -from snakes.utils.abcd.html import build as html
11 from snakes.utils.simul.html import json 7 from snakes.utils.simul.html import json
12 8
13 ## 9 ##
...@@ -26,11 +22,11 @@ ERR_OUTPUT = 7 ...@@ -26,11 +22,11 @@ ERR_OUTPUT = 7
26 ERR_BUG = 255 22 ERR_BUG = 255
27 23
28 def log (message) : 24 def log (message) :
29 - sys.stdout.write("abcd: %s\n" % message.strip()) 25 + sys.stdout.write("andy: %s\n" % message.strip())
30 sys.stdout.flush() 26 sys.stdout.flush()
31 27
32 def err (message) : 28 def err (message) :
33 - sys.stderr.write("abcd: %s\n" % message.strip()) 29 + sys.stderr.write("andy: %s\n" % message.strip())
34 sys.stderr.flush() 30 sys.stderr.flush()
35 31
36 def die (code, message=None) : 32 def die (code, message=None) :
...@@ -66,7 +62,7 @@ def bug () : ...@@ -66,7 +62,7 @@ def bug () :
66 62
67 gv_engines = ("dot", "neato", "twopi", "circo", "fdp") 63 gv_engines = ("dot", "neato", "twopi", "circo", "fdp")
68 64
69 -opt = optparse.OptionParser(prog="abcd", 65 +opt = optparse.OptionParser(prog="andy",
70 usage="%prog [OPTION]... FILE") 66 usage="%prog [OPTION]... FILE")
71 opt.add_option("-l", "--load", 67 opt.add_option("-l", "--load",
72 dest="plugins", action="append", default=[], 68 dest="plugins", action="append", default=[],
...@@ -81,9 +77,6 @@ for engine in gv_engines : ...@@ -81,9 +77,6 @@ for engine in gv_engines :
81 dest="gv" + engine, action="store", default=None, 77 dest="gv" + engine, action="store", default=None,
82 help="draw net using '%s' (from GraphViz)" % engine, 78 help="draw net using '%s' (from GraphViz)" % engine,
83 metavar="OUTFILE") 79 metavar="OUTFILE")
84 -opt.add_option("-a", "--all-names",
85 - dest="allnames", action="store_true", default=False,
86 - help="draw control-flow places names (default: hide)")
87 opt.add_option("--debug", 80 opt.add_option("--debug",
88 dest="debug", action="store_true", default=False, 81 dest="debug", action="store_true", default=False,
89 help="launch debugger on compiler error (default: no)") 82 help="launch debugger on compiler error (default: no)")
...@@ -98,22 +91,13 @@ opt.add_option("--port", ...@@ -98,22 +91,13 @@ opt.add_option("--port",
98 dest="port", action="store", default=8000, type=int, 91 dest="port", action="store", default=8000, type=int,
99 help="port on which the simulator server runs", 92 help="port on which the simulator server runs",
100 metavar="PORT") 93 metavar="PORT")
101 -opt.add_option("-H", "--html",
102 - dest="html", action="store", default=None,
103 - help="save net as HTML",
104 - metavar="OUTFILE")
105 -opt.add_option("--check",
106 - dest="check", action="store_true", default=False,
107 - help="check assertions")
108 94
109 def getopts (args) : 95 def getopts (args) :
110 - global options, abcd, tmp 96 + global options, andy, tmp
111 (options, args) = opt.parse_args(args) 97 (options, args) = opt.parse_args(args)
112 plugins = [] 98 plugins = []
113 for p in options.plugins : 99 for p in options.plugins :
114 plugins.extend(t.strip() for t in p.split(",")) 100 plugins.extend(t.strip() for t in p.split(","))
115 - if "ops" not in options.plugins :
116 - plugins.append("ops")
117 if "labels" not in plugins : 101 if "labels" not in plugins :
118 plugins.append("labels") 102 plugins.append("labels")
119 for engine in gv_engines : 103 for engine in gv_engines :
...@@ -121,7 +105,7 @@ def getopts (args) : ...@@ -121,7 +105,7 @@ def getopts (args) :
121 if gvopt and "gv" not in plugins : 105 if gvopt and "gv" not in plugins :
122 plugins.append("gv") 106 plugins.append("gv")
123 break 107 break
124 - if (options.html or options.simul) and "gv" not in plugins : 108 + if (options.simul) and "gv" not in plugins :
125 plugins.append("gv") 109 plugins.append("gv")
126 options.plugins = plugins 110 options.plugins = plugins
127 if len(args) < 1 : 111 if len(args) < 1 :
...@@ -132,17 +116,13 @@ def getopts (args) : ...@@ -132,17 +116,13 @@ def getopts (args) :
132 err("more than one input file provided") 116 err("more than one input file provided")
133 opt.print_help() 117 opt.print_help()
134 die(ERR_ARG) 118 die(ERR_ARG)
135 - abcd = args[0] 119 + andy = args[0]
136 - if options.pnml == abcd : 120 + if options.pnml == andy :
137 err("input file also used as output (--pnml)") 121 err("input file also used as output (--pnml)")
138 opt.print_help() 122 opt.print_help()
139 die(ERR_ARG) 123 die(ERR_ARG)
140 - if options.html == abcd :
141 - err("input file also used as output (--html)")
142 - opt.print_help()
143 - die(ERR_ARG)
144 for engine in gv_engines : 124 for engine in gv_engines :
145 - if getattr(options, "gv%s" % engine) == abcd : 125 + if getattr(options, "gv%s" % engine) == andy :
146 err("input file also used as output (--%s)" % engine) 126 err("input file also used as output (--%s)" % engine)
147 opt.print_help() 127 opt.print_help()
148 die(ERR_ARG) 128 die(ERR_ARG)
...@@ -151,58 +131,9 @@ def getopts (args) : ...@@ -151,58 +131,9 @@ def getopts (args) :
151 ## drawing nets 131 ## drawing nets
152 ## 132 ##
153 133
154 -def place_attr (place, attr) :
155 - # fix color
156 - if place.status == snk.entry :
157 - attr["fillcolor"] = "green"
158 - elif place.status == snk.internal :
159 - pass
160 - elif place.status == snk.exit :
161 - attr["fillcolor"] = "orange"
162 - else :
163 - attr["fillcolor"] = "lightblue"
164 - # fix shape
165 - if (not options.allnames
166 - and place.status in (snk.entry, snk.internal, snk.exit)) :
167 - attr["shape"] = "circle"
168 - # render marking
169 - if place._check == snk.tBlackToken :
170 - count = len(place.tokens)
171 - if count == 0 :
172 - marking = " "
173 - elif count == 1 :
174 - marking = "&#8226;"
175 - else :
176 - marking = "%s&#8226;" % count
177 - else :
178 - marking = str(place.tokens)
179 - # node label
180 - if (options.allnames
181 - or place.status not in (snk.entry, snk.internal, snk.exit)) :
182 - attr["label"] = "%s\\n%s" % (place.name, marking)
183 - else :
184 - attr["label"] = "%s" % marking
185 -
186 -def trans_attr (trans, attr) :
187 - pass
188 -
189 -def arc_attr (label, attr) :
190 - if label == snk.Value(snk.dot) :
191 - del attr["label"]
192 - elif isinstance(label, snk.Test) :
193 - attr["arrowhead"] = "none"
194 - attr["label"] = " %s " % label._annotation
195 - elif isinstance(label, snk.Flush) :
196 - attr["arrowhead"] = "box"
197 - attr["label"] = " %s " % label._annotation
198 -
199 -
200 def draw (net, target, engine="dot") : 134 def draw (net, target, engine="dot") :
201 try : 135 try :
202 - return net.draw(target, engine=engine, 136 + return net.draw(target, engine=engine)
203 - place_attr=place_attr,
204 - trans_attr=trans_attr,
205 - arc_attr=arc_attr)
206 except : 137 except :
207 die(ERR_OUTPUT, str(sys.exc_info()[1])) 138 die(ERR_OUTPUT, str(sys.exc_info()[1]))
208 139
...@@ -222,49 +153,36 @@ def save_pnml (net, target) : ...@@ -222,49 +153,36 @@ def save_pnml (net, target) :
222 ## simulator (not standalone) 153 ## simulator (not standalone)
223 ## 154 ##
224 155
225 -def simulate (source, filename="<string>") : 156 +def simulate (entities, potential, obligatory, filename='<string>') :
226 global options, snk 157 global options, snk
227 getopts(["--simul", filename]) 158 getopts(["--simul", filename])
228 - node = parse(source, filename=filename)
229 snk = snakes.plugins.load(options.plugins, "snakes.nets", "snk") 159 snk = snakes.plugins.load(options.plugins, "snakes.nets", "snk")
230 - build = Builder(snk) 160 + net = andy2snakes(snk, entities, potential, obligatory)
231 - net = build.build(node)
232 net.label(srcfile=filename, snakes=snk) 161 net.label(srcfile=filename, snakes=snk)
233 - return ABCDSimulator(node, net, draw(net, None)) 162 + return AndySimulator(net)
234 163
235 ## 164 ##
236 ## main 165 ## main
237 ## 166 ##
238 167
239 -def main (args=sys.argv[1:], src=None) : 168 +def main (args=sys.argv[1:]) :
240 global options, snk 169 global options, snk
241 # get options 170 # get options
242 try: 171 try:
243 - if src is None : 172 + getopts(args)
244 - getopts(args)
245 - else :
246 - getopts(list(args) + ["<string>"])
247 except SystemExit : 173 except SystemExit :
248 raise 174 raise
249 except : 175 except :
250 die(ERR_OPT, str(sys.exc_info()[1])) 176 die(ERR_OPT, str(sys.exc_info()[1]))
251 - # read source 177 + # read andy spec
252 - if src is not None : 178 + try:
253 - source = src 179 + env = {}
254 - else : 180 + execfile(andy, env)
255 - try : 181 + del env['__builtins__']
256 - source = open(abcd).read() 182 + except:
257 - except : 183 + die(ERR_IO, "could not read input file %r" % andy)
258 - die(ERR_IO, "could not read input file %r" % abcd) 184 + # compile to net
259 - # parse 185 + dirname = os.path.dirname(andy)
260 - try :
261 - node = parse(source, filename=abcd)
262 - except ParseError :
263 - die(ERR_PARSE, str(sys.exc_info()[1]))
264 - except :
265 - bug()
266 - # compile
267 - dirname = os.path.dirname(abcd)
268 if dirname and dirname not in sys.path : 186 if dirname and dirname not in sys.path :
269 sys.path.append(dirname) 187 sys.path.append(dirname)
270 elif "." not in sys.path : 188 elif "." not in sys.path :
...@@ -273,14 +191,13 @@ def main (args=sys.argv[1:], src=None) : ...@@ -273,14 +191,13 @@ def main (args=sys.argv[1:], src=None) :
273 snk = snakes.plugins.load(options.plugins, "snakes.nets", "snk") 191 snk = snakes.plugins.load(options.plugins, "snakes.nets", "snk")
274 except : 192 except :
275 die(ERR_PLUGIN, str(sys.exc_info()[1])) 193 die(ERR_PLUGIN, str(sys.exc_info()[1]))
276 - build = Builder(snk) 194 +
277 - try : 195 + try:
278 - net = build.build(node) 196 + net = andy2snakes(snk, env['entities'], env['potential'],
279 - net.label(srcfile=abcd, snakes=snk) 197 + env['obligatory'])
280 - except (CompilationError, DeclarationError) : 198 + except:
281 - die(ERR_COMPILE, str(sys.exc_info()[1]))
282 - except :
283 bug() 199 bug()
200 +
284 # output 201 # output
285 if options.pnml : 202 if options.pnml :
286 save_pnml(net, options.pnml) 203 save_pnml(net, options.pnml)
...@@ -288,17 +205,10 @@ def main (args=sys.argv[1:], src=None) : ...@@ -288,17 +205,10 @@ def main (args=sys.argv[1:], src=None) :
288 target = getattr(options, "gv%s" % engine) 205 target = getattr(options, "gv%s" % engine)
289 if target : 206 if target :
290 draw(net, target, engine) 207 draw(net, target, engine)
291 - if options.html :
292 - try :
293 - html(abcd, node, net, draw(net, None), options.html)
294 - except :
295 - bug()
296 trace, lineno = [], None 208 trace, lineno = [], None
297 - if options.check :
298 - lineno, trace = Checker(net).run()
299 if options.simul : 209 if options.simul :
300 try : 210 try :
301 - simul = Simulator(node, net, draw(net, None), options.port) 211 + simul = Simulator(net, options.port)
302 except : 212 except :
303 bug() 213 bug()
304 simul.start() 214 simul.start()
......
1 <!DOCTYPE html> 1 <!DOCTYPE html>
2 <html> 2 <html>
3 - <head> 3 +<head>
4 - <link type="text/css" href="r/css/bootstrap-theme.css" rel="stylesheet"/> 4 + <link type="text/css" href="r/css/bootstrap-theme.css" rel="stylesheet"/>
5 - <link type="text/css" href="r/css/bootstrap.css" rel="stylesheet"/> 5 + <link type="text/css" href="r/css/bootstrap.css" rel="stylesheet"/>
6 - <link type="text/css" href="r/css/docs.css" rel="stylesheet"/> 6 + <link type="text/css" href="r/css/docs.css" rel="stylesheet"/>
7 - <link type="text/css" href="r/simulator.css" rel="stylesheet"/> 7 + <link type="text/css" href="r/simulator.css" rel="stylesheet"/>
8 - <link type="text/css" href="r/model.css" rel="stylesheet"/> 8 + <link type="text/css" href="r/model.css" rel="stylesheet"/>
9 - <script src="r/jquery.min.js"></script> 9 + <script src="r/jquery.min.js"></script>
10 - <script src="r/js/bootstrap.min.js"></script> 10 + <script src="r/js/bootstrap.min.js"></script>
11 - <script src="r/jquery.periodic.js"></script> 11 + <script src="r/jquery.periodic.js"></script>
12 - <script src="r/js/bootstrap.file-input.js"></script> 12 + <script src="r/js/bootstrap.file-input.js"></script>
13 - <script src="r/d3.min.js"></script> 13 + <script src="r/d3.min.js"></script>
14 - <script src="r/js/petri.js"></script> 14 + <script src="r/js/petri.js"></script>
15 - <script src="r/simulator.js"></script> 15 + <script src="r/simulator.js"></script>
16 - </head>
17 <style> 16 <style>
18 - path { 17 + path { stroke: steelblue;
19 - stroke: steelblue; 18 + stroke-width: 2;
20 - stroke-width: 2; 19 + fill: none; }
21 - fill: none; 20 + line { stroke: black; }
22 - } 21 + text { font-family: Arial;
23 - 22 + font-size: 9pt; }
24 - line {
25 - stroke: black;
26 - }
27 -
28 - text {
29 - font-family: Arial;
30 - font-size: 9pt;
31 - }
32 -
33 </style> 23 </style>
34 - <body> 24 +</head>
35 - 25 +<body>
36 <header class="navbar navbar-static-top"> 26 <header class="navbar navbar-static-top">
37 - <div class="container">
38 <nav class="navbar navbar-default" role="navigation"> 27 <nav class="navbar navbar-default" role="navigation">
39 <div class="container-fluid"> 28 <div class="container-fluid">
40 - <div class="navbar-header"><button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-6"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="#">Simulation SNAKES</a></div> 29 + <div class="navbar-header">
41 - <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-6"> 30 + <button type="button" class="navbar-toggle"
42 - <ul id="nav_sim" class="nav navbar-nav"> 31 + data-toggle="collapse"
43 - <li><a href="#" id="ui-reset">Reset Simulation</a></li> 32 + data-target="#bs-example-navbar-collapse-6">
44 - <li><a href="#" id="ui-quit">Stop Simulation</a></li> 33 + <span class="sr-only">Toggle navigation</span>
45 - <li><a href="#" id="ui-help">Help</a></li> 34 + </button>
46 - </ul> 35 + <a class="navbar-brand" href="#">Simulation SNAKES</a>
47 </div> 36 </div>
37 + <div class="collapse navbar-collapse"
38 + id="bs-example-navbar-collapse-6">
39 + <ul class="nav navbar-nav" id="nav_sim">
40 + <li><a id="ui-reset">Reset Simulation</a></li>
41 + <li><a id="ui-quit">Stop Simulation</a></li>
42 + <li><a id="ui-help">Help</a></li>
43 + </ul>
44 + </div><!-- /.navbar-collapse -->
48 </div> 45 </div>
49 </nav> 46 </nav>
50 - </div>
51 </header> 47 </header>
52 - <div class="container"> 48 + <!-- model to be simulated -->
53 - 49 + %(model)s
54 - %(model)s
55 50
56 - <div class="modal fade" id="about" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"> 51 + <!-- information about the simulator -->
57 - <div class="modal-dialog"> 52 + <div aria-hidden="true" aria-labelledby="myModalLabel" class="modal fade"
58 - <div class="modal-content"> 53 + id="about" role="dialog" tabindex="-1">
59 - <div class="modal-header"><button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button> 54 + <div class="modal-dialog">
60 - <h4 class="modal-title" id="myModalLabel">Petri Net</h4> 55 + <div class="modal-content">
61 - </div> 56 + <div class="modal-header">
62 - <div class="modal-body"> 57 + <button aria-hidden="true" class="close"
63 - <p><span class="title">ABCD simulator is part of the SNAKES toolkit</span><br /> (C) 2014 Franck Pommereau</p> 58 + data-dismiss="modal" type="button">x</button>
64 - <p><a href="http://www.ibisc.univ-evry.fr/~fpommereau/SNAKES" target="_blank">SNAKES homepage</a></p> 59 + <h4 class="modal-title" id="myModalLabel">Petri Net</h4>
65 - </div> 60 + </div>
66 - <div class="modal-footer"><button type="button" class="btn btn-default" data-dismiss="modal">Close</button></div> 61 + <div class="modal-body">
62 + <p>
63 + <span class="title">Andy simulator is part of the
64 + SNAKES toolkit</span><br />
65 + (C) 2014 Franck Pommereau
66 + </p>
67 + <p>
68 + <a href="http://www.ibisc.univ-evry.fr/~fpommereau/SNAKES"
69 + target="_blank">SNAKES homepage</a>
70 + </p>
71 + </div>
72 + <div class="modal-footer">
73 + <button class="btn btn-default" data-dismiss="modal"
74 + type="button">Close</button>
67 </div> 75 </div>
68 </div> 76 </div>
69 </div> 77 </div>
70 -<script> 78 + </div>
71 - $(document).ready(function(){ 79 + <script>
72 - $.simisc({ 80 + $(document).ready(function(){
73 - "nav":{ 81 + $.simisc({ "nav":{ "about": { "text": "About",
74 - "about": { 82 + "attr": { "id":"ui-about",
75 - "text": "About", 83 + "data-toggle": "modal",
76 - "attr": { 84 + "data-target": "#about"
77 - "id":"ui-about", 85 + } } },
78 - "data-toggle": "modal", 86 + "graph": { "color": { "y":"red",
79 - "data-target": "#about" 87 + "x":"blue" } } });
80 - } 88 + });
81 - }, 89 + </script>
82 - "net": {
83 - "text": "Petri Net",
84 - "attr": {
85 - "id":"ui-net",
86 - "data-toggle": "modal",
87 - "data-target": "#net"
88 - }
89 - }
90 - },
91 - "graph": {
92 - "activate": false
93 - }
94 - });
95 - });
96 -</script>
97 </body> 90 </body>
98 </html> 91 </html>
......
1 +<div class="container-fluid">
2 +<div class="row">
1 <div class="page-header"> 3 <div class="page-header">
2 - <h1><tt>%(filename)s</tt> <small> powered by Franck</small></h1> 4 + <h1><tt>Andy Simulator</tt> <small> powered by Franck</small></h1>
5 +</div>
3 </div> 6 </div>
4 -<div class="row">
5 - <div class="col-md-3">
6 7
8 +<div class="row">
9 + <div class="col-md-4">
7 <div class="row"> 10 <div class="row">
8 <h3>Player</h3> 11 <h3>Player</h3>
9 - <div id="player"></div> 12 + <div id="player">&nbsp;</div>
10 </div> 13 </div>
11 - </div>
12 -</div>
13 -<div id="model" class="row">
14 - <div class="col-md-6">
15 <div class="row"> 14 <div class="row">
16 - <h3>ABCD</h3> 15 + <h3>Modes</h3>
17 - <div class="abcd">%(abcd)s</div> 16 + <div id="modes">&nbsp;</div>
18 </div> 17 </div>
19 18
20 - </div>
21 - <div class=col-md-6>
22 <div class="row"> 19 <div class="row">
23 - <h3>Tree</h3> 20 + <h3>Command Panel</h3>
24 - <div class="tree">%(tree)s</div> 21 + <div id="Command_center">&nbsp;</div>
25 </div> 22 </div>
26 </div> 23 </div>
27 24
28 - <div class="col-md-12"> 25 + <div class="col-md-8">
29 - <div id="trace_zone"></div> 26 + <div class="row">
27 + <h3>Net Graph</h3>
28 + <div id="graph">&nbsp;</div>
29 + </div>
30 </div> 30 </div>
31 </div> 31 </div>
32 32
33 -<div class="modal fade" id="net" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"> 33 +<div class="row">
34 - <div class="modal-dialog" style="width:auto;"> 34 + <div class="col-md-12">
35 - <div class="modal-content" style="overflow: scroll;"> 35 + <div id="trace_zone">&nbsp;</div>
36 - %(net)s
37 - </div>
38 </div> 36 </div>
39 -</div>
...\ No newline at end of file ...\ No newline at end of file
37 +</div>
38 +</div>
......
1 from snakes.utils.simul import BaseSimulator, BaseHTTPSimulator 1 from snakes.utils.simul import BaseSimulator, BaseHTTPSimulator
2 -import snakes.utils.abcd.html as html
3 2
4 -class ABCDSimulator (BaseSimulator) : 3 +class AndySimulator (BaseSimulator) :
5 - def __init__ (self, node, net, gv) :
6 - BaseSimulator.__init__(self, net)
7 - a2html = html.ABCD2HTML(node)
8 - n2html = html.Net2HTML(net, gv, a2html)
9 - self.info = {"filename" : node.st.filename,
10 - "abcd" : a2html.html(),
11 - "tree" : n2html.html(),
12 - "net" : n2html.svg()}
13 - self.tree = {}
14 - for node in net.node() :
15 - nid = gv.nodemap[node.name]
16 - if nid in n2html.n2t :
17 - self.tree[node.name] = "#" + n2html.n2t[nid]
18 - self.places = [place.name for place in net.place()
19 - if place.name in self.tree]
20 - self.abcd = {}
21 - self.transid = []
22 - for trans in net.transition() :
23 - nid = gv.nodemap[trans.name]
24 - self.transid.append(self.tree[trans.name])
25 - if nid in n2html.n2a :
26 - self.abcd[trans.name] = ", ".join("#" + i for i in
27 - n2html.n2a[nid])
28 - def init (self, state=-1) :
29 - res = BaseSimulator.init(self, state)
30 - res.update(self.info)
31 - res["help"] = self.init_help()
32 - return res
33 - def init_help (self) :
34 - help = BaseSimulator.init_help(self)
35 - help.update({
36 - "#model .abcd" : {
37 - "title" : "Source",
38 - "content" : "ABCD source code"
39 - },
40 - "#model .tree" : {
41 - "title" : "State",
42 - "content" : "hierarchy of ABCD objects",
43 - },
44 - "#model .petrinet" : {
45 - "title" : "Net",
46 - "content" : "Petri nets semantics"
47 - }})
48 - return help
49 def getstate (self, state) : 4 def getstate (self, state) :
5 + ret = BaseSimulator.getstate(self, state)
50 marking = self.states[state] 6 marking = self.states[state]
51 - modes = dict((t, []) for t in self.transid) 7 + ret["variables"] = dict((place, tokens.items()[0])
52 - for i, (trans, mode) in enumerate(marking.modes) : 8 + for place, tokens in marking.items())
53 - modes[self.tree[trans.name]].append({"state" : state, 9 + ret["groups"] = ["timed", "even", "odd"]
54 - "mode" : i, 10 + modes = []
55 - "html" : str(mode)}) 11 + for i, (trans, binding) in enumerate(marking.modes) :
56 - return {"id" : state, 12 + if (state + i) % 5 == 0 :
57 - "states" : 13 + groups = ["timed"]
58 - [{"do" : "dropclass", 14 + else :
59 - "select" : "#model .active", 15 + groups = []
60 - "class" : "active"}] 16 + modes.append(
61 - + [{"do" : "addclass", 17 + {"state" : state,
62 - "select" : self.abcd[trans.name], 18 + "mode" : i,
63 - "class" : "active"} for trans, mode in marking.modes] 19 + "html" : "%s (%s)" % (trans.name[7:], binding),
64 - + [{"do" : "addclass", 20 + "groups" : groups + ["odd" if (state % 2) else "even"]
65 - "select" : self.tree[trans.name], 21 + })
66 - "class" : "active"} for trans, mode in marking.modes] 22 + ret["modes"] = [{"select": "#modes", "items": modes}]
67 - + [{"do" : "settext", 23 + return ret
68 - "select" : "%s .content" % self.tree[place], 24 +
69 - "text" : "{}"} for place in self.places 25 +#class Simulator (BaseHTTPSimulator) :
70 - if place not in marking] 26 +# def __init__ (self, **system) :
71 - + [{"do" : "settext", 27 +# simul = AndySimulator(**system)
72 - "select" : "%s .content" % self.tree[place], 28 +# BaseHTTPSimulator.__init__(self, simulator=simul)
73 - "text" : str(marking[place])} for place in marking
74 - if place in self.tree],
75 - "modes" : [{"select" : "%s + .modes" % trans,
76 - "items" : items}
77 - for trans, items in modes.items()],
78 - }
79 29
80 class Simulator (BaseHTTPSimulator) : 30 class Simulator (BaseHTTPSimulator) :
81 - def __init__ (self, node, net, gv, port) : 31 + def __init__ (self, net, port) :
82 - simul = ABCDSimulator(node, net, gv) 32 + simul = AndySimulator(net)
83 BaseHTTPSimulator.__init__(self, net, simulator=simul, port=port) 33 BaseHTTPSimulator.__init__(self, net, simulator=simul, port=port)
84 - def init_model (self) : 34 +# def init_model (self) :
85 - return self.res["model.html"] % self.simul.info 35 +# return self.res["model.html"] % self.simul.info
86 - def init_ui (self) : 36 +# def init_ui (self) :
87 - return BaseHTTPSimulator.init_ui(self)[:-1] + [{ 37 +# return BaseHTTPSimulator.init_ui(self)[:-1] + [{
88 - "label" : "Show net", 38 +# "label" : "Show net",
89 - "id" : "ui-shownet", 39 +# "id" : "ui-shownet",
90 - "href" : "#", 40 +# "href" : "#",
91 - "script" : "dialog($('#model .petrinet').html())" 41 +# "script" : "dialog($('#model .petrinet').html())"
92 - }] 42 +# }]
43 +
......
1 -from snakes.lang.abcd.parser import ast
2 -
3 -class NodeCopier (ast.NodeTransformer) :
4 - def copy (self, node, **replace) :
5 - args = {}
6 - for name in node._fields + node._attributes :
7 - old = getattr(node, name, None)
8 - if name in replace :
9 - new = replace[name]
10 - elif isinstance(old, list):
11 - new = []
12 - for val in old :
13 - if isinstance(val, ast.AST) :
14 - new.append(self.visit(val))
15 - else :
16 - new.append(val)
17 - elif isinstance(old, ast.AST):
18 - new = self.visit(old)
19 - else :
20 - new = old
21 - args[name] = new
22 - if hasattr(node, "st") :
23 - args["st"] = node.st
24 - return node.__class__(**args)
25 - def generic_visit (self, node) :
26 - return self.copy(node)
27 -
28 -class ArgsBinder (NodeCopier) :
29 - def __init__ (self, args, buffers, nets, tasks) :
30 - NodeCopier.__init__(self)
31 - self.args = args
32 - self.buffers = buffers
33 - self.nets = nets
34 - self.tasks = tasks
35 - def visit_Name (self, node) :
36 - if node.id in self.args :
37 - return self.copy(self.args[node.id])
38 - else :
39 - return self.copy(node)
40 - def visit_Instance (self, node) :
41 - if node.net in self.nets :
42 - return self.copy(node, net=self.nets[node.net])
43 - else :
44 - return self.copy(node)
45 - def _visit_access (self, node) :
46 - if node.buffer in self.buffers :
47 - return self.copy(node, buffer=self.buffers[node.buffer])
48 - else :
49 - return self.copy(node)
50 - def visit_SimpleAccess (self, node) :
51 - return self._visit_access(node)
52 - def visit_FlushAccess (self, node) :
53 - return self._visit_access(node)
54 - def visit_SwapAccess (self, node) :
55 - return self._visit_access(node)
56 - def _visit_task (self, node) :
57 - if node.net in self.tasks :
58 - return self.copy(node, net=self.tasks[node.net])
59 - else :
60 - return self.copy(node)
61 - def visit_Spawn (self, node) :
62 - return self._visit_task(node)
63 - def visit_Wait (self, node) :
64 - return self._visit_task(node)
65 - def visit_Suspend (self, node) :
66 - return self._visit_task(node)
67 - def visit_Resume (self, node) :
68 - return self._visit_task(node)
69 - def visit_AbcdNet (self, node) :
70 - args = self.args.copy()
71 - buffers = self.buffers.copy()
72 - nets = self.nets.copy()
73 - tasks = self.tasks.copy()
74 - netargs = ([a.arg for a in node.args.args + node.args.kwonlyargs]
75 - + [node.args.vararg, node.args.kwarg])
76 - copy = True
77 - for a in netargs :
78 - for d in (args, buffers, nets, tasks) :
79 - if a in d :
80 - del d[a]
81 - copy = False
82 - if copy :
83 - return self.copy(node)
84 - else :
85 - return self.__class__(args, buffers, nets, tasks).visit(node)
86 -
87 -if __name__ == "__main__" :
88 - import doctest
89 - doctest.testmod()