Thanks to class Expression
, one may execute arbitrary Python
expressions, however, it is often necessary to import modules or use
existing objects (in particular functions), which is not possible from
within expressions.
To address this need, every instance of PetriNet
is equipped with an
attribute globalise
that holds a dict-like object used as the context
for evaluating the expressions embedded in the net and its components.
Consider for example, a net in which we use a guard that needs
constant math.pi
:
>>> from snakes.nets import *
>>> net = PetriNet("my net")
>>> trans = Transition("t", Expression("math.pi > 3"))
>>> net.add_transition(trans)
>>> net.add_place(Place("p", [dot]))
>>> net.add_input("p", "t", Value(dot))
>>> trans.modes()
Traceback (most recent call last):
...
NameError: name 'math' is not defined
(Note that we add a place and an input arc because disconnected
transitions in SNAKES have no modes at all so that trans.modes()
would return []
without even trying to evaluate the guard.) Because
module math
is not imported, we have a NameError
. But importing
math
will not solve the problem because we do it in the context of
your Python shell but not in that of the net:
>>> import math
>>> trans.modes()
Traceback (most recent call last):
...
NameError: name 'math' is not defined
The solution is to execute statement import math
in the context of
globals
as follows:
>>> net.globals.declare("import math")
>>> trans.modes()
[Substitution()]
Method net.globals.declare
expects a Python statement that is
exec
-ed in the context of the dict-like net.globals
. So our
import math
now has an effect that is remembered for all the
evaluations that will take place within the net. Because net.globals
is a dict-like structure, it is also possible to assign keys directly
to objects.
>>> bis = Transition("b", Expression("math.pi > THREE"))
>>> net.add_transition(bis)
>>> net.add_input("p", "b", Value(dot))
>>> bis.modes()
Traceback (most recent call last):
...
NameError: name 'THREE' is not defined
>>> net.globals["THREE"] = 3
>>> bis.modes()
[Substitution()]