Flow Control
Todo
This section is not finished yet. Provides more examples and explanations.
Variables
Variables should contain values of at most one type at each control flow point. For example, this means that joining control paths using the same variable to contain both a string and a int must be avoided.
Let’s look at this example code.
def compiler_error(arg):
v = 0 # v is an integer
if arg:
v = 1 # assign integer 1 to v
else:
v = "" # assign string "" to v
return v
def entry_point(argv): compiler_error(argv[1]); return 0
def target(*args): return entry_point
The control flow graph of the compiler_error
function is shown in the
following figure.
As you can see, at the merge point (highlighted in green), v2
can be
either integer 1
or an empty string ''
. this violate the RPython’s
restriction.
It is allowed to mix None
with many other types: wrapped objects, class
instances, lists, dicts, strings, etc., but not with int, floats or tuples.
class Obj():
pass
def flow_control_variables_unsupported(arg):
"""
int, floats or tuples cannot be mixed with None.
"""
i = None # integer
f = None # float
t = None # tuple
if arg:
i = None
f = None
t = None
else:
i = 0
f = 0.0
t = (1, 2, 3)
return i, f, t
def flow_control_variables(arg):
"""
It is allowed to mix None with many other types: wrapped objects, class
instances, lists, dicts, strings, etc.
"""
o = None # object instance
l = None # list
d = None # dict
s = None # string
if arg:
o = None
l = None
d = None
s = None
else:
o = Obj()
l = [1, 2, 3]
d = {1: "123"}
s = "hello"
if o and l and d and s:
print o, l, d[1], s
return o, l, d, s
def entry_point(argv): flow_control_variables(int(argv[1])); return 0
def target(*args): return entry_point
Constants
Note
All module globals are considered constants. Their binding must not be changed at run-time. Moreover, global (i.e. prebuilt) lists and dictionaries are supposed to be immutable: modifying e.g. a global list will give inconsistent results. However, global instances don’t have this restriction, so if you need mutable global state, store it in the attributes of some prebuilt singleton instance.
Control structures
Note
All allowed, for loops restricted to builtin types, generators very restricted.
Range
Note
Range and xrange are identical. range does not necessarily create an array, only if the result is modified. It is allowed everywhere and completely implemented. The only visible difference to CPython is the inaccessibility of the xrange fields start, stop and step.
Definitions
Note
Run-time definition of classes or functions is not allowed.
Generators
Note
Generators are supported, but their exact scope is very limited. you can’t merge two different generator in one control point.
Exceptions
Python exceptions are fully supported. For example, you can catch exceptions by
the except
keyword following a specific exception class.
def exceptions(x, y):
try:
n = x / y
except ZeroDivisionError:
print "division by zero"
def entry_point(argv):
exceptions(int(argv[1]), int(argv[2]))
return 0
def target(*args): return entry_point
if __name__ == "__main__": import sys; entry_point(sys.argv)
You can also use the raise
keyword to raise exceptions. The finally
keyword
is used to do some cleanup actions.
class B(Exception):
pass
class C(B):
pass
class D(C):
pass
def exceptions():
for cls in [B, C, D]:
try:
raise cls()
except D:
print("exception D")
except C:
print("exception C")
except B:
print("exception B")
finally:
print("put clean-up actions here")
def entry_point(argv):
exceptions()
return 0
def target(*args): return entry_point
if __name__ == "__main__": import sys; entry_point(sys.argv)
Attention
There is one special difference in the exception handling on “simple cases”. In RPython document, it says by default, code with no exception handlers does not raise exceptions. By supplying an exception handler, you ask for error checking. Without, you assure the system that the operation cannot fail. This rule does not apply to function calls: any called function is assumed to be allowed to raise any exception.
Todo
MesaPy added mandatory IndexError
checks. Give some details here.