Franck Pommereau

API doc extraction

Showing 102 changed files with 4479 additions and 0 deletions
1 +syntax: glob
2 +
3 +doc/api/*
4 +dist/*
5 +dput.sh
6 +*.pyc
7 +*~
8 +.gone
9 +,*
10 +*.class
1 +abcd crash on [foo>>(s), foo<<(s+s)]
2 +[foo(x,y,z)] creates a multi-arc instead of a tuple
3 +
4 +abcd substitues for loops variables:
5 +net Foo (x) :
6 + buffer b : int = [x for x in range(4)]
7 + ^ ^
8 + substituted (should not)
9 +
10 +errors during expressions evaluation are directly sent to user, should be wrapper to indicate this is a model error. And should be catched in abcd --simul/check
1 +recursive-include doc *
2 +include *
1 +all:
2 + @echo "Commands:"
3 + @echo " release prepare source for release"
4 + @echo " tgz build a source tarball"
5 + @echo " doc build API documentation"
6 + @echo " dput build and upload Ubuntu packages"
7 + @echo " clean delete some garbage files"
8 + @echo " test run tests through supported Python implementations"
9 + @echo " next-deb increments debian/VERSION"
10 + @echo " next-ppa increments debian/PPA"
11 + @echo " lang build generated files in snakes/lang"
12 + @echo " emacs compile Emacs files"
13 +
14 +committed:
15 + hg summary|grep -q '^commit: (clean)$$'
16 +
17 +next-deb:
18 + echo 1 > debian/PPA
19 + echo $$((1+$$(cat debian/VERSION))) > debian/VERSION
20 +
21 +emacs:
22 + emacs -batch -f batch-byte-compile utils/abcd-mode.el
23 +
24 +next-ppa:
25 + echo $$((1+$$(cat debian/PPA))) > debian/PPA
26 +
27 +release: committed test doc tgz
28 + hg tag version-$$(cat VERSION)
29 + echo 1 > debian/PPA
30 + echo 1 > debian/VERSION
31 + hg commit -m "version $$(cat VERSION)"
32 + hg push
33 +
34 +lang:
35 + python mklang.py
36 +
37 +tgz: committed
38 + hg archive snakes-$$(cat VERSION)-$$(cat debian/VERSION)
39 + cd snakes-$$(cat VERSION)-$$(cat debian/VERSION) && make doc
40 + tar cf snakes-$$(cat VERSION)-$$(cat debian/VERSION).tar snakes-$$(cat VERSION)-$$(cat debian/VERSION)
41 + rm -rf snakes-$$(cat VERSION)-$$(cat debian/VERSION)
42 + gzip -9 snakes-$$(cat VERSION)-$$(cat debian/VERSION).tar
43 + gpg --armor --sign --detach-sig snakes-$$(cat VERSION)-$$(cat debian/VERSION).tar.gz
44 +
45 +doc: snakes/*.py snakes/plugins/*.py snakes/utils/*.py snakes/lang/*.py
46 + make -C doc
47 +
48 +dput.sh: VERSION debian/*
49 + python mkdeb.py
50 +
51 +dput: committed dput.sh
52 + sh dput.sh
53 +
54 +clean:
55 + rm -f $$(find . -name ",*")
56 + rm -f $$(find . -name "*.pyc")
57 + rm -f $$(find . -name "*~")
58 + rm -f $$(find . -name "*.class")
59 + rm -rf $$(find . -type d -name __pycache__)
60 +
61 +test:
62 + python2.5 test.py
63 + python2.6 test.py
64 + python2.7 test.py
65 + python3 test.py
66 + unladen test.py
67 + pypy test.py
68 + spypy test.py
69 + stackless test.py
70 + jython test.py
1 + + emacs mode for ABCD
2 + ! fixex nodes merge in plugin labels
3 + ! fixed nets.MultiArc.flow (thanks to Jan Ciger's report)
4 +
5 +version 0.9.13 (Fri Jul 16 17:01:22 CEST 2010):
6 + + added inhibitor arcs
7 + + added Ubuntu Lucid (10.04) package
8 + ! fixed data.WordSet.fresh when base is used
9 + ! fixed reduce(xor, []) is some __hash__ methods
10 + + added PetriNet.layout method in snakes.plugins.gv
11 +
12 +version 0.9.12 (Thu Apr 1 19:42:33 CEST 2010):
13 + + removed PyGraphviz dependency (layout method supressed temporarily)
14 + + now compatible with PyPy (1.2), Unladen-Swallow and Jython (2.5.1)
15 + ! fixed snakes.plugins.clusters.rename_node
16 + ! fixed snakes.nets.Flush.flow
17 + ! fixed an uncaught exception in snakes.data.MultiSet.__eq__
18 + and snakes.data.Symbol.__eq__
19 + ! hopefully fixed LALR built in ABCD compiler
20 + ! fixed hash-related issues
21 + * moved PLY stuff to snakes.utils.abcd
22 + * snakes.compyler has been completely replaced (PLY dependency removed)
23 +
24 +version 0.9.11 (Thu Mar 25 19:32:31 CET 2010):
25 + ! fixed various doctests
26 + ! fixed issues with attributes locking
27 + ! fixed issues related to missing __hash__ methods
28 + ! fixed renaming a node to itself in ABCD
29 + + added snakes.nets.Evaluator.__contains__
30 + + added base argument to snakes.data.WordSet
31 + + added option --symbols to ABCD compiler
32 + + added snakes.data.Symbol
33 + + added net instances naming in ABCD
34 + + added logo
35 + + added let function to update bindings from expressions
36 + + added snakes.data.Subtitution.__setitem__
37 +
38 +version 0.9.10 (Fri Jun 19 13:32:45 CEST 2009):
39 + ! fixed inconstent hashing on clusters
40 + ! fixed mutability of hashed multisets
41 + ! fixed snakes.nets.Tuple.mode
42 +
43 +version 0.9.9 (Tue, 19 May 2009 15:00:00 +0100):
44 + + added mkdeb.py to build deb packages for multiple distributions
45 + + ported to Python 2.6
46 +
47 +version 0.9.8 (lun, 23 mar 2009 17:30:34 (CET)):
48 + + added graph_attr option to snakes.plugins.gv.StateGraph
49 + * plugin gv now draws partially constructed marking graphs
50 + ! fixed expression compilation in present of net parameters in ABCD
51 + compiler
52 + ! fixed flush arcs binding
53 + * plugin lashdata has been removed because its too experimental
54 + * merged plugin decorators into a single one
55 +
56 +version 0.9.7 (Tue, 20 Jan 2009 13:04:15 +0100):
57 + ! fixed sharing of globals between net components
58 + ! fixed loading of PNML when some plugins fail to load
59 + + added cpp option to abcd
60 + + added some docstrings and doctests
61 + ! fixed sharing of globals between net components
62 +
63 +version 0.9.6 (Fri, 28 Nov 2008 15:22:27 +0100):
64 + + added doc for ABCD
65 + ! fixed False and True handling in ABCD compiler
66 + + added cross product types to ABCD
67 +
68 +version 0.9.5 (Wed, 19 Nov 2008 21:42:05 +0100):
69 + + added distutils setup.py
70 + * strip PNML data before decoding (work around invalid XML)
71 + ! fixed Multiset.__pnmlload__ on iterable values
72 +
73 +version 0.9.4 (mar, 28 oct 2008 12:28:02 (UTC+0100)):
74 + ! fixed nets.Value.__eq__, __ne__ and __hash__
75 + ! fixed nets.Token.__repr__
76 + + added Flush arcs
77 + ! fixed nets.Tuple.bind
78 + ! fixed PNML dump/load of subclasses
79 + ! fixed nets.PetriNet.merge_* in the presence of Tuple arcs
80 + ! fixed plugins.clusters.Cluster.path
81 + ! fixed plugins.status.PetriNet.__pnmlload__
82 + ! fixed ABCD lexer
83 + + improved ABCD compiler with parametric nets, Python declarations
84 + ! fixed black token values in ABCD arcs and flush
85 + + ABCD compiler launches pdb.post_mortem when an error occurs in
86 + + added TCP mode to query plugin debug mode
87 + * removed dependency to epydoc in snakes.typing
88 + + updated PNML doc
89 + + added a producer/consumer ABCD example
90 +
91 +version 0.9.3 (lun, 29 sep 2008 08:04:55 (CEST)):
92 + ! fixed a bug in place pnml loading
93 + ! fixed wrong association of pnml tags to classes
94 + + improved query and associated programs, added documentation
95 + * improved loading of PNML files with plugins
96 + * PNML tag <snakes> can only occur once as a child of <pnml>
97 + + abcd compiler adds many structural information to PNML (including
98 + + test.py checks is snakes.version is correct AST if asked)
99 + + query plugins now has two verbosity levels
100 + + added snakes.compyler.Tree.__pnmldump__()
101 +
102 +version 0.9.2
103 + + added query plugin and demon client/server programs
104 + ! various small bugs fixed
105 + + improved PNML serialisation of standard objects
106 + + snakes.plugins.load puts new module in caller's environment
107 + ! fixed snakes.pnml.Tree.update
108 + * Substitution.image() returns a set
109 + + added apix.py
110 + ! PNML export empty arcs fixed
111 + ! fixed broken abcd.py
112 + * updated abcd.py so it uses gv
113 + * improved clustering efficiency
114 +
115 +version 0.9.1
116 + + added plugin gv to replace graphviz
117 + + added plugin clusters to manage clusters of nodes
118 + + updated plugins ops so it builds clusters
119 + * the plugin posops is deprecated since gv does the work much better
120 +
121 +version 0.9
122 + * dropped compatibilty with Python 2.4
123 + + finished pnml
124 + * the compyler module has been completely replaced
125 +
126 +Changes in 0.8.4 (06.09.2007 11:30:21):
127 + + updated the tutorial
128 +
129 +Changes in 0.8.3 (29.06.2007 11:57:39):
130 + + snakes.plugins.graphivz: added options to control the layout
131 + + snakes.plugins.graphviz: improved the rendering
132 + + updated the tutorial
133 +
134 +Changes in 0.8.2 (22.06.2007 13:09:02):
135 + + snakes.plugins.ops: added a name hiding operator (PetriNet.__div__)
136 + ! fixed several copy/clone problems
137 +
138 +Changes in 0.8.1 (20.06.2007 10:18:17):
139 + * updated tutorial
140 + + snakes.plugins.pos: the position of a node can be redefined when
141 + ! snakes.plugins.pos: accept float positions when loading from pnml
142 +
143 +Changes in 0.8 (19.06.2007 17:19:19): First public release.
1 +SNAKES is the Net Algebra Kit for Editors and Simulators
2 +========================================================
3 +
4 +////////////////////////////////////////////////////////////////
5 +This file is formatted in order to be processed by AsciiDoc
6 +(http://www.methods.co.nz/asciidoc). It will be more comfortable
7 +to render it or to read the HTML version available at:
8 +http://www.univ-paris12.fr/pommereau/soft/snakes/index.html
9 +////////////////////////////////////////////////////////////////
10 +
11 +SNAKES is a Python library that provides all then necessary to define
12 +and execute many sorts of Petri nets, in particular those of the PBC
13 +and M-nets family. Its main aim is to be a general Petri net library,
14 +being able to cope with most Petri nets models, and providing the
15 +researcher with a tool to quickly prototype its new ideas. SNAKES
16 +should be suitable to provide the data model for editors or
17 +simulators; actually, any editor that use SNAKES may also be a
18 +simulator as SNAKES can execute any net.
19 +
20 +A key feature of SNAKES is the ability to use arbitrary Python objects
21 +as tokens and arbitrary Python expressions in many points, for
22 +instance in transitions guards or arcs outgoing of transitions. This
23 +is what makes SNAKES that general. This relies on the capability of
24 +Python to run dynamically provided Python code (the $eval$ function).
25 +This feature may not be efficient enough for model-checking: speed is
26 +the price to pay for the wide generality. However, in the case of a
27 +new model, SNAKES may happen to be the only available tool.
28 +
29 +Another important feature of SNAKES is the plugin system that allows
30 +to extend the features and work with specialised classes of Petri
31 +nets. Currently, the following plugins are provided:
32 +
33 +pos:: adds to nodes the capability of holding their position. Nodes
34 +can be moved or shifted, Petri nets can be shifted globally and their
35 +bounding box can be computed.
36 +
37 +gv:: adds a method to draw a Petri net or a state graph using the tool
38 +http://www.graphviz.org[GraphViz] (through the Python binding
39 +http://networkx.lanl.gov/wiki/pygraphviz[PyGraphViz]). This module
40 +replaces the previous plugin called _graphviz_ and provides more
41 +flexibility and security, _graphviz_ is still provided but deprecated.
42 +
43 +status:: extends the Petri net model by adding status to the nodes.
44 +This is similar to what is used in the models of the PBC or Mnets
45 +family. Nodes can then merged automatically according to their status.
46 +
47 +ops:: this plugins defines control flow operations on Petri nets
48 +usually found in the PBC and Mnets family. Nets can be composed in
49 +parallel, sequence, choice and iteration. These operations rely on the
50 +places status.
51 +
52 +labels:: allows to add arbitrary labels to most objects (places,
53 +transitions, nets, ...)
54 +
55 +posops:: combines the features of pos and ops plugins: the control
56 +flow operations are modified in order to rearrange the nodes position
57 +in order to provide well shaped nets. This plugin is deprecated
58 +because the new _gv_ does the work much better.
59 +
60 +synchro:: it defines the label-based transition synchronisation
61 +defined in the Mnets model.
62 +
63 +// export:: allows to save Petri nets objects in the format of the tools
64 +// http://pep.sourceforge.net[PEP], http://helena.cnam.fr[Helena] and
65 +// http://maria[Maria]. http://pnml[PNML] is also supported as it is
66 +// built-in SNAKES.
67 +
68 +lashdata:: allows to define data that is not handled in the places of
69 +the Petri net but stored instead in the special structures handled by
70 +the http://www.montefiore.ulg.ac.be/~boigelot/research/lash/[library
71 +Lash]. This allows in particular to aggregate possibly infinite states
72 +into one meta-state.
73 +
74 +clusters:: this is an auxiliary plugin that allows to group nodes in a
75 +Petri net. This feature is used by _ops_ in order to record how a net
76 +is constructed, which is exploited by _gv_ in order to build a nice
77 +layout of composed nets.
78 +
79 +
80 +Getting SNAKES and installing it
81 +--------------------------------
82 +
83 +Download http://www.univ-paris12.fr/lacl/pommereau/soft/snakes/snakes-{VERSION}.tar.gz[$snakes-{VERSION}.tar.gz$]
84 +({sys:../stat snakes-{VERSION}.tar.gz})
85 +
86 +To install SNAKES, uncompress the archive and copy the directory
87 +snakes in a location where Python can find it (_i.e._, in a directory
88 +listed in your $PYTHONPATH$ environment variable).
89 +
90 +SNAKES should work with a Python version at least 2.5 but will _not_
91 +work for an older version. Optionally, you may want to install
92 +additional software required by some plugins:
93 +
94 +gv:: depends on http://www.graphviz.org[GraphViz] and its Python
95 + binding http://networkx.lanl.gov/wiki/pygraphviz[PyGraphViz]. The
96 + plugin _graphviz_ depends on GraphViz only but is now deprecated.
97 +
98 +lashdata:: requires
99 + http://www.montefiore.ulg.ac.be/~boigelot/research/lash[Lash] and
100 + the
101 + http://www.univ-paris12.fr/lacl/pommereau/soft/index.html#PyLash[Python
102 + Lash binding].
103 +
104 +[NOTE]
105 +=====================
106 +(C) 2007 Franck Pommereau <pommereau@univ-paris12.fr>
107 +
108 +This library is free software; you can redistribute it and/or modify
109 +it under the terms of the GNU Lesser General Public License as
110 +published by the Free Software Foundation; either version 2.1 of the
111 +License, or (at your option) any later version.
112 +
113 +This library is distributed in the hope that it will be useful, but
114 +WITHOUT ANY WARRANTY; without even the implied warranty of
115 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
116 +Lesser General Public License for more details.
117 +
118 +You should have received a copy of the GNU Lesser General Public
119 +License along with this library; if not, write to the Free Software
120 +Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
121 +USA
122 +=====================
123 +
124 +
125 +Contact
126 +-------
127 +
128 +Please feel free to send me comments, questions, bug reports or
129 +contributions by mailto:pommereau@univ-paris12.fr[email].
130 +
131 +If you wish to be notified of the new releases of SNAKES, please
132 +register at the http://freshmeat.net/projects/snakes[FreshMeat page].
133 +
134 +You may contribute to SNAKES by either send patches by email, or by
135 +using the https://launchpad.net/snakes[SNAKES Launchpad page].
136 +
137 +
138 +Documentation
139 +-------------
140 +
141 +A good starting point may be the link:tutorial.html[tutorial]. Then,
142 +you may find the link:api/index.html[API reference manual] useful, it
143 +documents all the API and gives number of examples of how to use the
144 +various classes and functions.
145 +
146 +If you do not program Python, you can learn it in a few hours thanks
147 +to the very good http://docs.python.org/tut/tut.html[Python tutorial].
148 +
149 +In order to know more about the PBC and M-nets family or the Petri net
150 +compositions defined in the plugins, you may read papers from
151 +http://www.univ-paris12.fr/lacl/pommereau/publis[my publications page]
152 +(in particular those with _calculus_ in the title).
1 +* add name to transitions, eg, [buff-(x) as name]
2 + make it consistent with instance names?
3 +* zero test/inhibitor arc
4 +! parameter and global buffer with same names => parameter ignored
5 +! accept net instances with too much parameters
1 +0.9.16
1 +#!/usr/bin/env python
2 +import snakes.utils.abcd.main as abcdmain
3 +abcdmain.main()
1 +#!/usr/bin/env python
2 +import socket, sys, readline
3 +from snakes.pnml import dumps, loads
4 +from snakes.plugins.query import Query
5 +
6 +env = {}
7 +
8 +def public (fun) :
9 + env[fun.__name__] = fun
10 + return fun
11 +
12 +@public
13 +def set (*larg, **karg) :
14 + """set(name, value) -> None
15 + assign value (object) to name (str) on the server"""
16 + return Query("set", *larg, **karg)
17 +
18 +@public
19 +def get (*larg, **karg) :
20 + """get(name) -> object
21 + return the last value assigned to name (str)"""
22 + return Query("get", *larg, **karg)
23 +
24 +@public
25 +def delete (*larg, **karg) :
26 + """delete(name) -> None
27 + discard name (str)"""
28 + return Query("del", *larg, **karg)
29 +
30 +@public
31 +def call (*larg, **karg) :
32 + """call(obj, ...) -> object
33 + call obj (str or result from another call) with the additional arguments
34 + return whatever the called object returns"""
35 + return Query("call", *larg, **karg)
36 +
37 +@public
38 +def help (command=None) :
39 + """help(command) -> None
40 + print help about command, if no command is given, list available commands"""
41 + if command is None:
42 + print "commands:", ", ".join(repr(cmd) for cmd in env
43 + if not cmd.startswith("_"))
44 + print " type 'help(cmd)' to ge help about a command"
45 + elif command in env :
46 + print env[command].__doc__
47 + elif command.__name__ in env :
48 + print command.__doc__
49 + else :
50 + print "unknown command %r" % command
51 +
52 +@public
53 +def quit () :
54 + """quit() -> None
55 + terminate the client"""
56 + print "bye"
57 + sys.exit(0)
58 +
59 +@public
60 +def load (path) :
61 + """net(path) -> object
62 + load a PNML file from path (str) and return the object is represents"""
63 + return loads(open(path).read())
64 +
65 +@public
66 +def show (query) :
67 + """show(obj) -> None
68 + show the PNML representation of obj (object), for instance of a query"""
69 + print dumps(query)
70 +
71 +_verbose = False
72 +
73 +@public
74 +def verbose (state=None) :
75 + """verbose(state) -> None
76 + turn on (state=True), off (state=False) or toggle (state not
77 + given) the printing of queries before they are sent to the
78 + server"""
79 + global _verbose
80 + if state is None :
81 + _verbose = not _verbose
82 + else :
83 + _verbose = state
84 + if _verbose :
85 + print "dump of queries enabled"
86 + else :
87 + print "dump of queries disabled"
88 +
89 +try :
90 + if sys.argv[1] in ("-t", "--tcp") :
91 + proto = "TCP"
92 + del sys.argv[1]
93 + else :
94 + proto = "UDP"
95 + host, port = sys.argv[1:]
96 + port = int(port)
97 +except :
98 + print >>sys.stderr, "Usage: snkc [--tcp] HOST PORT"
99 + sys.exit(1)
100 +
101 +sock = None
102 +
103 +def sendto (data, address) :
104 + global sock
105 + if proto == "UDP" :
106 + if sock is None :
107 + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
108 + sock.settimeout(2)
109 + sock.sendto(data, address)
110 + else :
111 + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
112 + sock.settimeout(2)
113 + sock.connect(address)
114 + sock.send(data)
115 +
116 +def recvfrom (size) :
117 + global sock
118 + if proto == "UDP" :
119 + data, address = sock.recvfrom(size)
120 + else :
121 + parts = []
122 + while True :
123 + parts.append(sock.recv(size))
124 + if len(parts[-1]) < size :
125 + break
126 + address = sock.getpeername()
127 + sock.close()
128 + data = "".join(parts)
129 + return data, address
130 +
131 +while True :
132 + try :
133 + data = raw_input("? ")
134 + q = eval(data.strip(), env)
135 + except (EOFError, KeyboardInterrupt) :
136 + quit()
137 + except SystemExit :
138 + raise
139 + except Exception, e :
140 + print "query error:", e
141 + continue
142 + if q is not None :
143 + q = dumps(q)
144 + if _verbose :
145 + print "# query to %s:%u" % (host, port)
146 + print q
147 + sendto(q, (host, port))
148 + try :
149 + data, address = recvfrom(2**20)
150 + if _verbose :
151 + print "# answer from %s:%u" % address
152 + print data.strip()
153 + except socket.timeout :
154 + print "# no answer received (timeout)"
155 + print
1 +#!/usr/bin/env python
2 +import sys
3 +import snakes.plugins
4 +snakes.plugins.load("query", "snakes.nets", "nets")
5 +
6 +port = 1234
7 +size = 2**20
8 +verbose = 0
9 +proto = "UDP"
10 +
11 +def help () :
12 + print "Usage: snkd [OPTION]"
13 + print "Options:"
14 + print " -p PORT, --port PORT listen on port number PORT"
15 + print " -t, --tcp use TCP instead of UDP"
16 + print " -s SIZE, --size SIZE set buffer size for inputs"
17 + print " -v, --verbose display information about queries"
18 + print " (use '-v' twice to dump queries/answers)"
19 + print " -h, --help print this help and exit"
20 +
21 +args = sys.argv[1:]
22 +try :
23 + while len(args) > 0 :
24 + arg = args.pop(0)
25 + if arg in ("-p", "--port") :
26 + port = int(args.pop(0))
27 + elif arg in ("-v", "--verbose") :
28 + verbose += 1
29 + elif arg in ("-t", "--tcp") :
30 + proto = "TCP"
31 + elif arg in ("-s", "--size") :
32 + size = int(args.pop(0))
33 + elif arg in ("-h", "--help") :
34 + help()
35 + sys.exit(0)
36 + else :
37 + print >>sys.stderr("snkd: invalid command %r" % arg)
38 + sys.exit(1)
39 +except SystemExit :
40 + raise
41 +except :
42 + cls, val, tb = sys.exc_info()
43 + print >>sys.stderr, "snkd: %s, %s" % (cls.__name__, val)
44 + sys.exit(1)
45 +
46 +if verbose :
47 + print "# starting"
48 + print "# listen on: %s:%u" % (proto, port)
49 + print "# buffer size: %uMb" % (size/1024)
50 + print "# verbosity:", verbose
51 +
52 +try :
53 + if proto == "UDP" :
54 + nets.UDPServer(port, size=size, verbose=verbose).run()
55 + else :
56 + nets.TCPServer(port, size=size, verbose=verbose).run()
57 +except KeyboardInterrupt :
58 + print "# bye"
59 +except :
60 + cls, val, tb = sys.exc_info()
61 + if verbose > 1 :
62 + raise
63 + elif verbose :
64 + print "# fatal error"
65 + print >>sys.stderr, "snkd: %s, %s" % (cls.__name__, val)
66 + sys.exit(2)
1 +lucid 10.04 LTS
2 +hardy 8.04 LTS
3 +oneiric 11.10
4 +precise 12.04 LTS
1 +python-snakes (0.9.16-1) UNRELEASED; urgency=low
2 +
3 + * see NEWS
4 +
5 + -- Franck Pommereau <pommereau@univ-paris12.fr> Tue, 07 Jun 2011 12:23:33 +0200
6 +
7 +python-snakes (0.9.15-1) UNRELEASED; urgency=low
8 +
9 + * see NEWS
10 +
11 + -- Franck Pommereau <pommereau@univ-paris12.fr> Tue, 10 May 2011 18:22:34 +0200
12 +
13 +python-snakes (0.9.14-1) UNRELEASED; urgency=low
14 +
15 + * see NEWS
16 +
17 + -- Franck Pommereau <pommereau@univ-paris12.fr> Mon, 11 Apr 2011 16:45:50 +0200
18 +
19 +python-snakes (0.9.13-2) UNRELEASED; urgency=low
20 +
21 + * see NEWS
22 +
23 + -- Franck Pommereau <pommereau@univ-paris12.fr> Fri, 23 Jul 2010 20:06:53 +0200
24 +
25 +python-snakes (0.9.13-1) UNRELEASED; urgency=low
26 +
27 + * see NEWS
28 +
29 + -- Franck Pommereau <pommereau@univ-paris12.fr> Fri, 16 Jul 2010 17:09:14 +0200
30 +
31 +python-snakes (0.9.12-2) UNRELEASED; urgency=low
32 +
33 + * see NEWS
34 +
35 + -- Franck Pommereau <pommereau@univ-paris12.fr> Sat, 03 Apr 2010 21:06:50 +0200
36 +
37 +python-snakes (0.9.12-1) UNRELEASED; urgency=low
38 +
39 + * see NEWS
40 +
41 + -- Franck Pommereau <pommereau@univ-paris12.fr> Thu, 01 Apr 2010 19:46:02 +0200
42 +
43 +python-snakes (0.9.11-1) UNRELEASED; urgency=low
44 +
45 + * see NEWS
46 +
47 + -- Franck Pommereau <pommereau@univ-paris12.fr> Thu, 25 Mar 2010 19:39:47 +0100
48 +
49 +python-snakes (0.9.10-1) UNRELEASED; urgency=low
50 +
51 + * see NEWS
52 +
53 + -- Franck Pommereau <pommereau@univ-paris12.fr> Fri, 19 Jun 2009 13:40:36 +0200
54 +
55 +python-snakes (0.9.9-2) UNRELEASED; urgency=low
56 +
57 + * see NEWS
58 +
59 + -- Franck Pommereau <pommereau@univ-paris12.fr> Tue, 19 May 2009 09:29:46 +0200
60 +
61 +python-snakes (0.9.8-2) UNRELEASED; urgency=low
62 +
63 + * see NEWS
64 +
65 + -- Franck Pommereau <pommereau@univ-paris12.fr> Tue, 14 Apr 2009 20:02:32 +0200
66 +
67 +python-snakes (0.9.8-1) UNRELEASED; urgency=low
68 +
69 + * see NEWS
70 +
71 + -- Franck Pommereau <pommereau@univ-paris12.fr> Mon, 23 Mar 2009 17:34:06 +0100
72 +
73 +python-snakes (0.9.7-1) UNRELEASED; urgency=low
74 +
75 + * see NEWS
76 +
77 + -- Franck Pommereau <pommereau@univ-paris12.fr> Tue, 20 Jan 2009 13:07:09 +0100
78 +
79 +python-snakes (0.9.6-2) UNRELEASED; urgency=low
80 +
81 + * see NEWS
82 +
83 + -- Franck Pommereau <pommereau@univ-paris12.fr> Tue, 02 Dec 2008 17:47:43 +0100
84 +
85 +python-snakes (0.9.6-1) UNRELEASED; urgency=low
86 +
87 + * see NEWS
88 +
89 + -- Franck Pommereau <pommereau@univ-paris12.fr> Fri, 28 Nov 2008 15:24:05 +0100
90 +
91 +python-snakes (0.9.5-2) UNRELEASED; urgency=low
92 +
93 + * Fixed doc installation path
94 +
95 + -- Franck Pommereau <pommereau@univ-paris12.fr> Fri, 21 Nov 2008 13:20:55 +0100
96 +
97 +python-snakes (0.9.5-1) UNRELEASED; urgency=low
98 +
99 + * Trying to fix build on Launchpad
100 +
101 + -- Franck Pommereau <pommereau@univ-paris12.fr> Fri, 21 Nov 2008 08:19:04 +0100
102 +
103 +python-snakes (0.9.5) UNRELEASED; urgency=low
104 +
105 + * See NEWS
106 +
107 + -- Franck Pommereau <pommereau@univ-paris12.fr> Wed, 19 Nov 2008 21:47:52 +0100
108 +
109 +python-snakes (0.9.4) UNRELEASED; urgency=low
110 +
111 + * Initial release. (Closes: #XXXXXX)
112 +
113 + -- Franck Pommereau <pommereau@univ-paris12.fr> Tue, 18 Nov 2008 12:09:16 +0100
1 +Source: python-snakes
2 +Section: python
3 +Priority: extra
4 +Maintainer: Franck Pommereau <pommereau@univ-paris12.fr>
5 +Homepage: http://lacl.univ-paris12.fr/pommereau/soft/snakes
6 +Build-Depends: python (>=2.5), cdbs (>=0.4.49), debhelper (>= 5), python-central (>=0.5.6)
7 +XS-Python-Version: >=2.5
8 +Standards-Version: 3.7.2
9 +
10 +Package: python-snakes
11 +Architecture: all
12 +XB-Python-Version: ${python:Versions}
13 +Depends: python (>=2.5), python-central, graphviz, python-tk
14 +Description: SNAKES is the Net Algebra Kit for Editors and Simulators
15 + SNAKES is a general purpose Petri net Python library allowing to
16 + define and execute most classes of Petri nets. It features a plugin
17 + system to allow its extension. In particular, plugins are provided to
18 + implement the operations usually found in the PBC and M-nets family.
1 +This package was debianized by Franck Pommereau <pommereau@univ-paris12.fr> on
2 +DATE
3 +
4 +License:
5 +
6 + This package is free software; you can redistribute it and/or
7 + modify it under the terms of the GNU Lesser General Public License
8 + as published by the Free Software Foundation; either version 2 of
9 + the License, or (at your option) any later version.
10 +
11 + This package is distributed in the hope that it will be useful, but
12 + WITHOUT ANY WARRANTY; without even the implied warranty of
13 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 + Lesser General Public License for more details.
15 +
16 + You should have received a copy of the GNU Lesser General Public
17 + License along with this package; if not, see
18 + `http://www.gnu.org/licenses/lgpl-3.0.txt'.
19 +
20 +On Debian systems, the complete text of the GNU General
21 +Public License can be found in `/usr/share/common-licenses/LGPL'.
22 +
23 +The Debian packaging is (C) 2008, Franck Pommereau
24 +<pommereau@univ-paris12.fr> and is licensed under the LGPL, see above.
1 +#!/usr/bin/make -f
2 +
3 +DEB_PYTHON_SYSTEM=pycentral
4 +
5 +include /usr/share/cdbs/1/rules/debhelper.mk
6 +include /usr/share/cdbs/1/class/python-distutils.mk
1 + GNU LESSER GENERAL PUBLIC LICENSE
2 + Version 3, 29 June 2007
3 +
4 + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
5 + Everyone is permitted to copy and distribute verbatim copies
6 + of this license document, but changing it is not allowed.
7 +
8 +
9 + This version of the GNU Lesser General Public License incorporates
10 +the terms and conditions of version 3 of the GNU General Public
11 +License, supplemented by the additional permissions listed below.
12 +
13 + 0. Additional Definitions.
14 +
15 + As used herein, "this License" refers to version 3 of the GNU Lesser
16 +General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 +General Public License.
18 +
19 + "The Library" refers to a covered work governed by this License,
20 +other than an Application or a Combined Work as defined below.
21 +
22 + An "Application" is any work that makes use of an interface provided
23 +by the Library, but which is not otherwise based on the Library.
24 +Defining a subclass of a class defined by the Library is deemed a mode
25 +of using an interface provided by the Library.
26 +
27 + A "Combined Work" is a work produced by combining or linking an
28 +Application with the Library. The particular version of the Library
29 +with which the Combined Work was made is also called the "Linked
30 +Version".
31 +
32 + The "Minimal Corresponding Source" for a Combined Work means the
33 +Corresponding Source for the Combined Work, excluding any source code
34 +for portions of the Combined Work that, considered in isolation, are
35 +based on the Application, and not on the Linked Version.
36 +
37 + The "Corresponding Application Code" for a Combined Work means the
38 +object code and/or source code for the Application, including any data
39 +and utility programs needed for reproducing the Combined Work from the
40 +Application, but excluding the System Libraries of the Combined Work.
41 +
42 + 1. Exception to Section 3 of the GNU GPL.
43 +
44 + You may convey a covered work under sections 3 and 4 of this License
45 +without being bound by section 3 of the GNU GPL.
46 +
47 + 2. Conveying Modified Versions.
48 +
49 + If you modify a copy of the Library, and, in your modifications, a
50 +facility refers to a function or data to be supplied by an Application
51 +that uses the facility (other than as an argument passed when the
52 +facility is invoked), then you may convey a copy of the modified
53 +version:
54 +
55 + a) under this License, provided that you make a good faith effort to
56 + ensure that, in the event an Application does not supply the
57 + function or data, the facility still operates, and performs
58 + whatever part of its purpose remains meaningful, or
59 +
60 + b) under the GNU GPL, with none of the additional permissions of
61 + this License applicable to that copy.
62 +
63 + 3. Object Code Incorporating Material from Library Header Files.
64 +
65 + The object code form of an Application may incorporate material from
66 +a header file that is part of the Library. You may convey such object
67 +code under terms of your choice, provided that, if the incorporated
68 +material is not limited to numerical parameters, data structure
69 +layouts and accessors, or small macros, inline functions and templates
70 +(ten or fewer lines in length), you do both of the following:
71 +
72 + a) Give prominent notice with each copy of the object code that the
73 + Library is used in it and that the Library and its use are
74 + covered by this License.
75 +
76 + b) Accompany the object code with a copy of the GNU GPL and this license
77 + document.
78 +
79 + 4. Combined Works.
80 +
81 + You may convey a Combined Work under terms of your choice that,
82 +taken together, effectively do not restrict modification of the
83 +portions of the Library contained in the Combined Work and reverse
84 +engineering for debugging such modifications, if you also do each of
85 +the following:
86 +
87 + a) Give prominent notice with each copy of the Combined Work that
88 + the Library is used in it and that the Library and its use are
89 + covered by this License.
90 +
91 + b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 + document.
93 +
94 + c) For a Combined Work that displays copyright notices during
95 + execution, include the copyright notice for the Library among
96 + these notices, as well as a reference directing the user to the
97 + copies of the GNU GPL and this license document.
98 +
99 + d) Do one of the following:
100 +
101 + 0) Convey the Minimal Corresponding Source under the terms of this
102 + License, and the Corresponding Application Code in a form
103 + suitable for, and under terms that permit, the user to
104 + recombine or relink the Application with a modified version of
105 + the Linked Version to produce a modified Combined Work, in the
106 + manner specified by section 6 of the GNU GPL for conveying
107 + Corresponding Source.
108 +
109 + 1) Use a suitable shared library mechanism for linking with the
110 + Library. A suitable mechanism is one that (a) uses at run time
111 + a copy of the Library already present on the user's computer
112 + system, and (b) will operate properly with a modified version
113 + of the Library that is interface-compatible with the Linked
114 + Version.
115 +
116 + e) Provide Installation Information, but only if you would otherwise
117 + be required to provide such information under section 6 of the
118 + GNU GPL, and only to the extent that such information is
119 + necessary to install and execute a modified version of the
120 + Combined Work produced by recombining or relinking the
121 + Application with a modified version of the Linked Version. (If
122 + you use option 4d0, the Installation Information must accompany
123 + the Minimal Corresponding Source and Corresponding Application
124 + Code. If you use option 4d1, you must provide the Installation
125 + Information in the manner specified by section 6 of the GNU GPL
126 + for conveying Corresponding Source.)
127 +
128 + 5. Combined Libraries.
129 +
130 + You may place library facilities that are a work based on the
131 +Library side by side in a single library together with other library
132 +facilities that are not Applications and are not covered by this
133 +License, and convey such a combined library under terms of your
134 +choice, if you do both of the following:
135 +
136 + a) Accompany the combined library with a copy of the same work based
137 + on the Library, uncombined with any other library facilities,
138 + conveyed under the terms of this License.
139 +
140 + b) Give prominent notice with the combined library that part of it
141 + is a work based on the Library, and explaining where to find the
142 + accompanying uncombined form of the same work.
143 +
144 + 6. Revised Versions of the GNU Lesser General Public License.
145 +
146 + The Free Software Foundation may publish revised and/or new versions
147 +of the GNU Lesser General Public License from time to time. Such new
148 +versions will be similar in spirit to the present version, but may
149 +differ in detail to address new problems or concerns.
150 +
151 + Each version is given a distinguishing version number. If the
152 +Library as you received it specifies that a certain numbered version
153 +of the GNU Lesser General Public License "or any later version"
154 +applies to it, you have the option of following the terms and
155 +conditions either of that published version or of any later version
156 +published by the Free Software Foundation. If the Library as you
157 +received it does not specify a version number of the GNU Lesser
158 +General Public License, you may choose any version of the GNU Lesser
159 +General Public License ever published by the Free Software Foundation.
160 +
161 + If the Library as you received it specifies that a proxy can decide
162 +whether future versions of the GNU Lesser General Public License shall
163 +apply, that proxy's public statement of acceptance of any version is
164 +permanent authorization for you to choose that version for the
165 +Library.
1 +all:
2 + rm -rf api
3 + epydoc --output api --no-frames --graph=all \
4 + --name="SNAKES is the Net Algebra Kit for Editors and Simulators" \
5 + --navlink='<img alt="SNAKES logo" src="snakes-logo.jpg" width="120" height="120"/>' \
6 + --no-private ../snakes
7 + convert ../logo/snakes-logo.png -background white -scale 120x120 ./api/snakes-logo.jpg
This diff is collapsed. Click to expand it.
1 +prod-cons.abcd
2 + a simple producer/consumer
3 +
4 +railroad.abcd
5 + a (not so) simple railroad crossing system
6 +railroad.py
7 + checks basic property of railroad.abcd
8 +
9 +ns/ns.abcd
10 + Needham-Schroeder public key authentication protocol
11 +ns/ns.py
12 + checks mutual authentication
This diff is collapsed. Click to expand it.
1 +# communication network
2 +buffer nw : object = ()
3 +# implementation of nonces and Dolev-Yao attacker
4 +from dolev_yao import *
5 +
6 +net Alice (this, who: buffer) :
7 + # protocol initiater
8 + buffer peer : int = ()
9 + buffer peer_nonce : Nonce = ()
10 + [who?(B), peer+(B), nw+("crypt", ("pub", B), this, Nonce(this))]
11 + ; [nw-("crypt", ("pub", this), Na, Nb), peer_nonce+(Nb) if Na == Nonce(this)]
12 + ; [peer?(B), peer_nonce?(Nb), nw+("crypt", ("pub", B), Nb)]
13 +
14 +net Bob (this) :
15 + # protocol responder
16 + buffer peer : int = ()
17 + buffer peer_nonce : Nonce = ()
18 + [nw-("crypt", ("pub", this), A, Na), peer+(A), peer_nonce+(Na)]
19 + ; [peer?(A), peer_nonce?(Na), nw+("crypt", ("pub", A), Na, Nonce(this))]
20 + ; [nw-("crypt", ("pub", this), Nb) if Nb == Nonce(this)]
21 +
22 +net Mallory (this, init) :
23 + # attacker
24 + buffer knowledge : object = (this, Nonce(this), ("priv", this)) + init
25 + # Dolev-Yao attacker, bound by protocol signature
26 + buffer spy : object = Spy(("crypt", ("pub", int), int, Nonce),
27 + ("crypt", ("pub", int), Nonce, Nonce),
28 + ("crypt", ("pub", int), Nonce))
29 + # capture on message and learn from it
30 + ([spy?(s), nw-(m), knowledge>>(k), knowledge<<(s.learn(m, k))]
31 + # loose message or inject another one (may be the same)
32 + ; ([True] + [spy?(s), knowledge?(x), nw+(x) if s.message(x)]))
33 + * [False]
34 +
35 +# Alice will contact one of these agents
36 +buffer agents : int = 2, 3
37 +# main processes, with friendly names
38 +alice::Alice(1, agents)
39 +| bob::Bob(2)
40 +| spy::Mallory(3, (1, ("pub", 1), 2, ("pub", 2)))
1 +import snakes.plugins
2 +snakes.plugins.load("status", "snakes.nets", "nets")
3 +from nets import *
4 +from dolev_yao import Nonce
5 +
6 +ns = loads(",ns.pnml")
7 +states = StateGraph(ns)
8 +
9 +for s in states :
10 + m = states.net.get_marking()
11 + # skip non final markings
12 + if "bob.x" not in m or "alice.x" not in m :
13 + continue
14 + # get Alice's and Bob's peers ids
15 + bp = list(m["bob.peer"])[0]
16 + ap = list(m["alice.peer"])[0]
17 + # violation of mutual authentication
18 + if bp == 1 and ap != 2 :
19 + print(s, "A(1) <=> %s ; B(2) <=> %s" % (ap, bp))
20 + print(m)
21 +
22 +print(len(states), "states")
1 +# get BlackToken
2 +#from snakes.nets import *
3 +
4 +buffer fork1 : BlackToken = dot
5 +buffer fork2 : BlackToken = dot
6 +buffer fork3 : BlackToken = dot
7 +
8 +# buffer parameters have to be declared as such
9 +net philo (left: buffer, right: buffer):
10 + buffer eating : BlackToken = ()
11 + ([left-(dot), right-(dot), eating+(dot)]
12 + ; [left+(dot), right+(dot), eating-(dot)])
13 + * [False]
14 +
15 +philo(fork1, fork2)
16 +| philo(fork2, fork3)
17 +| philo(fork3, fork1)
1 +# shared buffer between producers and consumers
2 +buffer bag : int = ()
3 +
4 +net prod () :
5 + # produces 10 tokens: 1..9 in bag
6 + buffer count : int = 0
7 + [count-(x), count+(x+1), bag+(x) if x < 10] * [count-(x) if x == 10]
8 +
9 +net odd () :
10 + # consumes odd tokens in bag
11 + [bag-(x) if (x % 2) == 1] * [False]
12 +
13 +net even () :
14 + # consumes even tokens un bag
15 + [bag-(x) if (x % 2) == 0] * [False]
16 +
17 +# main process with one instance of each net
18 +odd() | even() | prod()
1 +# symbols
2 +symbol RED, GREEN, UP, DOWN, OPEN, MOVING, CLOSED
3 +# states of the gate
4 +typedef gatestate : enum(OPEN, MOVING, CLOSED)
5 +
6 +# stores green light state
7 +buffer light : enum(RED, GREEN) = GREEN
8 +# commands send by the track to the gate
9 +buffer command : enum(UP, DOWN) = ()
10 +
11 +net gate () :
12 + # a pair of gates
13 + buffer state : gatestate = OPEN
14 + ([command-(DOWN), state-(OPEN), state+(MOVING)] ;
15 + [state-(MOVING), state+(CLOSED), light-(RED), light+(GREEN)] ;
16 + [command-(UP), state-(CLOSED), state+(MOVING)] ;
17 + [state-(MOVING), state+(OPEN)])
18 + * [False]
19 +
20 +net track () :
21 + # a track with trains passing on it
22 + buffer crossing : bool = False
23 + ([command+(DOWN), light-(GREEN), light+(RED)] ;
24 + [light?(GREEN), crossing-(False), crossing+(True)] ;
25 + [crossing-(True), crossing+(False), command+(UP)])
26 + * [False]
27 +
28 +# main process
29 +gate() | track()
1 +import sys
2 +
3 +import snakes.plugins
4 +snakes.plugins.load("gv", "snakes.nets", "snk")
5 +from snk import *
6 +
7 +n = loads(sys.argv[1])
8 +g = StateGraph(n)
9 +for s in g :
10 + m = g.net.get_marking()
11 + # safety property: train present => gates closed
12 + if ("train().crossing" in m
13 + and True in m["train().crossing"]
14 + and "closed" not in m["gate().state"]) :
15 + print("%s %s" % (s, m))
16 +print("checked %s states" % len(g))
17 +
18 +g.draw(sys.argv[1].rsplit(".", 1)[0] + "-states.png")
This diff is collapsed. Click to expand it.
1 +<?xml version="1.0" encoding="utf-8"?>
2 +<pnml>
3 + <net id="mynet">
4 + <place id="p2">
5 + <type domain="universal"/>
6 + <initialMarking>
7 + <multiset/>
8 + </initialMarking>
9 + </place>
10 + <place id="p1">
11 + <type domain="universal"/>
12 + <initialMarking>
13 + <multiset>
14 + <item>
15 + <value>
16 + <object type="int">
17 + 1
18 + </object>
19 + </value>
20 + <multiplicity>
21 + 1
22 + </multiplicity>
23 + </item>
24 + <item>
25 + <value>
26 + <object type="int">
27 + 2
28 + </object>
29 + </value>
30 + <multiplicity>
31 + 1
32 + </multiplicity>
33 + </item>
34 + </multiset>
35 + </initialMarking>
36 + </place>
37 + <transition id="t"/>
38 + <arc id="p1:t" source="p1" target="t">
39 + <inscription>
40 + <variable>
41 + x
42 + </variable>
43 + </inscription>
44 + </arc>
45 + <arc id="t:p2" source="t" target="p2">
46 + <inscription>
47 + <expression>
48 + x+1
49 + </expression>
50 + </inscription>
51 + </arc>
52 + </net>
53 +</pnml>
1 +<?xml version="1.0" encoding="utf-8"?>
2 +<pnml>
3 + <net id="Simple P/T net">
4 + <place id="p2">
5 + <initialMarking>
6 + <text>
7 + 0
8 + </text>
9 + </initialMarking>
10 + </place>
11 + <place id="p1">
12 + <initialMarking>
13 + <text>
14 + 1
15 + </text>
16 + </initialMarking>
17 + </place>
18 + <transition id="t2"/>
19 + <transition id="t1"/>
20 + <arc id="p2:t2" source="p2" target="t2">
21 + <inscription>
22 + <text>
23 + 1
24 + </text>
25 + </inscription>
26 + </arc>
27 + <arc id="t2:p1" source="t2" target="p1">
28 + <inscription>
29 + <text>
30 + 1
31 + </text>
32 + </inscription>
33 + </arc>
34 + <arc id="p1:t1" source="p1" target="t1">
35 + <inscription>
36 + <text>
37 + 1
38 + </text>
39 + </inscription>
40 + </arc>
41 + <arc id="t1:p2" source="t1" target="p2">
42 + <inscription>
43 + <text>
44 + 1
45 + </text>
46 + </inscription>
47 + </arc>
48 + </net>
49 +</pnml>
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
1 +import os, os.path
2 +
3 +snakes_version = open("VERSION").readline().strip()
4 +package_version = open("debian/VERSION").readline().strip()
5 +ppa_version = open("debian/PPA").readline().strip()
6 +changelog_version = open("debian/changelog").readline().split()[1].strip("()")
7 +distribs = [l.strip().split()[0] for l in open("debian/DISTRIB")]
8 +base_dir = os.getcwd()
9 +base_dist_dir = "dist"
10 +dput_sh = open("dput.sh", "w")
11 +
12 +def system (command) :
13 + print("*** %s" % command)
14 + retcode = os.system(command)
15 + if retcode != 0 :
16 + print("*** error return status (%s)" % retcode)
17 + sys.exit(retcode)
18 +
19 +def chdir (path) :
20 + print("*** cd %s" % path)
21 + os.chdir(path)
22 +
23 +def changelog (path, dist) :
24 + full_version = "%s-%s~ppa%s~%s1" % (snakes_version, package_version,
25 + ppa_version, dist)
26 + chdir(path)
27 + system("debchange -b --newversion %s --distribution %s 'see NEWS'"
28 + % (full_version, dist))
29 + chdir(base_dir)
30 +
31 +def build_package (dist_dir, dist) :
32 + full_version = "%s-%s~ppa%s~%s1" % (snakes_version, package_version,
33 + ppa_version, dist)
34 + deb_dir = os.path.join(dist_dir, "python-snakes_%s" % full_version)
35 + if not os.path.isdir(dist_dir) :
36 + print("*** make dir %r" % dist_dir)
37 + os.makedirs(dist_dir)
38 + if os.path.isdir(deb_dir) :
39 + system("rm -rf %s" % deb_dir)
40 + system("hg archive %s" % deb_dir)
41 + changelog(deb_dir, dist)
42 + system("sed -i -e 's/DATE/$(date -R)/' %s/debian/copyright" % deb_dir)
43 + system("sed -i -e 's/UNRELEASED/%s/' %s/debian/changelog" % (dist, deb_dir))
44 + chdir(deb_dir)
45 + system("make doc")
46 + system("dpkg-buildpackage")
47 + system("dpkg-buildpackage -S -sa")
48 + chdir(base_dir)
49 + dput_sh.write("dput lp %s_source.changes\n" % deb_dir)
50 +
51 +main_version = "%s-%s" % (snakes_version, package_version)
52 +if main_version != changelog_version :
53 + system("debchange --newversion %s --distribution UNRELEASED 'see NEWS'"
54 + % main_version)
55 + system("hg commit -m 'updated debian/changelog' debian/changelog")
56 +
57 +for dist in distribs :
58 + build_package(base_dist_dir, dist)
59 +dput_sh.close()
1 +import glob, os, os.path
2 +
3 +for src in glob.glob("snakes/lang/*/*.pgen") :
4 + tgt = os.path.join(os.path.dirname(src), "pgen.py")
5 + if not os.path.isfile(tgt) or os.path.getmtime(src) > os.path.getmtime(tgt) :
6 + print("python snakes/lang/pgen.py --output=%s %s" % (tgt, src))
7 + os.system("python snakes/lang/pgen.py --output=%s %s" % (tgt, src))
8 +
9 +for src in glob.glob("snakes/lang/*/*.asdl") :
10 + tgt = os.path.join(os.path.dirname(src), "asdl.py")
11 + if not os.path.isfile(tgt) or os.path.getmtime(src) > os.path.getmtime(tgt) :
12 + print("python snakes/lang/asdl.py --output=%s %s" % (tgt, src))
13 + os.system("python snakes/lang/asdl.py --output=%s %s" % (tgt, src))
1 +#!/usr/bin/env python
2 +
3 +import sys, os
4 +from distutils.core import setup
5 +
6 +def doc_files() :
7 + import os, os.path
8 + result = {}
9 + for root, dirs, files in os.walk("doc") :
10 + target_dir = os.path.join("share/doc/python-snakes",
11 + *root.split(os.sep)[1:])
12 + for name in files :
13 + if target_dir not in result :
14 + result[target_dir] = []
15 + result[target_dir].append(os.path.join(root, name))
16 + return list(result.items())
17 +
18 +if __name__ == "__main__" :
19 + print("Compiling Emacs files...")
20 + os.system("emacs -batch -f batch-byte-compile utils/abcd-mode.el")
21 + #
22 + setup(name="SNAKES",
23 + version=open("VERSION").read().strip(),
24 + description="SNAKES is the Net Algebra Kit for Editors and Simulators",
25 + long_description="""SNAKES is a general purpose Petri net Python
26 + library allowing to define and execute most classes of Petri
27 + nets. It features a plugin system to allow its extension. In
28 + particular, plugins are provided to implement the operations
29 + usually found in the PBC and M-nets family.""",
30 + author="Franck Pommereau",
31 + author_email="pommereau@univ-paris12.fr",
32 + maintainer="Franck Pommereau",
33 + maintainer_email="pommereau@univ-paris12.fr",
34 + url="http://lacl.univ-paris12.fr/pommereau/soft/snakes",
35 + scripts=["bin/abcd",
36 + "bin/snkc",
37 + "bin/snkd",
38 + ],
39 + packages=["snakes",
40 + "snakes.lang",
41 + "snakes.lang.pylib",
42 + "snakes.lang.python",
43 + "snakes.lang.abcd",
44 + "snakes.lang.ctlstar",
45 + "snakes.plugins",
46 + "snakes.utils",
47 + "snakes.utils.abcd",
48 + "snakes.utils.ctlstar",
49 + ],
50 + data_files=(doc_files()
51 + + [("share/emacs/site-lisp", ["utils/abcd-mode.el",
52 + "utils/abcd-mode.elc"])]),
53 + )
1 +"""SNAKES is the Net Algebra Kit for Editors and Simulators
2 +
3 +@author: Franck Pommereau
4 +@organization: University of Paris 12
5 +@copyright: (C) 2005 Franck Pommereau
6 +@license: GNU Lesser General Public Licence (aka. GNU LGPL),
7 + see the file C{doc/COPYING} in the distribution or visit U{the GNU
8 + web site<http://www.gnu.org/licenses/licenses.html#LGPL>}
9 +@contact: pommereau@univ-paris12.fr
10 +
11 +SNAKES is a Python library allowing to model all sorts of Petri nets
12 +and to execute them. It is very general as most Petri nets annotations
13 +can be arbitrary Python expressions while most values can be arbitrary
14 +Python objects.
15 +
16 +SNAKES can be further extended with plugins, several ones being
17 +already provided, in particular two plugins implement the Petri nets
18 +compositions defined for the Petri Box Calculus and its successors.
19 +"""
20 +
21 +version = "0.9.16"
22 +defaultencoding = "utf-8"
23 +
24 +class SnakesError (Exception) :
25 + "An error in SNAKES"
26 + pass
27 +
28 +class ConstraintError (SnakesError) :
29 + "Violation of a constraint"
30 + pass
31 +
32 +class NodeError (SnakesError) :
33 + "Error related to a place or a transition"
34 + pass
35 +
36 +class DomainError (SnakesError) :
37 + "Function applied out of its domain"
38 + pass
39 +
40 +class ModeError (SnakesError) :
41 + "The modes of a transition cannot be found"
42 + pass
43 +
44 +class PluginError (SnakesError) :
45 + "Error when adding a plugin"
46 + pass
47 +
48 +class UnificationError (SnakesError) :
49 + "Error while unifying parameters"
50 + pass
1 +"""Python 2 and 3 compatibility layer
2 +"""
3 +
4 +import sys
5 +
6 +try :
7 + xrange
8 +except NameError :
9 + xrange = range
10 +
11 +try :
12 + reduce
13 +except NameError :
14 + from functools import reduce
15 +
16 +try :
17 + import StringIO as io
18 +except ImportError :
19 + import io
20 +
21 +try :
22 + next
23 +except NameError :
24 + def next (obj) :
25 + return obj.next()
26 +
27 +PY3 = sys.version > "3"
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
1 +import sys
2 +if sys.version_info[:2] in ((2, 6), (2, 7)) :
3 + import ast
4 +elif sys.version_info[0] == 3 :
5 + import ast
6 +elif hasattr(sys, "pypy_version_info") :
7 + import astpypy as ast
8 +elif hasattr(sys, "JYTHON_JAR") :
9 + import astjy25 as ast
10 +elif sys.version_info[:2] == (2, 5) :
11 + import astpy25 as ast
12 +else :
13 + raise NotImplementedError("unsupported Python version")
14 +
15 +sys.modules["snkast"] = ast
16 +
17 +from . import unparse as _unparse
18 +from snakes.compat import *
19 +
20 +class Names (ast.NodeVisitor) :
21 + def __init__ (self) :
22 + ast.NodeVisitor.__init__(self)
23 + self.names = set()
24 + def visit_Name (self, node) :
25 + self.names.add(node.id)
26 +
27 +def getvars (expr) :
28 + """
29 + >>> list(sorted(getvars('x+y<z')))
30 + ['x', 'y', 'z']
31 + >>> list(sorted(getvars('x+y<z+f(3,t)')))
32 + ['f', 't', 'x', 'y', 'z']
33 + """
34 + names = Names()
35 + names.visit(ast.parse(expr))
36 + return names.names - set(['None', 'True', 'False'])
37 +
38 +class Unparser(_unparse.Unparser) :
39 + boolops = {"And": 'and', "Or": 'or'}
40 + def _Interactive (self, tree) :
41 + for stmt in tree.body :
42 + self.dispatch(stmt)
43 + def _Expression (self, tree) :
44 + self.dispatch(tree.body)
45 + def _ClassDef(self, tree):
46 + self.write("\n")
47 + for deco in tree.decorator_list:
48 + self.fill("@")
49 + self.dispatch(deco)
50 + self.fill("class "+tree.name)
51 + if tree.bases:
52 + self.write("(")
53 + for a in tree.bases:
54 + self.dispatch(a)
55 + self.write(", ")
56 + self.write(")")
57 + self.enter()
58 + self.dispatch(tree.body)
59 + self.leave()
60 +
61 +def unparse (st) :
62 + output = io.StringIO()
63 + Unparser(st, output)
64 + return output.getvalue().strip()
65 +
66 +class Renamer (ast.NodeTransformer) :
67 + def __init__ (self, map_names) :
68 + ast.NodeTransformer.__init__(self)
69 + self.map = [map_names]
70 + def visit_ListComp (self, node) :
71 + bind = self.map[-1].copy()
72 + for comp in node.generators :
73 + for name in getvars(comp.target) :
74 + if name in bind :
75 + del bind[name]
76 + self.map.append(bind)
77 + node.elt = self.visit(node.elt)
78 + self.map.pop(-1)
79 + return node
80 + def visit_SetComp (self, node) :
81 + return self.visit_ListComp(node)
82 + def visit_DictComp (self, node) :
83 + bind = self.map[-1].copy()
84 + for comp in node.generators :
85 + for name in getvars(comp.target) :
86 + if name in bind :
87 + del bind[name]
88 + self.map.append(bind)
89 + node.key = self.visit(node.key)
90 + node.value = self.visit(node.value)
91 + self.map.pop(-1)
92 + return node
93 + def visit_Name (self, node) :
94 + return ast.copy_location(ast.Name(id=self.map[-1].get(node.id,
95 + node.id),
96 + ctx=ast.Load()), node)
97 +
98 +def rename (expr, map={}, **ren) :
99 + """
100 + >>> rename('x+y<z', x='t')
101 + '((t + y) < z)'
102 + >>> rename('x+y<z+f(3,t)', f='g', t='z', z='t')
103 + '((x + y) < (t + g(3, z)))'
104 + >>> rename('[x+y for x in range(3)]', x='z')
105 + '[(x + y) for x in range(3)]'
106 + >>> rename('[x+y for x in range(3)]', y='z')
107 + '[(x + z) for x in range(3)]'
108 + """
109 + map_names = dict(map)
110 + map_names.update(ren)
111 + transf = Renamer(map_names)
112 + return unparse(transf.visit(ast.parse(expr)))
113 +
114 +class Binder (Renamer) :
115 + def visit_Name (self, node) :
116 + if node.id in self.map[-1] :
117 + return self.map[-1][node.id]
118 + else :
119 + return node
120 +
121 +def bind (expr, map={}, **ren) :
122 + """
123 + >>> bind('x+y<z', x=ast.Num(n=2))
124 + '((2 + y) < z)'
125 + >>> bind('x+y<z', y=ast.Num(n=2))
126 + '((x + 2) < z)'
127 + >>> bind('[x+y for x in range(3)]', x=ast.Num(n=2))
128 + '[(x + y) for x in range(3)]'
129 + >>> bind('[x+y for x in range(3)]', y=ast.Num(n=2))
130 + '[(x + 2) for x in range(3)]'
131 + """
132 + map_names = dict(map)
133 + map_names.update(ren)
134 + transf = Binder(map_names)
135 + return unparse(transf.visit(ast.parse(expr)))
136 +
137 +if __name__ == "__main__" :
138 + import doctest
139 + doctest.testmod()
1 +module ABCD version "$Revision: 1 $"
2 +{
3 + abcd = AbcdSpec(decl* context, process body, expr* asserts)
4 +
5 + decl = AbcdTypedef(identifier name, abcdtype type)
6 + | AbcdBuffer(identifier name, abcdtype type,
7 + Slice? capacity, expr content)
8 + | AbcdSymbol(identifier* symbols)
9 + | AbcdConst(identifier name, expr value)
10 + | AbcdNet(identifier name, arguments args, AbcdSpec body)
11 + | AbcdTask(identifier name, AbcdSpec body,
12 + abcdtype* input, ancdtype* output)
13 + | stmt -- this too much, but does not harm
14 +
15 + attributes (int lineno, int col_offset)
16 +
17 + process = AbcdAction(access* accesses, object guard)
18 + | AbcdFlowOp(process left, flowop op, process right)
19 + | AbcdInstance(identifier net, identifier? asname, expr* args,
20 + keyword* keywords, expr? starargs, expr? kwargs)
21 +
22 + attributes (int lineno, int col_offset)
23 +
24 + flowop = Sequence | Choice | Parallel | Loop
25 +
26 + access = SimpleAccess(identifier buffer, arc arc, expr tokens)
27 + | FlushAccess(identifier buffer, identifier target)
28 + | SwapAccess(identifier buffer, expr target, expr tokens)
29 + | Spawn(identifier net, expr pid, expr args)
30 + | Wait(identifier net, expr pid, expr args)
31 + | Suspend(identifier net, expr pid)
32 + | Resume(identifier net, expr pid)
33 +
34 + attributes (int lineno, int col_offset)
35 +
36 + arc = Produce | Test | Consume | Fill
37 +
38 + abcdtype = UnionType(abcdtype* types)
39 + | IntersectionType(abcdtype* types)
40 + | CrossType(abcdtype* types)
41 + | ListType(abcdtype items)
42 + | TupleType(abcdtype items)
43 + | SetType(abcdtype items)
44 + | DictType(abcdtype keys, abcdtype values)
45 + | EnumType(expr* items)
46 + | NamedType(identifier name)
47 +
48 + attributes (int lineno, int col_offset)
49 +
50 + --------------------------------------------------------------
51 + -- the rest is copied from "snakes/lang/python/python.asdl" --
52 + --------------------------------------------------------------
53 +
54 + stmt = FunctionDef(identifier name, arguments args,
55 + stmt* body, expr* decorator_list, expr? returns)
56 + | ClassDef(identifier name,
57 + expr* bases,
58 + keyword* keywords,
59 + expr? starargs,
60 + expr? kwargs,
61 + stmt* body,
62 + expr *decorator_list)
63 + | Return(expr? value)
64 +
65 + | Delete(expr* targets)
66 + | Assign(expr* targets, expr value)
67 + | AugAssign(expr target, operator op, expr value)
68 +
69 + | For(expr target, expr iter, stmt* body, stmt* orelse)
70 + | While(expr test, stmt* body, stmt* orelse)
71 + | If(expr test, stmt* body, stmt* orelse)
72 + | With(expr context_expr, expr? optional_vars, stmt* body)
73 +
74 + | Raise(expr? exc, expr? cause)
75 + | TryExcept(stmt* body, excepthandler* handlers, stmt* orelse)
76 + | TryFinally(stmt* body, stmt* finalbody)
77 + | Assert(expr test, expr? msg)
78 +
79 + | Import(alias* names)
80 + | ImportFrom(identifier module, alias* names, int? level)
81 +
82 + | Exec(expr body, expr? globals, expr? locals)
83 +
84 + | Global(identifier* names)
85 + | Nonlocal(identifier* names)
86 + | Expr(expr value)
87 + | Pass | Break | Continue
88 +
89 + attributes (int lineno, int col_offset)
90 +
91 + expr = BoolOp(boolop op, expr* values)
92 + | BinOp(expr left, operator op, expr right)
93 + | UnaryOp(unaryop op, expr operand)
94 + | Lambda(arguments args, expr body)
95 + | IfExp(expr test, expr body, expr orelse)
96 + | Dict(expr* keys, expr* values)
97 + | Set(expr* elts)
98 + | ListComp(expr elt, comprehension* generators)
99 + | SetComp(expr elt, comprehension* generators)
100 + | DictComp(expr key, expr value, comprehension* generators)
101 + | GeneratorExp(expr elt, comprehension* generators)
102 + | Yield(expr? value)
103 + | Compare(expr left, cmpop* ops, expr* comparators)
104 + | Call(expr func, expr* args, keyword* keywords,
105 + expr? starargs, expr? kwargs)
106 + | Num(object n)
107 + | Str(string s)
108 + | Ellipsis
109 +
110 + | Attribute(expr value, identifier attr, expr_context ctx)
111 + | Subscript(expr value, slice slice, expr_context ctx)
112 + | Starred(expr value, expr_context ctx)
113 + | Name(identifier id, expr_context ctx)
114 + | List(expr* elts, expr_context ctx)
115 + | Tuple(expr* elts, expr_context ctx)
116 +
117 + attributes (int lineno, int col_offset)
118 +
119 + expr_context = Load | Store | Del | AugLoad | AugStore | Param
120 +
121 + slice = Slice(expr? lower, expr? upper, expr? step)
122 + | ExtSlice(slice* dims)
123 + | Index(expr value)
124 +
125 + boolop = And | Or
126 +
127 + operator = Add | Sub | Mult | Div | Mod | Pow | LShift
128 + | RShift | BitOr | BitXor | BitAnd | FloorDiv
129 +
130 + unaryop = Invert | Not | UAdd | USub
131 +
132 + cmpop = Eq | NotEq | Lt | LtE | Gt | GtE | Is | IsNot | In | NotIn
133 +
134 + comprehension = (expr target, expr iter, expr* ifs)
135 +
136 + excepthandler = ExceptHandler(expr? type, identifier? name, stmt* body)
137 + attributes (int lineno, int col_offset)
138 +
139 + arguments = (arg* args, identifier? vararg, expr? varargannotation,
140 + arg* kwonlyargs, identifier? kwarg,
141 + expr? kwargannotation, expr* defaults,
142 + expr* kw_defaults)
143 + arg = (identifier arg, expr? annotation)
144 +
145 + keyword = (identifier arg, expr value)
146 +
147 + alias = (identifier name, identifier? asname)
148 +}
1 +# Grammar for ABCD
2 +
3 +# new tokens
4 +$QUESTION '?'
5 +$ELLIPSIS '...'
6 +
7 +file_input: abcd_main ENDMARKER
8 +
9 +abcd_main: (NEWLINE | abcd_global)* abcd_expr abcd_prop*
10 +abcd_global: import_stmt | abcd_symbol | abcd_typedef | abcd_const | abcd_decl
11 +abcd_spec: (NEWLINE | abcd_decl)* abcd_expr
12 +abcd_decl: abcd_net | abcd_task | abcd_buffer
13 +
14 +abcd_const: 'const' NAME '=' testlist
15 +abcd_symbol: 'symbol' abcd_namelist
16 +abcd_typedef: 'typedef' NAME ':' abcd_type
17 +abcd_net: 'net' NAME parameters ':' abcd_suite
18 +abcd_task: 'task' NAME typelist '-' '>' typelist ':' abcd_suite
19 +abcd_suite: abcd_expr | NEWLINE INDENT abcd_spec DEDENT
20 +abcd_buffer: [ decorators ] 'buffer' NAME ['[' test ']'] ':' abcd_type '=' testlist
21 +
22 +abcd_namelist: NAME (',' NAME)*
23 +typelist: '(' [abcd_type (',' abcd_type)*] ')'
24 +
25 +abcd_type: abcd_and_type ('|' abcd_and_type)*
26 +abcd_and_type: abcd_cross_type ('&' abcd_cross_type)*
27 +abcd_cross_type: abcd_base_type ('*' abcd_base_type)*
28 +abcd_base_type: (NAME ['(' abcd_type (',' abcd_type)* ')']
29 + | 'enum' '(' test (',' test)* ')' | '(' abcd_type ')')
30 +
31 +abcd_expr: abcd_choice_expr ('|' abcd_choice_expr)*
32 +abcd_choice_expr: abcd_iter_expr ('+' abcd_iter_expr)*
33 +abcd_iter_expr: abcd_seq_expr ('*' abcd_seq_expr)*
34 +abcd_seq_expr: abcd_base_expr (';' abcd_base_expr)*
35 +abcd_base_expr: (abcd_action | '(' abcd_expr ')') (NEWLINE)*
36 +abcd_action: ('[' 'True' ']' |
37 + '[' 'False' ']' |
38 + '[' abcd_access_list ['if' test] ']' |
39 + abcd_instance)
40 +abcd_access_list: abcd_access (',' abcd_access)*
41 +abcd_access: (NAME '+' '(' testlist ')' |
42 + NAME '?' '(' testlist ')' |
43 + NAME '-' '(' testlist ')' |
44 + NAME '<>' '(' testlist '=' testlist ')' |
45 + NAME '>>' '(' NAME ')' |
46 + NAME '<<' '(' testlist_comp ')' |
47 + NAME '.' NAME '(' test (',' test)* ')')
48 +abcd_instance: [NAME ':' ':'] NAME '(' [arglist] ')'
49 +
50 +tfpdef: NAME [':' ('net' | 'buffer' | 'task')]
51 +
52 +abcd_prop: 'assert' test (NEWLINE)*
53 +
54 +#
55 +# the rest is from SNAKES/Python grammar
56 +#
57 +
58 +decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
59 +decorators: decorator+
60 +decorated: decorators (classdef | funcdef)
61 +funcdef: 'def' NAME parameters ['-' '>' test] ':' suite
62 +parameters: '(' [typedargslist] ')'
63 +typedargslist: ((tfpdef ['=' test] ',')*
64 + ('*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef]
65 + | '**' tfpdef)
66 + | tfpdef ['=' test] (',' tfpdef ['=' test])* [','])
67 +varargslist: ((vfpdef ['=' test] ',')*
68 + ('*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef]
69 + | '**' vfpdef)
70 + | vfpdef ['=' test] (',' vfpdef ['=' test])* [','])
71 +vfpdef: NAME
72 +
73 +stmt: simple_stmt | compound_stmt
74 +simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
75 +small_stmt: (expr_stmt | del_stmt | pass_stmt | flow_stmt |
76 + import_stmt | global_stmt | nonlocal_stmt | assert_stmt)
77 +expr_stmt: testlist (augassign (yield_expr|testlist) |
78 + ('=' (yield_expr|testlist))*)
79 +augassign: ('+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' |
80 + '<<=' | '>>=' | '**=' | '//=')
81 +del_stmt: 'del' exprlist
82 +pass_stmt: 'pass'
83 +flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt
84 +break_stmt: 'break'
85 +continue_stmt: 'continue'
86 +return_stmt: 'return' [testlist]
87 +yield_stmt: yield_expr
88 +raise_stmt: 'raise' [test ['from' test]]
89 +import_stmt: import_name | import_from
90 +import_name: 'import' dotted_as_names
91 +import_from: ('from' (('.' | '...')* dotted_name | ('.' | '...')+)
92 + 'import' ('*' | '(' import_as_names ')' | import_as_names))
93 +import_as_name: NAME ['as' NAME]
94 +dotted_as_name: dotted_name ['as' NAME]
95 +import_as_names: import_as_name (',' import_as_name)* [',']
96 +dotted_as_names: dotted_as_name (',' dotted_as_name)*
97 +dotted_name: NAME ('.' NAME)*
98 +global_stmt: 'global' NAME (',' NAME)*
99 +nonlocal_stmt: 'nonlocal' NAME (',' NAME)*
100 +assert_stmt: 'assert' test [',' test]
101 +
102 +compound_stmt: (if_stmt | while_stmt | for_stmt | try_stmt | with_stmt
103 + | funcdef | classdef | decorated)
104 +if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
105 +while_stmt: 'while' test ':' suite ['else' ':' suite]
106 +for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite]
107 +try_stmt: ('try' ':' suite
108 + ((except_clause ':' suite)+
109 + ['else' ':' suite]
110 + ['finally' ':' suite] |
111 + 'finally' ':' suite))
112 +with_stmt: 'with' test [ with_var ] ':' suite
113 +with_var: 'as' expr
114 +except_clause: 'except' [test ['as' NAME]]
115 +suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT
116 +
117 +test: or_test ['if' or_test 'else' test] | lambdef
118 +test_nocond: or_test | lambdef_nocond
119 +lambdef: 'lambda' [varargslist] ':' test
120 +lambdef_nocond: 'lambda' [varargslist] ':' test_nocond
121 +or_test: and_test ('or' and_test)*
122 +and_test: not_test ('and' not_test)*
123 +not_test: 'not' not_test | comparison
124 +comparison: star_expr (comp_op star_expr)*
125 +comp_op: '<'|'>'|'=='|'>='|'<='|'!='|'<>'|'in'|'not' 'in'|'is'|'is' 'not'
126 +star_expr: ['*'] expr
127 +expr: xor_expr ('|' xor_expr)*
128 +xor_expr: and_expr ('^' and_expr)*
129 +and_expr: shift_expr ('&' shift_expr)*
130 +shift_expr: arith_expr (('<<'|'>>') arith_expr)*
131 +arith_expr: term (('+'|'-') term)*
132 +term: factor (('*'|'/'|'%'|'//') factor)*
133 +factor: ('+'|'-'|'~') factor | power
134 +power: atom trailer* ['**' factor]
135 +atom: ('(' [yield_expr|testlist_comp] ')' |
136 + '[' [testlist_comp] ']' |
137 + '{' [dictorsetmaker] '}' |
138 + NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False')
139 +testlist_comp: test ( comp_for | (',' test)* [','] )
140 +trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
141 +subscriptlist: subscript (',' subscript)* [',']
142 +subscript: test | [test] ':' [test] [sliceop]
143 +sliceop: ':' [test]
144 +exprlist: star_expr (',' star_expr)* [',']
145 +testlist: test (',' test)* [',']
146 +dictorsetmaker: ( (test ':' test (comp_for | (',' test ':' test)* [','])) |
147 + (test (comp_for | (',' test)* [','])) )
148 +
149 +classdef: 'class' NAME ['(' [arglist] ')'] ':' suite
150 +
151 +arglist: (argument ',')* (argument [',']
152 + |'*' test (',' argument)* [',' '**' test]
153 + |'**' test)
154 +argument: test [comp_for] | test '=' test
155 +
156 +comp_iter: comp_for | comp_if
157 +comp_for: 'for' exprlist 'in' or_test [comp_iter]
158 +comp_if: 'if' test_nocond [comp_iter]
159 +
160 +yield_expr: 'yield' [testlist]
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff could not be displayed because it is too large.
1 +import sys, datetime
2 +from snakes.lang.pylib import asdl
3 +from collections import defaultdict
4 +from functools import partial
5 +
6 +class memoize(object):
7 + def __init__(self, function):
8 + self.function = function
9 + self.memoized = {}
10 +
11 + def __call__(self, *args):
12 + try:
13 + return self.memoized[args]
14 + except KeyError:
15 + call = self.function(*args)
16 + self.memoized[args] = call
17 + return call
18 +
19 + def __get__(self, obj, objtype):
20 + """Support instance methods."""
21 + return partial(self.__call__, obj)
22 +
23 +def component_has_cycle(node, graph, proceeding, visited):
24 + if node in visited:
25 + return False
26 + if node in proceeding:
27 + proceeding.append(node) # populate trace
28 + return True
29 + proceeding.append(node)
30 + if node in graph:
31 + for successor in graph[node]:
32 + if component_has_cycle(successor, graph, proceeding, visited):
33 + return True
34 + proceeding.remove(node)
35 + visited.add(node)
36 + return False
37 +
38 +def has_cycle(graph):
39 + visited = set()
40 + proceeding = list()
41 + todo = set(graph.keys())
42 +
43 + while todo:
44 + node = todo.pop()
45 + if component_has_cycle(node, graph, proceeding, visited):
46 + i = proceeding.index(proceeding[-1])
47 + return proceeding[i:]
48 + todo.difference_update(visited)
49 + return []
50 +
51 +class CyclicDependencies(Exception):
52 + def __init__(self, seq):
53 + self.seq = seq
54 +
55 + def __str__(self):
56 + return "cyclic dependencies: {}".format(" -> ".join(self.seq))
57 +
58 +def remove_duplicates(l):
59 + d = {}
60 + nl = []
61 + for e in l:
62 + if not e in d:
63 + d[e] = 1
64 + nl.append(e)
65 + return nl
66 +
67 +class CodeGen (asdl.VisitorBase) :
68 +
69 + def __init__(self, node):
70 + asdl.VisitorBase.__init__(self)
71 +
72 + self.starting_node = None
73 + self.current_node = None
74 + self.hierarchy = defaultdict(list)
75 + self.hierarchy['_AST'] = []
76 + self.fields = defaultdict(list)
77 + self.attributes = defaultdict(list)
78 + self.code = defaultdict(list)
79 +
80 + self.visit(node)
81 + ret = has_cycle(self.hierarchy)
82 + if ret:
83 + raise CyclicDependencies(ret)
84 + self._gen_code(node)
85 +
86 + def visitModule(self, node):
87 + for name, child in node.types.items():
88 + if not self.starting_node:
89 + self.starting_node = str(name)
90 + self.current_node = str(name)
91 + self.hierarchy[name]
92 + self.visit(child)
93 +
94 + def visitSum(self, node):
95 + if hasattr(node, "fields"):
96 + self.fields[self.current_node] = node.fields
97 + else:
98 + self.fields[self.current_node] = []
99 + if hasattr(node, "attributes"):
100 + self.attributes[self.current_node] = node.attributes
101 + else:
102 + self.attributes[self.current_node] = []
103 +
104 + for child in node.types:
105 + self.visit(child)
106 +
107 + def visitConstructor (self, node):
108 + if str(node.name) in self.fields:
109 + #print >> sys.stderr, "constructor '{!s}' appears twice !".format(node.name)
110 + #exit(0)
111 + return
112 + self.fields[str(node.name)].extend(node.fields)
113 + self.hierarchy[str(node.name)].append(self.current_node)
114 +
115 + def visitProduct(self, node):
116 + self.fields[self.current_node].extend(node.fields)
117 +
118 + @memoize
119 + def _get_fields(self, name):
120 + if self.fields.has_key(name):
121 + fields = map(lambda f : f.name, self.fields[name])
122 + for parent in self.hierarchy[name]:
123 + fields.extend(self._get_fields(parent))
124 + return fields
125 + else:
126 + return []
127 +
128 + @memoize
129 + def _get_attributes(self, name):
130 + if name == '_AST':
131 + return []
132 + attributes = map(lambda a : a.name, self.attributes[name])
133 + for parent in self.hierarchy[name]:
134 + attributes.extend(self._get_attributes(parent))
135 + return attributes
136 +
137 + def _gen_code(self, node):
138 + is_methods = []
139 + for name in sorted(self.hierarchy):
140 + if name != '_AST':
141 + is_methods.extend(["",
142 + "def is{!s}(self):".format(name),
143 + ["return False"]
144 + ])
145 + cls = ["class _AST (ast.AST):",
146 + ["_fields = ()",
147 + "_attributes = ()",
148 + "",
149 + "def __init__ (self, **ARGS):",
150 + ["ast.AST.__init__(self)",
151 + "for k, v in ARGS.items():",
152 + ["setattr(self, k, v)"]
153 + ]
154 + ] + is_methods
155 + ]
156 + self.code['_AST'] = cls
157 +
158 + for name, parents in self.hierarchy.iteritems():
159 + if name == '_AST':
160 + continue
161 + if not parents:
162 + parents = ['_AST']
163 + fields = self.fields[name]
164 + args = []
165 + assign = []
166 + body = []
167 + _fields = remove_duplicates(self._get_fields(name))
168 + _attributes = remove_duplicates(self._get_attributes(name))
169 +
170 + body = []
171 + cls = ["class {!s} ({!s}):".format(name, ", ".join(parents)), body]
172 +
173 + non_default_args = []
174 + default_args = []
175 + for f in fields:
176 + if f.name.value == 'ctx':
177 + f.opt = True
178 +
179 + if f.opt:
180 + default_args.append("{!s}=None".format(f.name))
181 + assign.append("self.{0!s} = {0!s}".format(f.name))
182 + elif f.seq:
183 + default_args.append("{!s}=[]".format(f.name))
184 + assign.append("self.{0!s} = list({0!s})".format(f.name))
185 + else:
186 + non_default_args.append("{!s}".format(f.name))
187 + assign.append("self.{0!s} = {0!s}".format(f.name))
188 +
189 + args = non_default_args + default_args
190 +
191 + body.append("_fields = {!r}".format( tuple(map(repr, _fields))))
192 + body.append("_attributes = {!r}".format( tuple(map(repr, _attributes))))
193 + body.append("")
194 + # ctor
195 + args_str = ", ".join(args)
196 + if args_str != "":
197 + args_str += ", "
198 + body.append("def __init__ (self, {!s} **ARGS):".format(args_str))
199 + ctor_body = []
200 + body.append(ctor_body)
201 + ctor_body.extend(map(lambda base : "{!s}.__init__(self, **ARGS)".format(base), parents))
202 + ctor_body.extend(assign)
203 +
204 + body.extend(["", "def is{}(self):".format(name), ["return True"]])
205 +
206 + self.code[name] = cls
207 +
208 + @memoize
209 + def _cost(self, name):
210 + # print "call cost {}".format(name)
211 + if name == '_AST':
212 + return 0
213 + parents = self.hierarchy[name]
214 + return reduce(lambda acc, x: acc + self._cost(x), parents, 1)
215 +
216 + @property
217 + def python(self):
218 +
219 + classes = self.hierarchy.keys()
220 + classes.sort(lambda a, b: self._cost(a) - self._cost(b))
221 +
222 + code = ["from snakes.lang import ast",
223 + "from ast import *",
224 + ""]
225 +
226 + for cls in classes:
227 + code.extend(self.code[cls])
228 + code.append("")
229 +
230 + def python (code, indent) :
231 + for line in code :
232 + if isinstance(line, str) :
233 + yield (4*indent) * " " + line
234 + else :
235 + for sub in python(line, indent+1) :
236 + yield sub
237 + return "\n".join(python(code, 0))
238 +
239 +def compile_asdl(infilename, outfilename):
240 + """ Helper function to compile asdl files. """
241 +
242 + infile = open(infilename, 'r')
243 + outfile = open(outfilename, 'w')
244 +
245 + scanner = asdl.ASDLScanner()
246 + parser = asdl.ASDLParser()
247 + tokens = scanner.tokenize(infile.read())
248 + node = parser.parse(tokens)
249 +
250 + outfile.write(("# this file has been automatically generated running:\n"
251 + "# %s\n# timestamp: %s\n\n") % (" ".join(sys.argv),
252 + datetime.datetime.now()))
253 + outfile.write(CodeGen(node).python)
254 + outfile.close()
255 + infile.close()
256 +
257 +if __name__ == "__main__":
258 + # a simple CLI
259 + import getopt
260 + outfile = sys.stdout
261 + try :
262 + opts, args = getopt.getopt(sys.argv[1:], "ho:",
263 + ["help", "output="])
264 + if ("-h", "") in opts or ("--help", "") in opts :
265 + opts = [("-h", "")]
266 + args = [None]
267 + elif not args :
268 + raise getopt.GetoptError("no input file provided"
269 + " (try -h to get help)")
270 + elif len(args) > 1 :
271 + raise getopt.GetoptError("more than one input file provided")
272 + except getopt.GetoptError :
273 + sys.stderr.write("%s: %s\n" % (__file__, sys.exc_info()[1]))
274 + sys.exit(1)
275 + for (flag, arg) in opts :
276 + if flag in ("-h", "--help") :
277 + print("""usage: %s [OPTIONS] INFILE
278 + Options:
279 + -h, --help print this help and exit
280 + --output=OUTPUT set output file""" % __file__)
281 + sys.exit(0)
282 + elif flag in ("-o", "--output") :
283 + outfile = open(arg, "w")
284 + scanner = asdl.ASDLScanner()
285 + parser = asdl.ASDLParser()
286 + tokens = scanner.tokenize(open(args[0]).read())
287 + node = parser.parse(tokens)
288 + outfile.write(("# this file has been automatically generated running:\n"
289 + "# %s\n# timestamp: %s\n\n") % (" ".join(sys.argv),
290 + datetime.datetime.now()))
291 + try:
292 + outfile.write(CodeGen(node).python)
293 + except CyclicDependencies as cycle:
294 + msg = "[E] {!s}".format(cycle)
295 + outfile.write(msg)
296 + if outfile != sys.stdout:
297 + print >> sys.stderr, msg
298 + outfile.close()
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
1 +module CTLstar version "$Revision: 1 $"
2 +{
3 + ctlstar = Spec(ctldecl* atoms, ctldecl* properties, form? main)
4 + attributes (int lineno, int col_offset)
5 +
6 + ctldecl = Atom(identifier name, ctlarg* args, ctlparams* params,
7 + stmt* body)
8 + | Property(identifier name, ctlargs* args,
9 + ctlparams* params, form body)
10 + attributes (int lineno, int col_offset)
11 +
12 + ctlarg = Place(identifier name, string place)
13 + | Token(identifier name, string place)
14 + | Argument(identifier name, expr value, identifier type)
15 + attributes (int lineno, int col_offset)
16 +
17 + ctlparam = Parameter(identifier name, identifier type)
18 + attributes (int lineno, int col_offset)
19 +
20 + form = atom
21 + | CtlUnary(ctlunary op, form child)
22 + | CtlBinary(ctlbinary op, form left, form right)
23 + attributes (int lineno, int col_offset)
24 +
25 + ctlunary = notop | All | Exists | Next | Future | Globally
26 +
27 + notop = Not
28 +
29 + ctlbinary = boolop | Imply | Iff | Until | WeakUntil | Release
30 +
31 + atom = InPlace(expr* data, ctlarg place)
32 + | NotInPlace(expr* data, ctlarg place)
33 + | EmptyPlace(ctlarg place)
34 + | MarkedPlace(ctlarg place)
35 + | Deadlock
36 + | Boolean(bool val)
37 + | Instance(identifier name, arg* args)
38 + | Quantifier(ctlunary op,
39 + identifier* vars,
40 + ctlarg place,
41 + form child,
42 + bool distinct)
43 + attributes (int lineno, int col_offset)
44 +
45 + --------------------------------------------------------------
46 + -- the rest is copied from "snakes/lang/python/python.asdl" --
47 + --------------------------------------------------------------
48 +
49 + stmt = FunctionDef(identifier name, arguments args,
50 + stmt* body, expr* decorator_list, expr? returns)
51 + | ClassDef(identifier name,
52 + expr* bases,
53 + keyword* keywords,
54 + expr? starargs,
55 + expr? kwargs,
56 + stmt* body,
57 + expr *decorator_list)
58 + | Return(expr? value)
59 +
60 + | Delete(expr* targets)
61 + | Assign(expr* targets, expr value)
62 + | AugAssign(expr target, operator op, expr value)
63 +
64 + | For(expr target, expr iter, stmt* body, stmt* orelse)
65 + | While(expr test, stmt* body, stmt* orelse)
66 + | If(expr test, stmt* body, stmt* orelse)
67 + | With(expr context_expr, expr? optional_vars, stmt* body)
68 +
69 + | Raise(expr? exc, expr? cause)
70 + | TryExcept(stmt* body, excepthandler* handlers, stmt* orelse)
71 + | TryFinally(stmt* body, stmt* finalbody)
72 + | Assert(expr test, expr? msg)
73 +
74 + | Import(alias* names)
75 + | ImportFrom(identifier module, alias* names, int? level)
76 +
77 + | Exec(expr body, expr? globals, expr? locals)
78 +
79 + | Global(identifier* names)
80 + | Nonlocal(identifier* names)
81 + | Expr(expr value)
82 + | Pass | Break | Continue
83 +
84 + attributes (int lineno, int col_offset)
85 +
86 + expr = BoolOp(boolop op, expr* values)
87 + | BinOp(expr left, operator op, expr right)
88 + | UnaryOp(unaryop op, expr operand)
89 + | Lambda(arguments args, expr body)
90 + | IfExp(expr test, expr body, expr orelse)
91 + | Dict(expr* keys, expr* values)
92 + | Set(expr* elts)
93 + | ListComp(expr elt, comprehension* generators)
94 + | SetComp(expr elt, comprehension* generators)
95 + | DictComp(expr key, expr value, comprehension* generators)
96 + | GeneratorExp(expr elt, comprehension* generators)
97 + | Yield(expr? value)
98 + | Compare(expr left, cmpop* ops, expr* comparators)
99 + | Call(expr func, expr* args, keyword* keywords,
100 + expr? starargs, expr? kwargs)
101 + | Num(object n)
102 + | Str(string s)
103 + | Ellipsis
104 +
105 + | Attribute(expr value, identifier attr, expr_context ctx)
106 + | Subscript(expr value, slice slice, expr_context ctx)
107 + | Starred(expr value, expr_context ctx)
108 + | Name(identifier id, expr_context ctx)
109 + | List(expr* elts, expr_context ctx)
110 + | Tuple(expr* elts, expr_context ctx)
111 +
112 + attributes (int lineno, int col_offset)
113 +
114 + expr_context = Load | Store | Del | AugLoad | AugStore | Param
115 +
116 + slice = Slice(expr? lower, expr? upper, expr? step)
117 + | ExtSlice(slice* dims)
118 + | Index(expr value)
119 +
120 + boolop = And | Or
121 +
122 + operator = Add | Sub | Mult | Div | Mod | Pow | LShift
123 + | RShift | BitOr | BitXor | BitAnd | FloorDiv
124 +
125 + unaryop = Invert | notop | UAdd | USub
126 +
127 + cmpop = Eq | NotEq | Lt | LtE | Gt | GtE | Is | IsNot | In | NotIn
128 +
129 + comprehension = (expr target, expr iter, expr* ifs)
130 +
131 + excepthandler = ExceptHandler(expr? type, identifier? name, stmt* body)
132 + attributes (int lineno, int col_offset)
133 +
134 + arguments = (arg* args, identifier? vararg, expr? varargannotation,
135 + arg* kwonlyargs, identifier? kwarg,
136 + expr? kwargannotation, expr* defaults,
137 + expr* kw_defaults)
138 + arg = (identifier arg, expr? annotation)
139 +
140 + keyword = (identifier arg, expr value)
141 +
142 + alias = (identifier name, identifier? asname)
143 +}
1 +# Grammar for (permissive) CTL*
2 +
3 +# new tokens
4 +$ELLIPSIS '...'
5 +
6 +file_input: (NEWLINE | ctl_atomdef | ctl_propdef)* [ ctl_formula ] NEWLINE* ENDMARKER
7 +
8 +ctl_atomdef: 'atom' NAME '(' [ctl_parameters] ')' ':' suite
9 +ctl_propdef: 'prop' NAME '(' [ctl_parameters] ')' ':' ctl_suite
10 +ctl_suite: ( ctl_formula NEWLINE
11 + | NEWLINE INDENT ctl_formula NEWLINE+ DEDENT )
12 +ctl_parameters: (ctl_param ',')* ctl_param
13 +ctl_param: NAME ( '=' '@' STRING+ | ':' NAME )
14 +
15 +ctl_formula: ctl_or_formula [ ctl_connector ctl_or_formula ]
16 +ctl_connector: ( '=' '>' | '<=' '>' )
17 +ctl_or_formula: ctl_and_formula ('or' ctl_and_formula)*
18 +ctl_and_formula: ctl_not_formula ('and' ctl_not_formula)*
19 +ctl_not_formula: ('not' ctl_not_formula | ctl_binary_formula)
20 +ctl_binary_formula: ctl_unary_formula [ ctl_binary_op ctl_unary_formula ]
21 +ctl_unary_formula: [ ctl_unary_op ] (ctl_atom_formula | '(' ctl_formula ')')
22 +ctl_unary_op: ('A' | 'G' | 'F' | 'E' | 'X')
23 +ctl_binary_op: ('R' | 'U' | 'W')
24 +ctl_atom_formula: ( 'empty' '(' ctl_place ')'
25 + | 'marked' '(' ctl_place ')'
26 + | 'has' ['not'] '(' ctl_place ',' test (',' test)* ')'
27 + | 'deadlock' | 'True' | 'False'
28 + | NAME '(' ctl_arguments ')'
29 + | 'forall' [ 'distinct' ] NAME (',' NAME)*
30 + 'in' ctl_place '(' ctl_atom_formula ')'
31 + | 'exists' [ 'distinct' ] NAME (',' NAME)*
32 + 'in' ctl_place '(' ctl_atom_formula ')' )
33 +ctl_arguments: (NAME '=' ctl_place_or_test ',')* NAME '=' ctl_place_or_test
34 +ctl_place: '@' STRING+ | NAME
35 +ctl_place_or_test: test | '@' STRING+
36 +
37 +#
38 +# the rest is from SNAKES/Python grammar
39 +#
40 +
41 +decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
42 +decorators: decorator+
43 +decorated: decorators (classdef | funcdef)
44 +funcdef: 'def' NAME parameters ['-' '>' test] ':' suite
45 +parameters: '(' [typedargslist] ')'
46 +typedargslist: ((tfpdef ['=' test] ',')*
47 + ('*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef]
48 + | '**' tfpdef)
49 + | tfpdef ['=' test] (',' tfpdef ['=' test])* [','])
50 +tfpdef: NAME [':' test]
51 +varargslist: ((vfpdef ['=' test] ',')*
52 + ('*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef]
53 + | '**' vfpdef)
54 + | vfpdef ['=' test] (',' vfpdef ['=' test])* [','])
55 +vfpdef: NAME
56 +
57 +stmt: simple_stmt | compound_stmt
58 +simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
59 +small_stmt: (expr_stmt | del_stmt | pass_stmt | flow_stmt |
60 + import_stmt | global_stmt | nonlocal_stmt | assert_stmt)
61 +expr_stmt: testlist (augassign (yield_expr|testlist) |
62 + ('=' (yield_expr|testlist))*)
63 +augassign: ('+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' |
64 + '<<=' | '>>=' | '**=' | '//=')
65 +del_stmt: 'del' exprlist
66 +pass_stmt: 'pass'
67 +flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt
68 +break_stmt: 'break'
69 +continue_stmt: 'continue'
70 +return_stmt: 'return' [testlist]
71 +yield_stmt: yield_expr
72 +raise_stmt: 'raise' [test ['from' test]]
73 +import_stmt: import_name | import_from
74 +import_name: 'import' dotted_as_names
75 +import_from: ('from' (('.' | '...')* dotted_name | ('.' | '...')+)
76 + 'import' ('*' | '(' import_as_names ')' | import_as_names))
77 +import_as_name: NAME ['as' NAME]
78 +dotted_as_name: dotted_name ['as' NAME]
79 +import_as_names: import_as_name (',' import_as_name)* [',']
80 +dotted_as_names: dotted_as_name (',' dotted_as_name)*
81 +dotted_name: NAME ('.' NAME)*
82 +global_stmt: 'global' NAME (',' NAME)*
83 +nonlocal_stmt: 'nonlocal' NAME (',' NAME)*
84 +assert_stmt: 'assert' test [',' test]
85 +
86 +compound_stmt: (if_stmt | while_stmt | for_stmt | try_stmt | with_stmt
87 + | funcdef | classdef | decorated)
88 +if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
89 +while_stmt: 'while' test ':' suite ['else' ':' suite]
90 +for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite]
91 +try_stmt: ('try' ':' suite
92 + ((except_clause ':' suite)+
93 + ['else' ':' suite]
94 + ['finally' ':' suite] |
95 + 'finally' ':' suite))
96 +with_stmt: 'with' test [ with_var ] ':' suite
97 +with_var: 'as' expr
98 +except_clause: 'except' [test ['as' NAME]]
99 +suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT
100 +
101 +test: or_test ['if' or_test 'else' test] | lambdef
102 +test_nocond: or_test | lambdef_nocond
103 +lambdef: 'lambda' [varargslist] ':' test
104 +lambdef_nocond: 'lambda' [varargslist] ':' test_nocond
105 +or_test: and_test ('or' and_test)*
106 +and_test: not_test ('and' not_test)*
107 +not_test: 'not' not_test | comparison
108 +comparison: star_expr (comp_op star_expr)*
109 +comp_op: '<'|'>'|'=='|'>='|'<='|'!='|'<>'|'in'|'not' 'in'|'is'|'is' 'not'
110 +star_expr: ['*'] expr
111 +expr: xor_expr ('|' xor_expr)*
112 +xor_expr: and_expr ('^' and_expr)*
113 +and_expr: shift_expr ('&' shift_expr)*
114 +shift_expr: arith_expr (('<<'|'>>') arith_expr)*
115 +arith_expr: term (('+'|'-') term)*
116 +term: factor (('*'|'/'|'%'|'//') factor)*
117 +factor: ('+'|'-'|'~') factor | power
118 +power: atom trailer* ['**' factor]
119 +atom: ('(' [yield_expr|testlist_comp] ')' |
120 + '[' [testlist_comp] ']' |
121 + '{' [dictorsetmaker] '}' |
122 + NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False')
123 +testlist_comp: test ( comp_for | (',' test)* [','] )
124 +trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
125 +subscriptlist: subscript (',' subscript)* [',']
126 +subscript: test | [test] ':' [test] [sliceop]
127 +sliceop: ':' [test]
128 +exprlist: star_expr (',' star_expr)* [',']
129 +testlist: test (',' test)* [',']
130 +dictorsetmaker: ( (test ':' test (comp_for | (',' test ':' test)* [','])) |
131 + (test (comp_for | (',' test)* [','])) )
132 +
133 +classdef: 'class' NAME ['(' [arglist] ')'] ':' suite
134 +
135 +arglist: (argument ',')* (argument [',']
136 + |'*' test (',' argument)* [',' '**' test]
137 + |'**' test)
138 +argument: test [comp_for] | test '=' test
139 +
140 +comp_iter: comp_for | comp_if
141 +comp_for: 'for' exprlist 'in' or_test [comp_iter]
142 +comp_if: 'if' test_nocond [comp_iter]
143 +
144 +yield_expr: 'yield' [testlist]
This diff is collapsed. Click to expand it.
This diff could not be displayed because it is too large.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff could not be displayed because it is too large.
1 +module Python version "$Revision: SNAKES $"
2 +{
3 + mod = Module(stmt* body)
4 + | Interactive(stmt* body)
5 + | Expression(expr body)
6 + | Suite(stmt* body)
7 +
8 + stmt = FunctionDef(identifier name, arguments args,
9 + stmt* body, expr* decorator_list, expr? returns)
10 + | ClassDef(identifier name,
11 + expr* bases,
12 + keyword* keywords,
13 + expr? starargs,
14 + expr? kwargs,
15 + stmt* body,
16 + expr *decorator_list)
17 + | Return(expr? value)
18 +
19 + | Delete(expr* targets)
20 + | Assign(expr* targets, expr value)
21 + | AugAssign(expr target, operator op, expr value)
22 +
23 + | For(expr target, expr iter, stmt* body, stmt* orelse)
24 + | While(expr test, stmt* body, stmt* orelse)
25 + | If(expr test, stmt* body, stmt* orelse)
26 + | With(expr context_expr, expr? optional_vars, stmt* body)
27 +
28 + | Raise(expr? exc, expr? cause)
29 + | TryExcept(stmt* body, excepthandler* handlers, stmt* orelse)
30 + | TryFinally(stmt* body, stmt* finalbody)
31 + | Assert(expr test, expr? msg)
32 +
33 + | Import(alias* names)
34 + | ImportFrom(identifier module, alias* names, int? level)
35 +
36 + | Exec(expr body, expr? globals, expr? locals)
37 +
38 + | Global(identifier* names)
39 + | Nonlocal(identifier* names)
40 + | Expr(expr value)
41 + | Pass | Break | Continue
42 +
43 + attributes (int lineno, int col_offset)
44 +
45 + expr = BoolOp(boolop op, expr* values)
46 + | BinOp(expr left, operator op, expr right)
47 + | UnaryOp(unaryop op, expr operand)
48 + | Lambda(arguments args, expr body)
49 + | IfExp(expr test, expr body, expr orelse)
50 + | Dict(expr* keys, expr* values)
51 + | Set(expr* elts)
52 + | ListComp(expr elt, comprehension* generators)
53 + | SetComp(expr elt, comprehension* generators)
54 + | DictComp(expr key, expr value, comprehension* generators)
55 + | GeneratorExp(expr elt, comprehension* generators)
56 + | Yield(expr? value)
57 + | Compare(expr left, cmpop* ops, expr* comparators)
58 + | Call(expr func, expr* args, keyword* keywords,
59 + expr? starargs, expr? kwargs)
60 + | Num(object n)
61 + | Str(string s)
62 + | Ellipsis
63 +
64 + | Attribute(expr value, identifier attr, expr_context ctx)
65 + | Subscript(expr value, slice slice, expr_context ctx)
66 + | Starred(expr value, expr_context ctx)
67 + | Name(identifier id, expr_context ctx)
68 + | List(expr* elts, expr_context ctx)
69 + | Tuple(expr* elts, expr_context ctx)
70 +
71 + attributes (int lineno, int col_offset)
72 +
73 + expr_context = Load | Store | Del | AugLoad | AugStore | Param
74 +
75 + slice = Slice(expr? lower, expr? upper, expr? step)
76 + | ExtSlice(slice* dims)
77 + | Index(expr value)
78 +
79 + boolop = And | Or
80 +
81 + operator = Add | Sub | Mult | Div | Mod | Pow | LShift
82 + | RShift | BitOr | BitXor | BitAnd | FloorDiv
83 +
84 + unaryop = Invert | Not | UAdd | USub
85 +
86 + cmpop = Eq | NotEq | Lt | LtE | Gt | GtE | Is | IsNot | In | NotIn
87 +
88 + comprehension = (expr target, expr iter, expr* ifs)
89 +
90 + excepthandler = ExceptHandler(expr? type, identifier? name, stmt* body)
91 + attributes (int lineno, int col_offset)
92 +
93 + arguments = (arg* args, identifier? vararg, expr? varargannotation,
94 + arg* kwonlyargs, identifier? kwarg,
95 + expr? kwargannotation, expr* defaults,
96 + expr* kw_defaults)
97 + arg = (identifier arg, expr? annotation)
98 +
99 + keyword = (identifier arg, expr value)
100 +
101 + alias = (identifier name, identifier? asname)
102 +}
1 +# Grammar for Python in SNAKES
2 +# This is a mixture of the grammars from various Python versions
3 +
4 +$ELLIPSIS '...'
5 +
6 +file_input: (NEWLINE | stmt)* ENDMARKER
7 +
8 +decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE
9 +decorators: decorator+
10 +decorated: decorators (classdef | funcdef)
11 +funcdef: 'def' NAME parameters ['-' '>' test] ':' suite
12 +parameters: '(' [typedargslist] ')'
13 +typedargslist: ((tfpdef ['=' test] ',')*
14 + ('*' [tfpdef] (',' tfpdef ['=' test])* [',' '**' tfpdef]
15 + | '**' tfpdef)
16 + | tfpdef ['=' test] (',' tfpdef ['=' test])* [','])
17 +tfpdef: NAME [':' test]
18 +varargslist: ((vfpdef ['=' test] ',')*
19 + ('*' [vfpdef] (',' vfpdef ['=' test])* [',' '**' vfpdef]
20 + | '**' vfpdef)
21 + | vfpdef ['=' test] (',' vfpdef ['=' test])* [','])
22 +vfpdef: NAME
23 +
24 +stmt: simple_stmt | compound_stmt
25 +simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
26 +small_stmt: (expr_stmt | del_stmt | pass_stmt | flow_stmt |
27 + import_stmt | global_stmt | nonlocal_stmt | assert_stmt)
28 +expr_stmt: testlist (augassign (yield_expr|testlist) |
29 + ('=' (yield_expr|testlist))*)
30 +augassign: ('+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' |
31 + '<<=' | '>>=' | '**=' | '//=')
32 +del_stmt: 'del' exprlist
33 +pass_stmt: 'pass'
34 +flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt
35 +break_stmt: 'break'
36 +continue_stmt: 'continue'
37 +return_stmt: 'return' [testlist]
38 +yield_stmt: yield_expr
39 +raise_stmt: 'raise' [test ['from' test]]
40 +import_stmt: import_name | import_from
41 +import_name: 'import' dotted_as_names
42 +import_from: ('from' (('.' | '...')* dotted_name | ('.' | '...')+)
43 + 'import' ('*' | '(' import_as_names ')' | import_as_names))
44 +import_as_name: NAME ['as' NAME]
45 +dotted_as_name: dotted_name ['as' NAME]
46 +import_as_names: import_as_name (',' import_as_name)* [',']
47 +dotted_as_names: dotted_as_name (',' dotted_as_name)*
48 +dotted_name: NAME ('.' NAME)*
49 +global_stmt: 'global' NAME (',' NAME)*
50 +nonlocal_stmt: 'nonlocal' NAME (',' NAME)*
51 +assert_stmt: 'assert' test [',' test]
52 +
53 +compound_stmt: (if_stmt | while_stmt | for_stmt | try_stmt | with_stmt
54 + | funcdef | classdef | decorated)
55 +if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
56 +while_stmt: 'while' test ':' suite ['else' ':' suite]
57 +for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite]
58 +try_stmt: ('try' ':' suite
59 + ((except_clause ':' suite)+
60 + ['else' ':' suite]
61 + ['finally' ':' suite] |
62 + 'finally' ':' suite))
63 +with_stmt: 'with' test [ with_var ] ':' suite
64 +with_var: 'as' expr
65 +except_clause: 'except' [test ['as' NAME]]
66 +suite: simple_stmt | NEWLINE INDENT stmt+ DEDENT
67 +
68 +test: or_test ['if' or_test 'else' test] | lambdef
69 +test_nocond: or_test | lambdef_nocond
70 +lambdef: 'lambda' [varargslist] ':' test
71 +lambdef_nocond: 'lambda' [varargslist] ':' test_nocond
72 +or_test: and_test ('or' and_test)*
73 +and_test: not_test ('and' not_test)*
74 +not_test: 'not' not_test | comparison
75 +comparison: star_expr (comp_op star_expr)*
76 +comp_op: '<'|'>'|'=='|'>='|'<='|'!='|'<>'|'in'|'not' 'in'|'is'|'is' 'not'
77 +star_expr: ['*'] expr
78 +expr: xor_expr ('|' xor_expr)*
79 +xor_expr: and_expr ('^' and_expr)*
80 +and_expr: shift_expr ('&' shift_expr)*
81 +shift_expr: arith_expr (('<<'|'>>') arith_expr)*
82 +arith_expr: term (('+'|'-') term)*
83 +term: factor (('*'|'/'|'%'|'//') factor)*
84 +factor: ('+'|'-'|'~') factor | power
85 +power: atom trailer* ['**' factor]
86 +atom: ('(' [yield_expr|testlist_comp] ')' |
87 + '[' [testlist_comp] ']' |
88 + '{' [dictorsetmaker] '}' |
89 + NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False')
90 +testlist_comp: test ( comp_for | (',' test)* [','] )
91 +trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME
92 +subscriptlist: subscript (',' subscript)* [',']
93 +subscript: test | [test] ':' [test] [sliceop]
94 +sliceop: ':' [test]
95 +exprlist: star_expr (',' star_expr)* [',']
96 +testlist: test (',' test)* [',']
97 +dictorsetmaker: ( (test ':' test (comp_for | (',' test ':' test)* [','])) |
98 + (test (comp_for | (',' test)* [','])) )
99 +
100 +classdef: 'class' NAME ['(' [arglist] ')'] ':' suite
101 +
102 +arglist: (argument ',')* (argument [',']
103 + |'*' test (',' argument)* [',' '**' test]
104 + |'**' test)
105 +argument: test [comp_for] | test '=' test
106 +
107 +comp_iter: comp_for | comp_if
108 +comp_for: 'for' exprlist 'in' or_test [comp_iter]
109 +comp_if: 'if' test_nocond [comp_iter]
110 +
111 +yield_expr: 'yield' [testlist]
This diff is collapsed. Click to expand it.
This diff could not be displayed because it is too large.
1 +"""A plugins system.
2 +
3 +The first example shows how to load a plugin: we load
4 +C{snakes.plugins.hello} and plug it into C{snakes.nets}, which results
5 +in a new module that actually C{snakes.nets} extended by
6 +C{snakes.plugins.hello}.
7 +
8 +>>> import snakes.plugins as plugins
9 +>>> hello_nets = plugins.load('hello', 'snakes.nets')
10 +>>> n = hello_nets.PetriNet('N')
11 +>>> n.hello()
12 +Hello from N
13 +>>> n = hello_nets.PetriNet('N', hello='Hi, this is %s!')
14 +>>> n.hello()
15 +Hi, this is N!
16 +
17 +The next example shows how to simulate the effect of C{import module}:
18 +we give to C{load} a thrid argument that is the name of the created
19 +module, from which it becomes possible to import names or C{*}.
20 +
21 +B{Warning:} this feature will not work C{load} is not called from the
22 +module where we then do the C{from ... import ...}. This is exactly
23 +the same when, from a module C{foo} that you load a module C{bar}: if
24 +C{bar} loads other modules they will not be imported in C{foo}.
25 +
26 +>>> plugins.load('hello', 'snakes.nets', 'another_version')
27 +<module ...>
28 +>>> from another_version import PetriNet
29 +>>> n = PetriNet('another net')
30 +>>> n.hello()
31 +Hello from another net
32 +>>> n = PetriNet('yet another net', hello='Hi, this is %s!')
33 +>>> n.hello()
34 +Hi, this is yet another net!
35 +
36 +How to define a plugin is explained in the example C{hello}.
37 +"""
38 +
39 +import imp, sys, inspect
40 +from functools import wraps
41 +
42 +def update (module, objects) :
43 + """Update a module content
44 + """
45 + for obj in objects :
46 + if isinstance(obj, tuple) :
47 + try :
48 + n, o = obj
49 + except :
50 + raise ValueError("expected (name, object) and got '%r'" % obj)
51 + setattr(module, n, o)
52 + elif inspect.isclass(obj) or inspect.isfunction(obj) :
53 + setattr(module, obj.__name__, obj)
54 + else :
55 + raise ValueError("cannot plug '%r'" % obj)
56 +
57 +def build (name, module, *objects) :
58 + """Builds an extended module.
59 +
60 + The parameter C{module} is exactly that taken by the function
61 + C{extend} of a plugin. This list argument C{objects} holds all the
62 + objects, constructed in C{extend}, that are extensions of objects
63 + from C{module}. The resulting value should be returned by
64 + C{extend}.
65 +
66 + @param name: the name of the constructed module
67 + @type name: C{str}
68 + @param module: the extended module
69 + @type module: C{module}
70 + @param objects: the sub-objects
71 + @type objects: each is a class object
72 + @return: the new module
73 + @rtype: C{module}
74 + """
75 + result = imp.new_module(name)
76 + result.__dict__.update(module.__dict__)
77 + update(result, objects)
78 + result.__plugins__ = (module.__dict__.get("__plugins__",
79 + (module.__name__,))
80 + + (name,))
81 + for obj in objects :
82 + if inspect.isclass(obj) :
83 + obj.__plugins__ = result.__plugins__
84 + return result
85 +
86 +def load (plugins, base, name=None) :
87 + """Load plugins.
88 +
89 + C{plugins} can be a single plugin name or module or a list of such
90 + values. If C{name} is not C{None}, the extended module is loaded
91 + ad C{name} in C{sys.modules} as well as in the global environment
92 + from which C{load} was called.
93 +
94 + @param plugins: the module that implements the plugin, or its name,
95 + or a collection of such values
96 + @type plugins: C{str} or C{module}, or a C{list}/C{tuple}/... of
97 + such values
98 + @param base: the module being extended or its name
99 + @type base: C{str} or C{module}
100 + @param name: the name of the created module
101 + @type name: C{str}
102 + @return: the extended module
103 + @rtype: C{module}
104 + """
105 + if type(base) is str :
106 + result = __import__(base, fromlist=["__name__"])
107 + else :
108 + result = base
109 + if isinstance(plugins, str) :
110 + plugins = [plugins]
111 + else :
112 + try :
113 + plugins = list(plugins)
114 + except TypeError :
115 + plugins = [plugins]
116 + for i, p in enumerate(plugins) :
117 + if isinstance(p, str) and not p.startswith("snakes.plugins.") :
118 + plugins[i] = "snakes.plugins." + p
119 + for plug in plugins :
120 + if type(plug) is str :
121 + plug = __import__(plug, fromlist=["__name__"])
122 + result = plug.extend(result)
123 + if name is not None :
124 + result.__name__ = name
125 + sys.modules[name] = result
126 + inspect.stack()[1][0].f_globals[name] = result
127 + return result
128 +
129 +def plugin (base, depends=[], conflicts=[]) :
130 + """Decorator for extension functions
131 +
132 + @param base: name of base module (usually 'snakes.nets')
133 + @type base: str
134 + @param depends: list of plugins on which this one depends
135 + @type depends: list of str
136 + @param conflicts: list of plugins with which this one conflicts
137 + @type conflicts: list of str
138 + @return: the appropriate decorator
139 + @rtype: function
140 + """
141 + def wrapper (fun) :
142 + @wraps(fun)
143 + def extend (module) :
144 + try :
145 + loaded = set(module.__plugins__)
146 + except AttributeError :
147 + loaded = set()
148 + for name in depends :
149 + if name not in loaded :
150 + module = load(name, module)
151 + loaded.update(module.__plugins__)
152 + conf = set(conflicts) & loaded
153 + if len(conf) > 0 :
154 + raise ValueError("plugin conflict (%s)" % ", ".join(conf))
155 + objects = fun(module)
156 + if type(objects) is not tuple :
157 + objects = (objects,)
158 + return build(fun.__module__, module, *objects)
159 + module = sys.modules[fun.__module__]
160 + module.__test__ = {"extend" : extend}
161 + objects = fun(__import__(base, fromlist=["__name__"]))
162 + if type(objects) is not tuple :
163 + objects = (objects,)
164 + update(module, objects)
165 + return extend
166 + return wrapper
167 +
168 +def new_instance (cls, obj) :
169 + """Create a copy of C{obj} which is an instance of C{cls}
170 + """
171 + result = object.__new__(cls)
172 + result.__dict__.update(obj.__dict__)
173 + return result
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
1 +"""An example plugin that allows instances class C{PetriNet} to say hello.
2 +
3 +A new method C{hello} is added. The constructor is added a keyword
4 +argument C{hello} that must be the C{str} to print when calling
5 +C{hello}, with one C{%s} that will be replaced by the name of the net
6 +when C{hello} is called.
7 +
8 +Defining a plugins need writing a module with a single function called
9 +C{extend} that takes a single argument that is the module to be
10 +extended.
11 +
12 +Inside the function, extensions of the classes in the module are
13 +defined as normal sub-classes.
14 +
15 +The function C{extend} should return the extended module created by
16 +C{snakes.plugins.build} that takes as arguments: the name of the
17 +extended module, the module taken as argument and the sub-classes
18 +defined (expected as a list argument C{*args} in no special order).
19 +
20 +If the plugin depends on other plugins, for instance C{foo} and
21 +C{bar}, the function C{extend} should be decorated by
22 +C{@depends('foo', 'bar')}.
23 +
24 +Read the source code of this module to have an example
25 +"""
26 +
27 +import snakes.plugins
28 +
29 +@snakes.plugins.plugin("snakes.nets")
30 +def extend (module) :
31 + """Extends C{module}
32 + """
33 + class PetriNet (module.PetriNet) :
34 + """Extension of the class C{PetriNet} in C{module}
35 + """
36 + def __init__ (self, name, **args) :
37 + """When extending an existing method, take care that you
38 + may be working on an already extended class, so you so not
39 + know how its arguments have been changed. So, always use
40 + those from the unextended class plus C{**args}, remove
41 + from it what your plugin needs and pass it to the method
42 + of the extended class if you need to call it.
43 +
44 + >>> PetriNet('N').hello()
45 + Hello from N
46 + >>> PetriNet('N', hello='Hi! This is %s...').hello()
47 + Hi! This is N...
48 +
49 + @param args: plugin options
50 + @keyword hello: the message to print, with C{%s} where the
51 + net name should appear.
52 + @type hello: C{str}
53 + """
54 + self._hello = args.pop("hello", "Hello from %s")
55 + module.PetriNet.__init__(self, name, **args)
56 + def hello (self) :
57 + """A new method C{hello}
58 +
59 + >>> n = PetriNet('N')
60 + >>> n.hello()
61 + Hello from N
62 + """
63 + print(self._hello % self.name)
64 + return PetriNet
1 +"""A plugin to add labels to nodes and nets.
2 +
3 +"""
4 +
5 +from snakes.plugins import plugin, new_instance
6 +from snakes.pnml import Tree
7 +
8 +@plugin("snakes.nets")
9 +def extend (module) :
10 + class Transition (module.Transition) :
11 + def label (self, *get, **set) :
12 + if not hasattr(self, "_labels") :
13 + self._labels = {}
14 + result = tuple(self._labels[g] for g in get)
15 + self._labels.update(set)
16 + if len(get) == 1 :
17 + return result[0]
18 + elif len(get) > 1 :
19 + return result
20 + elif len(set) == 0 :
21 + return self._labels.copy()
22 + def has_label (self, name, *names) :
23 + if len(names) == 0 :
24 + return name in self._labels
25 + else :
26 + return tuple(n in self._labels for n in (name,) + names)
27 + def copy (self, name=None, **options) :
28 + if not hasattr(self, "_labels") :
29 + self._labels = {}
30 + result = module.Transition.copy(self, name, **options)
31 + result._labels = self._labels.copy()
32 + return result
33 + def __pnmldump__ (self) :
34 + """
35 + >>> t = Transition('t')
36 + >>> t.label(foo='bar', spam=42)
37 + >>> t.__pnmldump__()
38 + <?xml version="1.0" encoding="utf-8"?>
39 + <pnml>
40 + <transition id="t">
41 + <label name="foo">
42 + <object type="str">
43 + bar
44 + </object>
45 + </label>
46 + <label name="spam">
47 + <object type="int">
48 + 42
49 + </object>
50 + </label>
51 + </transition>
52 + </pnml>
53 + """
54 + t = module.Transition.__pnmldump__(self)
55 + if hasattr(self, "_labels") :
56 + for key, val in self._labels.items() :
57 + t.add_child(Tree("label", None,
58 + Tree.from_obj(val),
59 + name=key))
60 + return t
61 + @classmethod
62 + def __pnmlload__ (cls, tree) :
63 + """
64 + >>> old = Transition('t')
65 + >>> old.label(foo='bar', spam=42)
66 + >>> p = old.__pnmldump__()
67 + >>> new = Transition.__pnmlload__(p)
68 + >>> new
69 + Transition('t', Expression('True'))
70 + >>> new.__class__
71 + <class 'snakes.plugins.labels.Transition'>
72 + >>> new.label('foo', 'spam')
73 + ('bar', 42)
74 + """
75 + t = new_instance(cls, module.Transition.__pnmlload__(tree))
76 + t._labels = dict((lbl["name"], lbl.child().to_obj())
77 + for lbl in tree.get_children("label"))
78 + return t
79 + class Place (module.Place) :
80 + def label (self, *get, **set) :
81 + if not hasattr(self, "_labels") :
82 + self._labels = {}
83 + result = tuple(self._labels[g] for g in get)
84 + self._labels.update(set)
85 + if len(get) == 1 :
86 + return result[0]
87 + elif len(get) > 1 :
88 + return result
89 + elif len(set) == 0 :
90 + return self._labels.copy()
91 + def has_label (self, name, *names) :
92 + if len(names) == 0 :
93 + return name in self._labels
94 + else :
95 + return tuple(n in self._labels for n in (name,) + names)
96 + def copy (self, name=None, **options) :
97 + if not hasattr(self, "_labels") :
98 + self._labels = {}
99 + result = module.Place.copy(self, name, **options)
100 + result._labels = self._labels.copy()
101 + return result
102 + def __pnmldump__ (self) :
103 + """
104 + >>> p = Place('p')
105 + >>> p.label(foo='bar', spam=42)
106 + >>> p.__pnmldump__()
107 + <?xml version="1.0" encoding="utf-8"?>
108 + <pnml>
109 + <place id="p">
110 + <type domain="universal"/>
111 + <initialMarking>
112 + <multiset/>
113 + </initialMarking>
114 + <label name="foo">
115 + <object type="str">
116 + bar
117 + </object>
118 + </label>
119 + <label name="spam">
120 + <object type="int">
121 + 42
122 + </object>
123 + </label>
124 + </place>
125 + </pnml>
126 + """
127 + t = module.Place.__pnmldump__(self)
128 + if hasattr(self, "_labels") :
129 + for key, val in self._labels.items() :
130 + t.add_child(Tree("label", None,
131 + Tree.from_obj(val),
132 + name=key))
133 + return t
134 + @classmethod
135 + def __pnmlload__ (cls, tree) :
136 + """
137 + >>> old = Place('p')
138 + >>> old.label(foo='bar', spam=42)
139 + >>> p = old.__pnmldump__()
140 + >>> new = Place.__pnmlload__(p)
141 + >>> new
142 + Place('p', MultiSet([]), tAll)
143 + >>> new.__class__
144 + <class 'snakes.plugins.labels.Place'>
145 + >>> new.label('foo', 'spam')
146 + ('bar', 42)
147 + """
148 + p = new_instance(cls, module.Place.__pnmlload__(tree))
149 + p._labels = dict((lbl["name"], lbl.child().to_obj())
150 + for lbl in tree.get_children("label"))
151 + return p
152 + class PetriNet (module.PetriNet) :
153 + def label (self, *get, **set) :
154 + if not hasattr(self, "_labels") :
155 + self._labels = {}
156 + result = tuple(self._labels[g] for g in get)
157 + self._labels.update(set)
158 + if len(get) == 1 :
159 + return result[0]
160 + elif len(get) > 1 :
161 + return result
162 + elif len(set) == 0 :
163 + return self._labels.copy()
164 + def has_label (self, name, *names) :
165 + if len(names) == 0 :
166 + return name in self._labels
167 + else :
168 + return tuple(n in self._labels for n in (name,) + names)
169 + def copy (self, name=None, **options) :
170 + if not hasattr(self, "_labels") :
171 + self._labels = {}
172 + result = module.PetriNet.copy(self, name, **options)
173 + result._labels = self._labels.copy()
174 + return result
175 + def __pnmldump__ (self) :
176 + """
177 + >>> n = PetriNet('n')
178 + >>> n.label(foo='bar', spam=42)
179 + >>> n.__pnmldump__()
180 + <?xml version="1.0" encoding="utf-8"?>
181 + <pnml>
182 + <net id="n">
183 + <label name="foo">
184 + <object type="str">
185 + bar
186 + </object>
187 + </label>
188 + <label name="spam">
189 + <object type="int">
190 + 42
191 + </object>
192 + </label>
193 + </net>
194 + </pnml>
195 + """
196 + t = module.PetriNet.__pnmldump__(self)
197 + if hasattr(self, "_labels") :
198 + for key, val in self._labels.items() :
199 + t.add_child(Tree("label", None,
200 + Tree.from_obj(val),
201 + name=key))
202 + return t
203 + @classmethod
204 + def __pnmlload__ (cls, tree) :
205 + """
206 + >>> old = PetriNet('n')
207 + >>> old.label(foo='bar', spam=42)
208 + >>> p = old.__pnmldump__()
209 + >>> new = PetriNet.__pnmlload__(p)
210 + >>> new
211 + PetriNet('n')
212 + >>> new.__class__
213 + <class 'snakes.plugins.labels.PetriNet'>
214 + >>> new.label('foo', 'spam')
215 + ('bar', 42)
216 + """
217 + n = new_instance(cls, module.PetriNet.__pnmlload__(tree))
218 + n._labels = dict((lbl["name"], lbl.child().to_obj())
219 + for lbl in tree.get_children("label"))
220 + return n
221 + def merge_places (self, target, sources, **options) :
222 + module.PetriNet.merge_places(self, target, sources, **options)
223 + new = self.place(target)
224 + for place in sources :
225 + new.label(**dict(self.place(place).label()))
226 + def merge_transitions (self, target, sources, **options) :
227 + module.PetriNet.merge_transitions(self, target, sources, **options)
228 + new = self.transition(target)
229 + for trans in sources :
230 + new.label(**dict(self.transition(trans).label()))
231 + return Transition, Place, PetriNet
1 +"""A plugin to compose nets.
2 +
3 +The compositions are based on place status and automatically merge
4 +some nodes (buffers and variables, tick transitions).
5 +
6 +>>> import snakes.plugins
7 +>>> snakes.plugins.load('ops', 'snakes.nets', 'nets')
8 +<module ...>
9 +>>> from nets import *
10 +>>> from snakes.plugins.status import entry, internal, exit, buffer
11 +>>> basic = PetriNet('basic')
12 +>>> basic.add_place(Place('e', status=entry))
13 +>>> basic.add_place(Place('x', status=exit))
14 +>>> basic.add_transition(Transition('t'))
15 +>>> basic.add_input('e', 't', Value(1))
16 +>>> basic.add_output('x', 't', Value(2))
17 +>>> basic.add_place(Place('b', [1], status=buffer('buf')))
18 +
19 +>>> n = basic.copy()
20 +>>> n.hide(entry)
21 +>>> n.node('e').status
22 +Status(None)
23 +>>> n.hide(buffer('buf'), buffer(None))
24 +>>> n.node('b').status
25 +Buffer('buffer')
26 +
27 +>>> n = basic / 'buf'
28 +>>> n.node('[b/buf]').status
29 +Buffer('buffer')
30 +
31 +>>> n = basic & basic
32 +>>> n.status(internal)
33 +('[x&e]',)
34 +>>> n.place('[x&e]').pre
35 +{'[t&]': Value(2)}
36 +>>> n.place('[x&e]').post
37 +{'[&t]': Value(1)}
38 +>>> n.status(buffer('buf'))
39 +('[b&b]',)
40 +
41 +>>> n = basic + basic
42 +>>> n.status(entry)
43 +('[e+e]',)
44 +>>> list(sorted(n.place('[e+e]').post.items()))
45 +[('[+t]', Value(1)), ('[t+]', Value(1))]
46 +>>> n.status(exit)
47 +('[x+x]',)
48 +>>> list(sorted(n.place('[x+x]').pre.items()))
49 +[('[+t]', Value(2)), ('[t+]', Value(2))]
50 +
51 +>>> n = basic * basic
52 +>>> n.status(entry)
53 +('[e,x*e]',)
54 +>>> n.place('[e,x*e]').post
55 +{'[t*]': Value(1), '[*t]': Value(1)}
56 +>>> n.place('[e,x*e]').pre
57 +{'[t*]': Value(2)}
58 +
59 +>>> n1 = basic.copy()
60 +>>> n1.declare('global x; x=1')
61 +>>> n2 = basic.copy()
62 +>>> n2.globals['y'] = 2
63 +>>> n = n1 + n2
64 +>>> n.globals['x'], n.globals['y']
65 +(1, 2)
66 +>>> n._declare
67 +['global x; x=1']
68 +"""
69 +
70 +import snakes.plugins
71 +from snakes.plugins.status import Status, entry, exit, internal
72 +from snakes.data import cross
73 +from snakes.plugins.clusters import Cluster
74 +
75 +def _glue (op, one, two) :
76 + result = one.__class__("(%s%s%s)" % (one.name, op, two.name))
77 + def new (name) :
78 + return "[%s%s]" % (name, op)
79 + for net in (one, two) :
80 + result.clusters.add_child(Cluster())
81 + result._declare = list(set(result._declare) | set(net._declare))
82 + result.globals.update(net.globals)
83 + for place in net.place() :
84 + result.add_place(place.copy(new(place.name)),
85 + cluster=[-1]+net.clusters.get_path(place.name))
86 + for trans in net.transition() :
87 + result.add_transition(trans.copy(new(trans.name)),
88 + cluster=[-1]+net.clusters.get_path(trans.name))
89 + for place, label in trans.input() :
90 + result.add_input(new(place.name),
91 + new(trans.name),
92 + label.copy())
93 + for place, label in trans.output() :
94 + result.add_output(new(place.name),
95 + new(trans.name),
96 + label.copy())
97 + def new (name) :
98 + return "[%s%s]" % (op, name)
99 + for status in result.status :
100 + result.status.merge(status)
101 + new = result.status(status)
102 + if len(new) == 1 :
103 + name = "[%s%s%s]" % (",".join(sorted(one.status(status))),
104 + op,
105 + ",".join(sorted(two.status(status))))
106 + if name != new[0] :
107 + result.rename_node(new[0], name)
108 + return result
109 +
110 +@snakes.plugins.plugin("snakes.nets",
111 + depends=["snakes.plugins.clusters",
112 + "snakes.plugins.status"])
113 +def extend (module) :
114 + "Build the extended module"
115 + class PetriNet (module.PetriNet) :
116 + def __or__ (self, other) :
117 + "Parallel"
118 + return _glue("|", self, other)
119 + def __and__ (self, other) :
120 + "Sequence"
121 + result = _glue("&", self, other)
122 + remove = set()
123 + for x, e in cross((self.status(exit), other.status(entry))) :
124 + new = "[%s&%s]" % (x, e)
125 + new_x, new_e = "[%s&]" % x, "[&%s]" % e
126 + result.merge_places(new, (new_x, new_e), status=internal)
127 + remove.update((new_x, new_e))
128 + for p in remove :
129 + result.remove_place(p)
130 + return result
131 + def __add__ (self, other) :
132 + "Choice"
133 + result = _glue("+", self, other)
134 + for status in (entry, exit) :
135 + remove = set()
136 + for l, r in cross((self.status(status),
137 + other.status(status))) :
138 + new = "[%s+%s]" % (l, r)
139 + new_l, new_r = "[%s+]" % l, "[+%s]" % r
140 + result.merge_places(new, (new_l, new_r), status=status)
141 + remove.update((new_l, new_r))
142 + for p in remove :
143 + result.remove_place(p)
144 + return result
145 + def __mul__ (self, other) :
146 + "Iteration"
147 + result = _glue("*", self, other)
148 + remove = set()
149 + for e1, x1, e2 in cross((self.status(entry),
150 + self.status(exit),
151 + other.status(entry))) :
152 + new = "[%s,%s*%s]" % (e1, x1, e2)
153 + new_e1, new_x1 = "[%s*]" % e1, "[%s*]" % x1
154 + new_e2 = "[*%s]" % e2
155 + result.merge_places(new, (new_e1, new_x1, new_e2),
156 + status=entry)
157 + remove.update((new_e1, new_x1, new_e2))
158 + for p in remove :
159 + result.remove_place(p)
160 + return result
161 + def hide (self, old, new=None) :
162 + if new is None :
163 + new = Status(None)
164 + for node in self.status(old) :
165 + self.set_status(node, new)
166 + def __div__ (self, name) :
167 + result = self.copy()
168 + for node in result.node() :
169 + result.rename_node(node.name, "[%s/%s]" % (node, name))
170 + for status in result.status :
171 + if status._value == name :
172 + result.hide(status, status.__class__(status._name, None))
173 + return result
174 + def __truediv__ (self, other) :
175 + return self.__div__(other)
176 + return PetriNet
1 +"""A plugin to add positions to the nodes.
2 +
3 + - C{Place} and C{Transition} constructors are added an optional
4 + argument C{pos=(x,y)} to set their position
5 +
6 + - C{Place} and C{Transition} are added an attribute C{pos} that is
7 + pair of numbers with attributes C{x} and C{y} and methods
8 + C{shift(dx, dy)} and C{moveto(x, y)}
9 +
10 + - Petri nets are added methods C{bbox()} that returns a pair of
11 + extrema C{((xmin, ymin), (xmax, ymax))}, a method C{shift(dx, dy)}
12 + that shift all the nodes, and a method C{transpose()} that rotates
13 + the net in such a way that the top-down direction becomes
14 + left-right
15 +
16 +>>> import snakes.plugins
17 +>>> snakes.plugins.load('pos', 'snakes.nets', 'nets')
18 +<module ...>
19 +>>> from nets import PetriNet, Place, Transition
20 +>>> n = PetriNet('N')
21 +>>> n.add_place(Place('p00'))
22 +>>> n.add_transition(Transition('t10', pos=(1, 0)))
23 +>>> n.add_place(Place('p11', pos=(1, 1)))
24 +>>> n.add_transition(Transition('t01', pos=(0, 1)))
25 +>>> n.node('t10').pos
26 +Position(1, 0)
27 +>>> n.node('t10').pos.x
28 +1
29 +>>> n.node('t10').pos.y
30 +0
31 +>>> n.node('t10').pos.y = 1
32 +Traceback (most recent call last):
33 + ...
34 +AttributeError: readonly attribute
35 +>>> n.node('t10').pos()
36 +(1, 0)
37 +>>> n.bbox()
38 +((0, 0), (1, 1))
39 +>>> n.shift(1, 2)
40 +>>> n.bbox()
41 +((1, 2), (2, 3))
42 +>>> n.node('t01').copy().pos
43 +Position(1, 3)
44 +>>> n.transpose()
45 +>>> n.node('t01').pos
46 +Position(-3, 1)
47 +"""
48 +
49 +from snakes import SnakesError
50 +from snakes.compat import *
51 +from snakes.plugins import plugin, new_instance
52 +from snakes.pnml import Tree
53 +
54 +class Position (object) :
55 + "The position of a node"
56 + def __init__ (self, x, y) :
57 + self.__dict__["x"] = x
58 + self.__dict__["y"] = y
59 + def __str__ (self) :
60 + return "(%s, %s)" % (str(self.x), str(self.y))
61 + def __repr__ (self) :
62 + return "Position(%s, %s)" % (str(self.x), str(self.y))
63 + def __setattr__ (self, name, value) :
64 + if name in ("x", "y") :
65 + raise AttributeError("readonly attribute")
66 + else :
67 + self.__dict__[name] = value
68 + def moveto (self, x, y) :
69 + self.__init__(x, y)
70 + def shift (self, dx, dy) :
71 + self.__init__(self.x + dx, self.y + dy)
72 + def __getitem__ (self, rank) :
73 + if rank == 0 :
74 + return self.x
75 + elif rank == 1 :
76 + return self.y
77 + else :
78 + raise IndexError("Position index out of range")
79 + def __iter__ (self) :
80 + yield self.x
81 + yield self.y
82 + def __call__ (self) :
83 + return (self.x, self.y)
84 +
85 +@plugin("snakes.nets")
86 +def extend (module) :
87 + class Place (module.Place) :
88 + def __init__ (self, name, tokens=[], check=None, **args) :
89 + x, y = args.pop("pos", (0, 0))
90 + self.pos = Position(x, y)
91 + module.Place.__init__(self, name, tokens, check, **args)
92 + def copy (self, name=None, **args) :
93 + x, y = args.pop("pos", self.pos())
94 + result = module.Place.copy(self, name, **args)
95 + result.pos.moveto(x, y)
96 + return result
97 + def __pnmldump__ (self) :
98 + """
99 + >>> p = Place('p', pos=(1, 2))
100 + >>> p.__pnmldump__()
101 + <?xml version="1.0" encoding="utf-8"?>
102 + <pnml>
103 + <place id="p">
104 + <type domain="universal"/>
105 + <initialMarking>
106 + <multiset/>
107 + </initialMarking>
108 + <graphics>
109 + <position x="1" y="2"/>
110 + </graphics>
111 + </place>
112 + </pnml>
113 + """
114 + t = module.Place.__pnmldump__(self)
115 + try :
116 + gfx = t.child("graphics")
117 + except SnakesError :
118 + gfx = Tree("graphics", None)
119 + t.add_child(gfx)
120 + gfx.add_child(Tree("position", None,
121 + x=str(self.pos.x),
122 + y=str(self.pos.y)))
123 + return t
124 + @classmethod
125 + def __pnmlload__ (cls, tree) :
126 + """
127 + >>> old = Place('p', pos=(1, 2))
128 + >>> p = old.__pnmldump__()
129 + >>> new = Place.__pnmlload__(p)
130 + >>> new.pos
131 + Position(1, 2)
132 + >>> new
133 + Place('p', MultiSet([]), tAll)
134 + >>> new.__class__
135 + <class 'snakes.plugins.pos.Place'>
136 + """
137 + result = new_instance(cls, module.Place.__pnmlload__(tree))
138 + try :
139 + p = tree.child("graphics").child("position")
140 + x, y = eval(p["x"]), eval(p["y"])
141 + result.pos = Position(x, y)
142 + except SnakesError :
143 + result.pos = Position(0, 0)
144 + return result
145 + class Transition (module.Transition) :
146 + def __init__ (self, name, guard=None, **args) :
147 + x, y = args.pop("pos", (0, 0))
148 + self.pos = Position(x, y)
149 + module.Transition.__init__(self, name, guard, **args)
150 + def copy (self, name=None, **args) :
151 + x, y = args.pop("pos", self.pos())
152 + result = module.Transition.copy(self, name, **args)
153 + result.pos.moveto(x, y)
154 + return result
155 + def __pnmldump__ (self) :
156 + """
157 + >>> t = Transition('t', pos=(2, 1))
158 + >>> t.__pnmldump__()
159 + <?xml version="1.0" encoding="utf-8"?>
160 + <pnml>
161 + <transition id="t">
162 + <graphics>
163 + <position x="2" y="1"/>
164 + </graphics>
165 + </transition>
166 + </pnml>
167 + """
168 + t = module.Transition.__pnmldump__(self)
169 + t.add_child(Tree("graphics", None,
170 + Tree("position", None,
171 + x=str(self.pos.x),
172 + y=str(self.pos.y))))
173 + return t
174 + @classmethod
175 + def __pnmlload__ (cls, tree) :
176 + """
177 + >>> old = Transition('t', pos=(2, 1))
178 + >>> p = old.__pnmldump__()
179 + >>> new = Transition.__pnmlload__(p)
180 + >>> new.pos
181 + Position(2, 1)
182 + >>> new
183 + Transition('t', Expression('True'))
184 + >>> new.__class__
185 + <class 'snakes.plugins.pos.Transition'>
186 + """
187 + result = new_instance(cls, module.Transition.__pnmlload__(tree))
188 + try :
189 + p = tree.child("graphics").child("position")
190 + x, y = eval(p["x"]), eval(p["y"])
191 + result.pos = Position(x, y)
192 + except SnakesError :
193 + result.pos = Position(0, 0)
194 + return result
195 + class PetriNet (module.PetriNet) :
196 + def add_place (self, place, **args) :
197 + if "pos" in args :
198 + x, y = args.pop("pos")
199 + place.pos.moveto(x, y)
200 + module.PetriNet.add_place(self, place, **args)
201 + def add_transition (self, trans, **args) :
202 + if "pos" in args :
203 + x, y = args.pop("pos")
204 + trans.pos.moveto(x, y)
205 + module.PetriNet.add_transition(self, trans, **args)
206 + def merge_places (self, target, sources, **args) :
207 + pos = args.pop("pos", None)
208 + module.PetriNet.merge_places(self, target, sources, **args)
209 + if pos is None :
210 + pos = reduce(complex.__add__,
211 + (complex(*self._place[name].pos())
212 + for name in sources)) / len(sources)
213 + x, y = pos.real, pos.imag
214 + else :
215 + x, y = pos
216 + self._place[target].pos.moveto(x, y)
217 + def merge_transitions (self, target, sources, **args) :
218 + pos = args.pop("pos", None)
219 + module.PetriNet.merge_transitions(self, target, sources, **args)
220 + if pos is None :
221 + pos = reduce(complex.__add__,
222 + (complex(*self._trans[name].pos())
223 + for name in sources)) / len(sources)
224 + x, y = pos.real, pos.imag
225 + else :
226 + x, y = pos
227 + self._trans[target].pos.moveto(x, y)
228 + def bbox (self) :
229 + if len(self._node) == 0 :
230 + return (0, 0), (0, 0)
231 + else :
232 + nodes = iter(self._node.values())
233 + xmin, ymin = next(nodes).pos()
234 + xmax, ymax = xmin, ymin
235 + for n in nodes :
236 + x, y = n.pos()
237 + xmin = min(xmin, x)
238 + xmax = max(xmax, x)
239 + ymin = min(ymin, y)
240 + ymax = max(ymax, y)
241 + return (xmin, ymin), (xmax, ymax)
242 + def shift (self, dx, dy) :
243 + for node in self.node() :
244 + node.pos.shift(dx, dy)
245 + def transpose (self) :
246 + for node in self.node() :
247 + x, y = node.pos()
248 + node.pos.moveto(-y, x)
249 + return Place, Transition, PetriNet, Position
1 +from snakes.plugins import plugin
2 +from snakes.pnml import Tree, loads, dumps
3 +import imp, sys, socket, traceback, operator
4 +
5 +class QueryError (Exception) :
6 + pass
7 +
8 +class Query (object) :
9 + def __init__ (self, name, *larg, **karg) :
10 + self._name = name
11 + self._larg = tuple(larg)
12 + self._karg = dict(karg)
13 + __pnmltag__ = "query"
14 + def __pnmldump__ (self) :
15 + """
16 + >>> Query('set', 'x', 42).__pnmldump__()
17 + <?xml version="1.0" encoding="utf-8"?>
18 + <pnml>
19 + <query name="set">
20 + <argument>
21 + <object type="str">
22 + x
23 + </object>
24 + </argument>
25 + <argument>
26 + <object type="int">
27 + 42
28 + </object>
29 + </argument>
30 + </query>
31 + </pnml>
32 + >>> Query('test', x=1).__pnmldump__()
33 + <?xml version="1.0" encoding="utf-8"?>
34 + <pnml>
35 + <query name="test">
36 + <keyword name="x">
37 + <object type="int">
38 + 1
39 + </object>
40 + </keyword>
41 + </query>
42 + </pnml>
43 + >>> Query('test', 'x', 42, y=1).__pnmldump__()
44 + <?xml version="1.0" encoding="utf-8"?>
45 + <pnml>
46 + <query name="test">
47 + <argument>
48 + <object type="str">
49 + x
50 + </object>
51 + </argument>
52 + <argument>
53 + <object type="int">
54 + 42
55 + </object>
56 + </argument>
57 + <keyword name="y">
58 + <object type="int">
59 + 1
60 + </object>
61 + </keyword>
62 + </query>
63 + </pnml>
64 + >>> Query('set', 'x', Query('call', 'x.upper')).__pnmldump__()
65 + <?xml version="1.0" encoding="utf-8"?>
66 + <pnml>
67 + <query name="set">
68 + <argument>
69 + <object type="str">
70 + x
71 + </object>
72 + </argument>
73 + <argument>
74 + <query name="call">
75 + <argument>
76 + <object type="str">
77 + x.upper
78 + </object>
79 + </argument>
80 + </query>
81 + </argument>
82 + </query>
83 + </pnml>
84 + """
85 + children = []
86 + for arg in self._larg :
87 + children.append(Tree("argument", None,
88 + Tree.from_obj(arg)))
89 + for name, value in self._karg.items() :
90 + children.append(Tree("keyword", None,
91 + Tree.from_obj(value),
92 + name=name))
93 + return Tree(self.__pnmltag__, None, *children, **{"name": self._name})
94 + @classmethod
95 + def __pnmlload__ (cls, tree) :
96 + """
97 + >>> Tree._tag2obj = {'query': Query}
98 + >>> t = Query('test', 'x', 42, y=1).__pnmldump__()
99 + >>> q = Query.__pnmlload__(t)
100 + >>> q._name
101 + 'test'
102 + >>> q._larg
103 + ('x', 42)
104 + >>> q._karg
105 + {'y': 1}
106 + """
107 + larg = (child.child().to_obj()
108 + for child in tree.get_children("argument"))
109 + karg = dict((child["name"], child.child().to_obj())
110 + for child in tree.get_children("keyword"))
111 + return cls(tree["name"], *larg, **karg)
112 + def run (self, envt) :
113 + """
114 + >>> import imp
115 + >>> env = imp.new_module('environment')
116 + >>> Query('set', 'x', 'hello').run(env)
117 + >>> env.x
118 + 'hello'
119 + >>> Query('set', 'x', Query('call', 'x.upper')).run(env)
120 + >>> env.x
121 + 'HELLO'
122 + >>> Query('test', 1, 2, 3).run(env)
123 + Traceback (most recent call last):
124 + ...
125 + QueryError: unknown query 'test'
126 + """
127 + try :
128 + handler = getattr(self, "_run_%s" % self._name)
129 + except AttributeError :
130 + raise QueryError("unknown query %r" % self._name)
131 + self._envt = envt
132 + larg = tuple(a.run(envt) if isinstance(a, self.__class__) else a
133 + for a in self._larg)
134 + karg = dict((n, v.run(envt) if isinstance(v, self.__class__) else v)
135 + for n, v in self._karg.items())
136 + try :
137 + return handler(*larg, **karg)
138 + except TypeError :
139 + cls, val, tb = sys.exc_info()
140 + try :
141 + fun, msg = str(val).strip().split("()", 1)
142 + except :
143 + raise val
144 + if fun.startswith("_run_") and hasattr(self, fun) :
145 + raise TypeError(fun[5:] + "()" + msg)
146 + raise val
147 + def _get_object (self, path) :
148 + obj = self._envt
149 + for n in path :
150 + obj = getattr(obj, n)
151 + return obj
152 + def _run_set (self, name, value) :
153 + """
154 + >>> import imp
155 + >>> env = imp.new_module('environment')
156 + >>> Query('set', 'x', 1).run(env)
157 + >>> env.x
158 + 1
159 + """
160 + path = name.split(".")
161 + setattr(self._get_object(path[:-1]), path[-1], value)
162 + def _run_get (self, name) :
163 + """
164 + >>> import imp
165 + >>> env = imp.new_module('environment')
166 + >>> env.x = 2
167 + >>> Query('get', 'x').run(env)
168 + 2
169 + """
170 + path = name.split(".")
171 + return self._get_object(path)
172 + def _run_del (self, name) :
173 + """
174 + >>> import imp
175 + >>> env = imp.new_module('environment')
176 + >>> env.x = 2
177 + >>> Query('del', 'x').run(env)
178 + >>> env.x
179 + Traceback (most recent call last):
180 + ...
181 + AttributeError: 'module' object has no attribute 'x'
182 + """
183 + path = name.split(".")
184 + delattr(self._get_object(path[:-1]), path[-1])
185 + def _run_call (self, fun, *larg, **karg) :
186 + """
187 + >>> import imp
188 + >>> env = imp.new_module('environment')
189 + >>> env.x = 'hello'
190 + >>> Query('call', 'x.center', 7).run(env)
191 + ' hello '
192 + >>> env.__dict__.update(__builtins__)
193 + >>> Query('call', Query('call', 'getattr',
194 + ... Query('call', 'x.center', 7),
195 + ... 'upper')).run(env)
196 + ' HELLO '
197 + """
198 + if isinstance(fun, str) :
199 + fun = self._get_object(fun.split("."))
200 + return fun(*larg, **karg)
201 +
202 +@plugin("snakes.nets")
203 +def extend (module) :
204 + class UDPServer (object) :
205 + def __init__ (self, port, size=2**20, verbose=0) :
206 + self._size = size
207 + self._verbose = verbose
208 + self._sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
209 + self._sock.bind(("", port))
210 + self._env = imp.new_module("snk")
211 + self._env.__dict__.update(__builtins__)
212 + self._env.__dict__.update(operator.__dict__)
213 + self._env.__dict__.update(module.__dict__)
214 + def recvfrom (self) :
215 + return self._sock.recvfrom(self._size)
216 + def sendto (self, data, address) :
217 + self._sock.sendto(data.strip() + "\n", address)
218 + def run (self) :
219 + while True :
220 + data, address = self.recvfrom()
221 + data = data.strip()
222 + if self._verbose :
223 + print("# query from %s:%u" % address)
224 + try :
225 + if self._verbose > 1 :
226 + print(data)
227 + res = loads(data).run(self._env)
228 + if res is None :
229 + res = Tree("answer", None, status="ok")
230 + else :
231 + res = Tree("answer", None, Tree.from_obj(res),
232 + status="ok")
233 + except :
234 + cls, val, tb = sys.exc_info()
235 + res = Tree("answer", str(val).strip(),
236 + error=cls.__name__, status="error")
237 + if self._verbose > 1 :
238 + print("# error")
239 + for entry in traceback.format_exception(cls, val, tb) :
240 + for line in entry.splitlines() :
241 + print("## %s" % line)
242 + if self._verbose :
243 + if self._verbose > 1 :
244 + print("# answer")
245 + print(res.to_pnml())
246 + elif res["status"] == "error" :
247 + print("# answer: %s: %s" % (res["error"], res.data))
248 + else :
249 + print("# answer: %s" % res["status"])
250 + self.sendto(res.to_pnml(), address)
251 + class TCPServer (UDPServer) :
252 + def __init__ (self, port, size=2**20, verbose=0) :
253 + self._size = size
254 + self._verbose = verbose
255 + self._sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
256 + self._sock.bind(("", port))
257 + self._sock.listen(1)
258 + self._env = imp.new_module("snk")
259 + self._env.__dict__.update(__builtins__)
260 + self._env.__dict__.update(operator.__dict__)
261 + self._env.__dict__.update(module.__dict__)
262 + self._connection = {}
263 + def recvfrom (self) :
264 + connection, address = self._sock.accept()
265 + self._connection[address] = connection
266 + parts = []
267 + while True :
268 + parts.append(connection.recv(self._size))
269 + if len(parts[-1]) < self._size :
270 + break
271 + return "".join(parts), address
272 + def sendto (self, data, address) :
273 + self._connection[address].send(data.rstrip() + "\n")
274 + self._connection[address].close()
275 + del self._connection[address]
276 + return Query, UDPServer, TCPServer
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
File mode changed
1 +from snakes import SnakesError
2 +
3 +class CompilationError (SnakesError) :
4 + pass
5 +
6 +class DeclarationError (SnakesError) :
7 + pass
This diff is collapsed. Click to expand it.
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 +import sys, optparse, os.path
2 +import pdb, traceback
3 +import snakes.plugins
4 +from snakes.utils.abcd.build import Builder
5 +from snakes.lang.abcd.parser import parse
6 +from snakes.lang.pgen import ParseError
7 +from snakes.utils.abcd import CompilationError, DeclarationError
8 +from snakes.utils.abcd.simul import Simulator
9 +from snakes.utils.abcd.checker import Checker
10 +
11 +##
12 +## error messages
13 +##
14 +
15 +ERR_ARG = 1
16 +ERR_OPT = 2
17 +ERR_IO = 3
18 +ERR_PARSE = 4
19 +ERR_PLUGIN = 5
20 +ERR_COMPILE = 6
21 +ERR_OUTPUT = 7
22 +ERR_BUG = 255
23 +
24 +def err (message) :
25 + sys.stderr.write("abcd: %s\n" % message.strip())
26 +
27 +def die (code, message=None) :
28 + if message :
29 + err(message)
30 + if options.debug :
31 + pdb.post_mortem(sys.exc_info()[2])
32 + else :
33 + sys.exit(code)
34 +
35 +def bug () :
36 + sys.stderr.write("""
37 + ********************************************************************
38 + *** An unexpected error ocurred. Please report this bug to ***
39 + *** <franck.pommereau@gmail.com>, together with the execution ***
40 + *** trace below and, if possible, a stripped-down version of the ***
41 + *** ABCD source code that caused this bug. Thank you for your ***
42 + *** help in improving SNAKES! ***
43 + ********************************************************************
44 +
45 +""")
46 + traceback.print_exc()
47 + if options.debug :
48 + pdb.post_mortem(sys.exc_info()[2])
49 + else :
50 + sys.exit(ERR_BUG)
51 +
52 +##
53 +## options parsing
54 +##
55 +
56 +gv_engines = ("dot", "neato", "twopi", "circo", "fdp")
57 +
58 +opt = optparse.OptionParser(prog="abcd",
59 + usage="%prog [OPTION]... FILE")
60 +opt.add_option("-l", "--load",
61 + dest="plugins", action="append", default=[],
62 + help="load plugin (this option can be repeated)",
63 + metavar="PLUGIN")
64 +opt.add_option("-p", "--pnml",
65 + dest="pnml", action="store", default=None,
66 + help="save net as PNML",
67 + metavar="OUTFILE")
68 +for engine in gv_engines :
69 + opt.add_option("-" + engine[0], "--" + engine,
70 + dest="gv" + engine, action="store", default=None,
71 + help="draw net using '%s' (from GraphViz)" % engine,
72 + metavar="OUTFILE")
73 +opt.add_option("-a", "--all-names",
74 + dest="allnames", action="store_true", default=False,
75 + help="draw control-flow places names (default: hide)")
76 +opt.add_option("--debug",
77 + dest="debug", action="store_true", default=False,
78 + help="launch debugger on compiler error (default: no)")
79 +opt.add_option("-s", "--simul",
80 + dest="simul", action="store_true", default=False,
81 + help="launch interactive code simulator")
82 +opt.add_option("--check",
83 + dest="check", action="store_true", default=False,
84 + help="check assertions")
85 +
86 +def getopts (args) :
87 + global options, abcd
88 + (options, args) = opt.parse_args(args)
89 + plugins = []
90 + for p in options.plugins :
91 + plugins.extend(t.strip() for t in p.split(","))
92 + if "ops" not in options.plugins :
93 + plugins.append("ops")
94 + if "labels" not in plugins :
95 + plugins.append("labels")
96 + for engine in gv_engines :
97 + gvopt = getattr(options, "gv%s" % engine)
98 + if gvopt and "gv" not in plugins :
99 + plugins.append("gv")
100 + break
101 + options.plugins = plugins
102 + if len(args) < 1 :
103 + err("no input file provided")
104 + opt.print_help()
105 + die(ERR_ARG)
106 + elif len(args) > 1 :
107 + err("more than one input file provided")
108 + opt.print_help()
109 + die(ERR_ARG)
110 + abcd = args[0]
111 + if options.pnml == abcd :
112 + err("input file also used as output (--pnml)")
113 + opt.print_help()
114 + die(ERR_ARG)
115 + for engine in gv_engines :
116 + if getattr(options, "gv%s" % engine) == abcd :
117 + err("input file also used as output (--%s)" % engine)
118 + opt.print_help()
119 + die(ERR_ARG)
120 +
121 +##
122 +## drawing nets
123 +##
124 +
125 +def place_attr (place, attr) :
126 + # fix color
127 + if place.status == snk.entry :
128 + attr["fillcolor"] = "green"
129 + elif place.status == snk.internal :
130 + pass
131 + elif place.status == snk.exit :
132 + attr["fillcolor"] = "yellow"
133 + else :
134 + attr["fillcolor"] = "lightblue"
135 + # fix shape
136 + if (not options.allnames
137 + and place.status in (snk.entry, snk.internal, snk.exit)) :
138 + attr["shape"] = "circle"
139 + # render marking
140 + if place._check == snk.tBlackToken :
141 + count = len(place.tokens)
142 + if count == 0 :
143 + marking = " "
144 + elif count == 1 :
145 + marking = "@"
146 + else :
147 + marking = "%s@" % count
148 + else :
149 + marking = str(place.tokens)
150 + # node label
151 + if (options.allnames
152 + or place.status not in (snk.entry, snk.internal, snk.exit)) :
153 + attr["label"] = "%s\\n%s" % (place.name, marking)
154 + else :
155 + attr["label"] = "%s" % marking
156 +
157 +def trans_attr (trans, attr) :
158 + pass
159 +
160 +def arc_attr (label, attr) :
161 + if label == snk.Value(snk.dot) :
162 + del attr["label"]
163 + elif isinstance(label, snk.Test) :
164 + attr["arrowhead"] = "none"
165 + attr["label"] = " %s " % label._annotation
166 + elif isinstance(label, snk.Flush) :
167 + attr["arrowhead"] = "box"
168 + attr["label"] = " %s " % label._annotation
169 +
170 +def draw (net, engine, target) :
171 + try :
172 + net.draw(target, engine=engine,
173 + place_attr=place_attr,
174 + trans_attr=trans_attr,
175 + arc_attr=arc_attr)
176 + except :
177 + die(ERR_OUTPUT, str(sys.exc_info()[1]))
178 +
179 +##
180 +## save pnml
181 +##
182 +
183 +def save_pnml (net, target) :
184 + try :
185 + out = open(target, "w")
186 + out.write(snk.dumps(net))
187 + out.close()
188 + except :
189 + die(ERR_OUTPUT, str(sys.exc_info()[1]))
190 +
191 +##
192 +## main
193 +##
194 +
195 +def main (args=sys.argv[1:], src=None) :
196 + global snk
197 + # get options
198 + try:
199 + if src is None :
200 + getopts(args)
201 + else :
202 + getopts(list(args) + ["<string>"])
203 + except SystemExit :
204 + raise
205 + except :
206 + die(ERR_OPT, str(sys.exc_info()[1]))
207 + # read source
208 + if src is not None :
209 + source = src
210 + else :
211 + try :
212 + source = open(abcd).read()
213 + except :
214 + die(ERR_IO, "could not read input file %r" % abcd)
215 + # parse
216 + try :
217 + node = parse(source, filename=abcd)
218 + except ParseError :
219 + die(ERR_PARSE, str(sys.exc_info()[1]))
220 + except :
221 + bug()
222 + # compile
223 + dirname = os.path.dirname(abcd)
224 + if dirname and dirname not in sys.path :
225 + sys.path.append(dirname)
226 + elif "." not in sys.path :
227 + sys.path.append(".")
228 + try :
229 + snk = snakes.plugins.load(options.plugins, "snakes.nets", "snk")
230 + except :
231 + die(ERR_PLUGIN, str(sys.exc_info()[1]))
232 + build = Builder(snk)
233 + try :
234 + net = build.build(node)
235 + net.label(srcfile=abcd)
236 + except (CompilationError, DeclarationError) :
237 + die(ERR_COMPILE, str(sys.exc_info()[1]))
238 + except :
239 + bug()
240 + # output
241 + if options.pnml :
242 + save_pnml(net, options.pnml)
243 + for engine in gv_engines :
244 + target = getattr(options, "gv%s" % engine)
245 + if target :
246 + draw(net, engine, target)
247 + trace, lineno = [], None
248 + if options.check :
249 + lineno, trace = Checker(net).run()
250 + if options.simul :
251 + Simulator(snk, source, net, trace, lineno).run()
252 + elif trace :
253 + if lineno is None :
254 + print("unsafe execution:")
255 + else :
256 + asserts = dict((a.lineno, a) for a in net.label("asserts"))
257 + print("line %s, %r failed:"
258 + % (lineno, asserts[lineno].st.source()))
259 + for trans, mode in trace :
260 + print(" %s %s" % (trans, mode))
261 + return net
262 +
263 +if __name__ == "__main__" :
264 + main()
This diff is collapsed. Click to expand it.
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()
This diff is collapsed. Click to expand it.
1 +from snakes.lang.ctlstar.parser import parse
2 +from snakes.lang.ctlstar import asdl as ast
3 +from snakes.lang import getvars, bind
4 +import _ast
5 +
6 +class SpecError (Exception) :
7 + def __init__ (self, node, reason) :
8 + Exception.__init__(self, "[line %s] %s" % (node.lineno, reason))
9 +
10 +def astcopy (node) :
11 + if not isinstance(node, _ast.AST) :
12 + return node
13 + attr = {}
14 + for name in node._fields + node._attributes :
15 + value = getattr(node, name)
16 + if isinstance(value, list) :
17 + attr[name] = [astcopy(child) for child in value]
18 + else :
19 + attr[name] = astcopy(value)
20 + return node.__class__(**attr)
21 +
22 +class Builder (object) :
23 + def __init__ (self, spec) :
24 + self.spec = spec
25 + self.decl = {}
26 + for node in spec.atoms + spec.properties :
27 + if node.name in self.decl :
28 + raise SpecError(node, "%r already declare line %s"
29 + % (name.name, self.decl[name.name].lineno))
30 + self.decl[node.name] = node
31 + self.main = spec.main
32 + def build (self, node) :
33 + node = astcopy(node)
34 + return self._build(node, {})
35 + def _build (self, node, ctx) :
36 + if isinstance(node, ast.atom) :
37 + try :
38 + builder = getattr(self, "_build_%s" % node.__class__.__name__)
39 + except AttributeError :
40 + node.atomic = True
41 + else :
42 + node = builder(node, ctx)
43 + node.atomic = True
44 + elif isinstance(node, ast.CtlBinary) :
45 + node.left = self._build(node.left, ctx)
46 + node.right = self._build(node.right, ctx)
47 + node.atomic = (isinstance(node.op, (ast.boolop, ast.Imply,
48 + ast.Iff))
49 + and node.left.atomic
50 + and node.right.atomic)
51 + elif isinstance(node, ast.CtlUnary) :
52 + node.child = self._build(node.child, ctx)
53 + node.atomic = (isinstance(node.op, ast.Not)
54 + and node.child.atomic)
55 + else :
56 + assert False, "how did we get there?"
57 + return node
58 + def _build_place (self, param, ctx) :
59 + if isinstance(param, ast.Parameter) :
60 + if param.name not in ctx :
61 + raise SpecError(param, "place %r should be instantiated"
62 + % param.name)
63 + return ctx[param.name]
64 + else :
65 + return param
66 + def _build_InPlace (self, node, ctx) :
67 + node.data = [bind(child, ctx) for child in node.data]
68 + node.place = self._build_place(node.place, ctx)
69 + return node
70 + def _build_NotInPlace (self, node, ctx) :
71 + return self._build_InPlace(node, ctx)
72 + def _build_EmptyPlace (self, node, ctx) :
73 + node.place = self._build_place(node.place, ctx)
74 + return node
75 + def _build_MarkedPlace (self, node, ctx) :
76 + return self._build_EmptyPlace(node, ctx)
77 + # skip Deadlock and Boolean: nothing to do
78 + def _build_Quantifier (self, node, ctx) :
79 + node.place = self._build_place(node.place, ctx)
80 + ctx = ctx.copy()
81 + for name in node.vars :
82 + ctx[name] = ast.Token(name, node.place.place)
83 + node.child = self._build(node.child, ctx)
84 + return node
85 + def _build_Instance (self, node, ctx) :
86 + if node.name not in self.decl :
87 + raise SpecError(node, "undeclared object %r" % node.name)
88 + ctx = ctx.copy()
89 + decl = self.decl[node.name]
90 + for arg in decl.args :
91 + ctx[arg.name] = arg
92 + if isinstance(decl, ast.Property) :
93 + return self._build_Instance_Property(node, decl, ctx)
94 + else :
95 + return self._build_Instance_Atom(node, decl, ctx)
96 + def _build_Instance_Property (self, node, prop, ctx) :
97 + bound = set(a.name for a in prop.args)
98 + args = dict((a.arg, a.annotation) for a in node.args)
99 + for param in prop.params :
100 + if param.name in bound :
101 + raise SpecError(node, "argument %r already bound"
102 + % param.name)
103 + elif param.name in args :
104 + arg = args.pop(param.name)
105 + bound.add(param.name)
106 + else :
107 + raise SpecError(node, "missing argument %r" % param.name)
108 + if param.type == "place" :
109 + if not isinstance(arg, ast.Place) :
110 + raise SpecError(node, "expected place for %r"
111 + % param.name)
112 + arg.name = param.name
113 + ctx[param.name] = arg
114 + if args :
115 + raise SpecError(node, "too many arguments (%s)"
116 + % ", ".join(repr(a) for a in args))
117 + return self._build(astcopy(prop.body), ctx)
118 + def _build_Instance_Atom (self, node, atom, ctx) :
119 + bound = set(a.name for a in atom.args)
120 + args = dict((a.arg, a.annotation) for a in node.args)
121 + new = astcopy(atom)
122 + for param in atom.params :
123 + if param.name in bound :
124 + raise SpecError(node, "argument %r already bound"
125 + % param.name)
126 + elif param.name in args :
127 + arg = args.pop(param.name)
128 + bound.add(param.name)
129 + else :
130 + raise SpecError(node, "missing argument %r" % param.name)
131 + if param.type == "place" :
132 + if not isinstance(arg, ast.Place) :
133 + raise SpecError(node, "expected place for %r"
134 + % param.name)
135 + arg.name = param.name
136 + else :
137 + arg = ast.Argument(name=param.name,
138 + value=arg,
139 + type=param.type)
140 + new.args.append(arg)
141 + if args :
142 + raise SpecError(node, "too many arguments (%s)"
143 + % ", ".join(repr(a) for a in args))
144 + del new.params[:]
145 + return new
146 +
147 +def build (spec, main=None) :
148 + b = Builder(spec)
149 + if main is None :
150 + return b.build(spec.main)
151 + else :
152 + return b.build(main)
1 +#!/bin/sh
2 +exec python bin/abcd --dot ,railroad.png \
3 + --pnml ,railroad.pnml \
4 + doc/examples/abcd/railroad.abcd
...\ No newline at end of file ...\ No newline at end of file
1 +import doctest, sys, os, glob
2 +
3 +retcode = 0
4 +
5 +import snakes
6 +version = open("VERSION").read().strip()
7 +if snakes.version != version :
8 + print("Mismatched versions:")
9 + print(" snakes.version = %r" % snakes.version)
10 + print(" VERSION = %r" % version)
11 + sys.exit(1)
12 +
13 +def test (module) :
14 + print(" Testing '%s'" % module.__name__)
15 + f, t = doctest.testmod(module, #verbose=True,
16 + optionflags=doctest.NORMALIZE_WHITESPACE
17 + | doctest.REPORT_ONLY_FIRST_FAILURE
18 + | doctest.ELLIPSIS)
19 + return f
20 +
21 +modules = ["snakes",
22 + "snakes.hashables",
23 + "snakes.lang",
24 + "snakes.lang.python.parser",
25 + "snakes.lang.abcd.parser",
26 + "snakes.lang.ctlstar.parser",
27 + "snakes.data",
28 + "snakes.typing",
29 + "snakes.nets",
30 + "snakes.pnml",
31 + "snakes.plugins",
32 + "snakes.plugins.pos",
33 + "snakes.plugins.status",
34 + "snakes.plugins.ops",
35 + "snakes.plugins.synchro",
36 + "snakes.plugins.hello",
37 + "snakes.plugins.gv",
38 + "snakes.plugins.clusters",
39 + "snakes.plugins.labels",
40 + "snakes.utils.abcd.build",
41 + ]
42 +
43 +stop = False
44 +if len(sys.argv) > 1 :
45 + if sys.argv[1] == "--stop" :
46 + stop = True
47 + del sys.argv[1]
48 +
49 +doscripts = True
50 +if len(sys.argv) > 1 :
51 + modules = sys.argv[1:]
52 + doscripts = False
53 +
54 +for modname in modules :
55 + try :
56 + __import__(modname)
57 + retcode = max(retcode, test(sys.modules[modname]))
58 + if retcode and stop :
59 + break
60 + except :
61 + print(" Could not test %r:" % modname)
62 + c, e, t = sys.exc_info()
63 + print(" %s: %s" % (c.__name__, e))
64 +
65 +if doscripts :
66 + for script in (glob.glob("test-scripts/test*.sh")
67 + + glob.glob("test-scripts/test*.py")) :
68 + print(" Running '%s'" % script)
69 + retcode = max(retcode, os.system(script))
70 + if retcode and stop :
71 + break
72 +
73 +sys.exit(retcode)
1 +(provide 'abcd-mode)
2 +
3 +(define-derived-mode abcd-mode python-mode "ABCD"
4 + (font-lock-add-keywords
5 + nil
6 + `((,(concat "\\<\\(buffer\\|typedef\\|net\\|enum\\|task\\|const\\|symbol\\)\\>")
7 + 1 font-lock-keyword-face t))))
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.