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