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