1 Inlining can be considered similar to grammar productions. The path of
2 execution in Python is somewhat indirect due to the need to branch
3 continuously in order to perform work. Consider the following function calls:
4
5 x(n)
6 y(n)
7 z(n)
8
9 Where x, y and z are identifiable in advance and are stable, one can consider
10 the contents of these functions together. We can write the executed code using
11 the following abstract representation:
12
13 XYZ
14
15 However, it is rather likely that one instead sees things like this:
16
17 a.x(n)
18 b.y(n)
19 c.z(n)
20
21 Here, the functions called depend on what a, b and c are. This might be
22 written as follows using the abstract representation, borrowing from regular
23 expression notation:
24
25 (X|P)(Y|Q)(Z|R)
26
27 Here, P, Q and R are alternatives for X, Y and Z respectively. Within each of
28 these functions, other code is executed, and we might want to expand the
29 top-level "productions" to show the actual operations performed inside those
30 functions. Consider Y and Q being defined as follows:
31
32 def Y(n):
33 return n
34
35 def Q(n):
36 return n and Q(f(n))
37
38 This might change the abstract representation as follows:
39
40 (X|P)(Y|F*)(Z|R)
41
42 Here, Q evaluates n and either returns n immediately or calls itself with the
43 result of f (which we will consider as identical to F). Where Q does not have
44 a value of n that causes it to return immediately, F is invoked, and so F is
45 invoked repeatedly until a final invocation of Q that returns immediately.