1 Namespace Definition
2 ====================
3
4 Module attributes are defined either at the module level or by global
5 statements.
6
7 Class attributes are defined only within class statements.
8
9 Instance attributes are defined only by assignments to attributes of self
10 within __init__ methods.
11
12 Data Structures
13 ===============
14
15 Since classes, functions and instances are all "objects", each must support
16 certain features and operations in the same way.
17
18 The __class__ Attribute
19 -----------------------
20
21 All objects support the __class__ attribute:
22
23 Class: refers to the type class (type.__class__ also refers to the type class)
24 Function: refers to the function class
25 Instance: refers to the class instantiated to make the object
26
27 Invocation
28 ----------
29
30 The following actions need to be supported:
31
32 Class: create instance, call __init__ with instance, return object
33 Function: call function body, return result
34 Instance: call __call__ method, return result
35
36 Structure Layout
37 ----------------
38
39 A suitable structure layout might be something like this:
40
41 0 1 2 3 4
42 classcode invocation __class__ attribute ...
43 reference reference reference
44
45 Here, the classcode refers to the attribute lookup table for the object. Since
46 classes and instances share the same classcode, they might resemble the
47 following:
48
49 Class C:
50
51 0 1 2 3 4
52 code for C __new__ class type attribute ...
53 reference reference reference
54
55 Instance of C:
56
57 0 1 2 3 4
58 code for C C.__call__ class C attribute ...
59 reference reference reference
60 (if exists)
61
62 The __new__ reference would lead to code consisting of the following
63 instructions:
64
65 create instance for C
66 call C.__init__(instance, ...)
67 return instance
68
69 If C has a __call__ attribute, the invocation "slot" of C instances would
70 refer to the same thing as C.__call__.
71
72 For functions, the same general layout applies:
73
74 Function f:
75
76 0 1 2 3 4
77 code for code class attribute ...
78 function reference function reference
79 reference
80
81 Here, the code reference would lead to code for the function.
82
83 Invocation Operation
84 --------------------
85
86 Consequently, regardless of the object an invocation is always done as
87 follows:
88
89 get invocation reference (at object+1)
90 jump to reference
91
92 Additional preparation is necessary before the above code: positional
93 arguments must be saved to the parameter stack, and keyword arguments must be
94 resolved and saved to the appropriate position in the parameter stack.
95
96 Attribute Operations
97 --------------------
98
99 Attribute access needs to go through the attribute lookup table.
100
101 Instruction Evaluation Model
102 ============================
103
104 Programs use a value stack where evaluated instructions may save their
105 results. A value stack pointer indicates the top of this stack. In addition, a
106 separate stack is used to record the invocation frames. All stack pointers
107 refer to the next address to be used by the stack, not the address of the
108 uppermost element.
109
110 Frame Stack Value Stack
111 ----------- ----------- Address of Callable
112 -------------------
113 previous ...
114 current ------> callable -----> identifier
115 arg1 reference to code
116 arg2
117 arg3
118 local4
119 local5
120 ...
121
122 Loading local names is a matter of performing frame-relative accesses to the
123 value stack.
124
125 Invocations and Argument Evaluation
126 -----------------------------------
127
128 When preparing for an invocation, the caller first sets the invocation frame
129 pointer. Then, positional arguments are added to the stack such that the first
130 argument positions are filled. A number of stack locations for the remaining
131 arguments specified in the program are then reserved. The names of keyword
132 arguments are used (in the form of table index values) to consult the
133 parameter table and to find the location in which such arguments are to be
134 stored.
135
136 fn(a, b, d=1, e=2, c=3) -> fn(a, b, c, d, e)
137
138 Value Stack
139 -----------
140
141 ... ... ... ...
142 fn fn fn fn
143 a a a a
144 b b b b
145 ___ ___ ___ --> 3
146 ___ --> 1 1 | 1
147 ___ | ___ --> 2 | 2
148 1 ----------- 2 ----------- 3 -----------
149
150 Conceptually, the frame can be considered as a collection of attributes, as
151 seen in other kinds of structures:
152
153 Frame for invocation of fn:
154
155 0 1 2 3 4 5
156 code a b c d e
157 reference
158
159 However, where arguments are specified positionally, such "attributes" are not
160 set using a comparable approach to that employed with other structures.
161 Keyword arguments are set using an attribute-like mechanism, though, where the
162 position of each argument discovered using the parameter table.
163
164 Tuples, Frames and Allocation
165 -----------------------------
166
167 Using the approach where arguments are treated like attributes in some kind of
168 structure, we could choose to allocate frames in places other than a stack.
169 This would produce something somewhat similar to a plain tuple object.
170
171 Optimisations
172 =============
173
174 Some optimisations around constant objects might be possible; these depend on
175 the following:
176
177 * Reliable tracking of assignments: where assignment operations occur, the
178 target of the assignment should be determined if any hope of optimisation
179 is to be maintained. Where no guarantees can be made about the target of
180 an assignment, no assignment-related information should be written to
181 potential targets.
182
183 * Objects acting as "containers" of attributes must be regarded as "safe":
184 where assignments are recorded as occurring on an attribute, it must be
185 guaranteed that no other unforeseen ways exist to assign to such
186 attributes.
187
188 The discussion below presents certain rules which must be imposed to uphold
189 the above requirements.
190
191 Safe Containers
192 ---------------
193
194 Where attributes of modules, classes and instances are only set once and are
195 effectively constant, it should be possible to circumvent the attribute lookup
196 mechanism and to directly reference the attribute value. This technique may
197 only be considered applicable for the following "container" objects, subject
198 to the noted constraints:
199
200 1. For modules, "safety" is enforced by ensuring that assignments to module
201 attributes are only permitted within the module itself either at the
202 top-level or via names declared as globals. Thus, the following would not
203 be permitted:
204
205 another_module.this_module.attr = value
206
207 In the above, this_module is a reference to the current module.
208
209 2. For classes, "safety" is enforced by ensuring that assignments to class
210 attributes are only permitted within the class definition, outside
211 methods. This would mean that classes would be "sealed" at definition time
212 (like functions).
213
214 Unlike the property of function locals that they may only sensibly be accessed
215 within the function in which they reside, these cases demand additional
216 controls or assumptions on or about access to the stored data. Meanwhile, it
217 would be difficult to detect eligible attributes on arbitrary instances due to
218 the need for some kind of type inference or abstract execution.
219
220 Constant Attributes
221 -------------------
222
223 When accessed via "safe containers", as described above, any attribute with
224 only one recorded assignment on it can be considered a constant attribute and
225 this eligible for optimisation, the consequence of which would be the
226 replacement of a LoadAttrIndex instruction (which needs to look up an
227 attribute using the run-time details of the "container" and the compile-time
228 details of the attribute) with a LoadAttr instruction.
229
230 However, some restrictions exist on assignment operations which may be
231 regarded to cause only one assignment in the lifetime of a program:
232
233 1. For module attributes, only assignments at the top-level outside loop
234 statements can be reliably assumed to cause only a single assignment.
235
236 2. For class attributes, only assignments at the top-level within class
237 definitions and outside loop statements can be reliably assumed to cause
238 only a single assignment.
239
240 All assignments satisfying the "safe container" requirements, but not the
241 requirements immediately above, should each be recorded as causing at least
242 one assignment.
243
244 Additional Controls
245 -------------------
246
247 For the above cases for "container" objects, the following controls would need
248 to apply:
249
250 1. Modules would need to be immutable after initialisation. However, during
251 initialisation, there remains a possibility of another module attempting
252 to access the original module. For example, if ppp/__init__.py contained
253 the following...
254
255 x = 1
256 import ppp.qqq
257 print x
258
259 ...and if ppp/qqq.py contained the following...
260
261 import ppp
262 ppp.x = 2
263
264 ...then the value 2 would be printed. Since modules are objects which are
265 registered globally in a program, it would be possible to set attributes
266 in the above way.
267
268 2. Classes would need to be immutable after initialisation. However, since
269 classes are objects, any reference to a class after initialisation could
270 be used to set attributes on the class.
271
272 Solutions:
273
274 1. Insist on global scope for module attribute assignments.
275
276 2. Insist on local scope within classes.
277
278 Both of the above measures need to be enforced at run-time, since an arbitrary
279 attribute assignment could be attempted on any kind of object, yet to uphold
280 the properties of "safe containers", attempts to change attributes of such
281 objects should be denied. Since foreseen attribute assignment operations have
282 certain properties detectable at compile-time, it could be appropriate to
283 generate special instructions (or modified instructions) during the
284 initialisation of modules and classes for such foreseen assignments, whilst
285 employing normal attribute assignment operations in all other cases. Indeed,
286 the StoreAttr instruction, which is used to set attributes in "safe
287 containers" would be used exclusively for this purpose; the StoreAttrIndex
288 instruction would be used exclusively for all other attribute assignments.
289
290 Constant Attribute Values
291 -------------------------
292
293 Where an attribute value is itself regarded as constant, is a "safe container"
294 and is used in an operation accessing its own attributes, the value can be
295 directly inspected for optimisations or employed in the generated code. For
296 the attribute values themselves, only objects of a constant nature may be
297 considered suitable for this particular optimisation:
298
299 * Classes
300 * Modules
301 * Instances defined as constant literals
302
303 This is because arbitrary objects (such as most instances) have no
304 well-defined form before run-time and cannot be investigated further at
305 compile-time or have a representation inserted into the generated code.
306
307 Class Attributes and Access via Instances
308 -----------------------------------------
309
310 Unlike module attributes, class attributes can be accessed in a number of
311 different ways:
312
313 * Using the class itself:
314
315 C.x = 123
316 cls = C; cls.x = 234
317
318 * Using a subclass of the class (for reading attributes):
319
320 class D(C):
321 pass
322 D.x # setting D.x would populate D, not C
323
324 * Using instances of the class or a subclass of the class (for reading
325 attributes):
326
327 c = C()
328 c.x # setting c.x would populate c, not C
329
330 Since assignments are only achieved using direct references to the class, and
331 since class attributes should be defined only within the class initialisation
332 process, the properties of class attributes should be consistent with those
333 desired.
334
335 Method Access via Instances
336 ---------------------------
337
338 It is desirable to optimise method access, even though most method calls are
339 likely to occur via instances. It is possible, given the properties of methods
340 as class attributes to investigate the kind of instance that the self
341 parameter/local refers to within each method: it should be an instance either
342 of the class in which the method is defined or a compatible class, although
343 situations exist where this might not be the case:
344
345 * Explicit invocation of a method:
346
347 d = D() # D is not related to C
348 C.f(d) # calling f(self) in C
349
350 If blatant usage of incompatible instances were somehow disallowed, it would
351 still be necessary to investigate the properties of an instance's class and
352 its relationship with other classes. Consider the following example:
353
354 class A:
355 def f(self): ...
356
357 class B:
358 def f(self): ...
359 def g(self):
360 self.f()
361
362 class C(A, B):
363 pass
364
365 Here, instances of B passed into the method B.g could be assumed to provide
366 access to B.f when self.f is resolved at compile-time. However, instances of C
367 passed into B.g would instead provide access to A.f when self.f is resolved at
368 compile-time (since the method resolution order is C, A, B instead of just B).
369
370 One solution might be to specialise methods for each instance type, but this
371 could be costly. Another less ambitious solution might only involve the
372 optimisation of such internal method calls if an unambiguous target can be
373 resolved.
374
375 Optimising Function Invocations
376 -------------------------------
377
378 Where an attribute value is itself regarded as constant and is a function,
379 knowledge about the parameters of the function can be employed to optimise the
380 preparation of the invocation frame.