micropython

docs/structures.txt

137:f660fe1aac5c
2008-09-01 Paul Boddie Added notes about calling initialisers and instantiators, adopting a strategy where instantiation detected at compile-time is performed using an initialiser directly, whereas that detected at run-time is done using an instantiator whose code is now generated in the image. Added a finalise method to the Importer in order to set attribute locations before code generation, since some code (use of initialisers) requires details of a different program unit's locals (although this is actually unnecessary, but done because Attr instances are employed in the generated code). Changed class invocation at compile-time to acquire the new object reference from the frame of an already invoked initialiser just before dropping the frame. Added some support for raw image encoding of classes and functions. Changed JumpWithFrame usage to involve the current callable, not the current value. Added RecoverFrame and AdjustFrame instructions. Improved the tests around instantiation.
     1 Data Structures
     2 ===============
     3 
     4 The fundamental "value type" is a pair of references: one pointing to the
     5 referenced object represented by the interchangeable value; one referring to
     6 the context of the referenced object, typically the object through which the
     7 referenced object was acquired as an attribute.
     8 
     9 Value Layout
    10 ------------
    11 
    12     0           1
    13     object      context
    14     reference   reference
    15 
    16 Values and Contexts
    17 -------------------
    18 
    19 Values are acquired through name lookups and attribute access, yielding
    20 the appropriate object reference together with a context reference as
    21 indicated in the following table:
    22 
    23     Type of Access          Context     Notes
    24     --------------          -------     -----
    25 
    26     Local name              Preserved   Functions provide no context
    27 
    28     Global name             Preserved   Modules provide no context
    29 
    30     Class-originating       Accessor    Class accessor preserves the stored
    31     attribute                 -or-      context; instance accessor overrides
    32                             Preserved   the stored context if it is null or
    33                                         belongs to the instance's class
    34                                         hierarchy
    35 
    36     Instance-originating    Preserved   Methods retain their original context
    37     attribute
    38 
    39 There may be some scope for simplifying the above, to the detriment of Python
    40 compatibility, since the unbound vs. bound methods situation can be confusing.
    41 
    42 Acquiring Values
    43 ----------------
    44 
    45 According to the table describing value acquisition, different instructions
    46 must implement different operations when acquiring values:
    47 
    48     Instruction     Purpose                 Context Operations
    49     -----------     -------                 ------------------
    50 
    51     LoadConst       Load class, function,   Combine null context with loaded
    52                     module, constant        object
    53 
    54     LoadAddress     Load attribute from     Classes, functions and modules
    55                     known object            cause the loaded attribute to be
    56                                             retrieved unchanged; whereas
    57                                             constants (representing instances)
    58                                             cause the constant to override the
    59                                             attribute's own context (since all
    60                                             attributes should belong to the
    61                                             constant's class hierarchy)
    62 
    63     LoadAddressContext                      Override loaded context with a
    64                                             predetermined object (provided
    65                                             that the object and context are
    66                                             compatible, which can be tested at
    67                                             compile-time)
    68 
    69     LoadAttr        Load attribute from     Attributes with null contexts or
    70                     instance                contexts compatible with the
    71                                             instance cause loaded attributes
    72                                             to combine the instance as context
    73                                             with the object from the
    74                                             attribute; other attributes have
    75                                             their context preserved
    76 
    77     LoadAttrIndex   Load attribute from     Functions and modules as unknown
    78                     object                  the unknown object accessor cause
    79                                             the loaded attribute to be
    80                                             retrieved unchanged; classes and
    81                                             instances cause the LoadAttr rules
    82                                             to apply (class compatibility
    83                                             applies)
    84 
    85 A certain amount of run-time testing might be required for both LoadAttr and
    86 LoadAttrIndex instructions. However, with certain restrictions in place around
    87 class attributes, some simplifications are possible:
    88 
    89   * Since only class-originating attributes may cause context overriding, and
    90     since class attributes may only be defined within class definitions, the
    91     attributes whose context may be modified should be known at compile-time.
    92     (These will be those attributes whose context agrees with their parent
    93     class.)
    94 
    95   * By recording a special context value for attributes whose context can be
    96     overridden, this value can be tested efficiently at run-time where the
    97     appropriate conditions are satisfied. (This special context value or
    98     indicator will be present in the object table record for the attribute.)
    99 
   100   * It should be possible to move the instance compatibility condition testing
   101     to compile-time by testing the compatibility of the origin of an attribute
   102     with the class on which it is stored. However, some compatibility testing
   103     will still be required if invoking methods via classes, since the instance
   104     will be specified in the argument list instead of being presented in an
   105     attribute lookup instruction.
   106 
   107 Storing Values
   108 --------------
   109 
   110 According to the table describing value acquisition, different instructions
   111 must implement different operations when acquiring values:
   112 
   113     Instruction     Purpose                 Context Operations
   114     -----------     -------                 ------------------
   115 
   116     StoreAddress    Store attribute in a    Preserve context; note that no
   117                     known object            test for class attribute
   118                                             assignment should be necessary
   119                                             since this instruction should only
   120                                             be generated for module globals
   121 
   122     StoreAttr       Store attribute in an   Preserve context; note that no
   123                     instance                test for class attribute
   124                                             assignment should be necessary
   125                                             since this instruction should only
   126                                             be generated for self accesses
   127 
   128     StoreAttrIndex  Store attribute in an   Preserve context; since the index
   129                     unknown object          lookup could yield a class
   130                                             attribute, a test of the nature of
   131                                             the nature of the structure is
   132                                             necessary in order to prevent
   133                                             assignments to classes
   134 
   135 Objects
   136 -------
   137 
   138 Since classes, functions and instances are all "objects", each must support
   139 certain features and operations in the same way.
   140 
   141 The __class__ Attribute
   142 -----------------------
   143 
   144 All objects support the __class__ attribute:
   145 
   146 Class: refers to the type class (type.__class__ also refers to the type class)
   147 Function: refers to the function class
   148 Instance: refers to the class instantiated to make the object
   149 
   150 Invocation
   151 ----------
   152 
   153 The following actions need to be supported:
   154 
   155 Class: create instance, call __init__ with instance, return object
   156 Function: call function body, return result
   157 Instance: call __call__ method, return result
   158 
   159 Structure Layout
   160 ----------------
   161 
   162 A suitable structure layout might be something like this:
   163 
   164     Identifier  Identifier  Address     Details     Type        Object      ...
   165 
   166     0           1           2           3           4           5           6
   167     classcode   attrcode    invocation  invocation  __class__   attribute   ...
   168                             reference   #args,      reference   reference
   169                                         defaults
   170                                         reference
   171 
   172 Here, the classcode refers to the attribute lookup table for the object. Since
   173 classes and instances share the same classcode, they might resemble the
   174 following:
   175 
   176 Class C:
   177 
   178     0           1           2           3           4           5           6
   179     code for C  attrcode    __new__     __new__     class type  attribute   ...
   180                 for C       reference   #args,      reference   reference
   181                                         defaults
   182                                         reference
   183 
   184 Instance of C:
   185 
   186     0           1           2           3           4           5           6
   187     code for C  attrcode    C.__call__  C.__call__  class C     attribute   ...
   188                 for C       reference   #args,      reference   reference
   189                             (if exists) defaults
   190                                         reference
   191 
   192 The __new__ reference would lead to code consisting of the following
   193 instructions:
   194 
   195     create instance for C
   196     call C.__init__(instance, ...)
   197     return instance
   198 
   199 If C has a __call__ attribute, the invocation "slot" of C instances would
   200 refer to the same thing as C.__call__.
   201 
   202 For functions, the same general layout applies:
   203 
   204 Function f:
   205 
   206     0           1           2           3           4           5           6
   207     code for    attrcode    code        code        class       attribute   ...
   208     function    for         reference   #args,      function    (default)
   209                 function                defaults    reference   reference
   210                                         reference
   211 
   212 Here, the code reference would lead to code for the function. Note that the
   213 function locals are completely distinct from this structure and are not
   214 comparable to attributes. Instead, attributes are reserved for default
   215 parameter values.
   216 
   217 For modules, there is no meaningful invocation reference:
   218 
   219 Module m:
   220 
   221     0           1           2           3           4           5           6
   222     code for m  attrcode    (unused)    (unused)    module type attribute   ...
   223                 for m                               reference   (global)
   224                                                                 reference
   225 
   226 Both classes and modules have code in their definitions, but this would be
   227 generated in order and not referenced externally.
   228 
   229 Invocation Operation
   230 --------------------
   231 
   232 Consequently, regardless of the object an invocation is always done as
   233 follows:
   234 
   235     get invocation reference (at object+1)
   236     jump to reference
   237 
   238 Additional preparation is necessary before the above code: positional
   239 arguments must be saved to the parameter stack, and keyword arguments must be
   240 resolved and saved to the appropriate position in the parameter stack.
   241 
   242 Attribute Operations
   243 --------------------
   244 
   245 Attribute access needs to go through the attribute lookup table. Some
   246 optimisations are possible and are described in the appropriate section.
   247 
   248 One important aspect of attribute access is the appropriate setting of the
   249 context in the acquired attribute value. From the table describing the
   250 acquisition of values, it is clear that the principal exception is that where
   251 a class-originating attribute is accessed on an instance. Consequently, the
   252 following algorithm could be employed once an attribute has been located:
   253 
   254  1. If the attribute's context is a special value, indicating that it should
   255     be replaced upon instance access, then proceed to the next step;
   256     otherwise, acquire both the context and the object as they are.
   257 
   258  2. If the accessor is an instance, use that as the value's context, acquiring
   259     only the object from the attribute.
   260 
   261 Where accesses can be determined ahead of time (as discussed in the
   262 optimisations section), the above algorithm may not necessarily be employed in
   263 the generated code for some accesses.
   264 
   265 Instance/Class Compatibility
   266 ----------------------------
   267 
   268 Although it would be possible to have a data structure mapping classes to
   269 compatible classes, which in the case of context (or self argument)
   270 suitability in invocations would involve a mapping from a class to itself plus
   271 its descendants, the need to retain the key to such a data structure for each
   272 class might introduce a noticeable overhead. Such a structure would
   273 effectively be a matrix with each dimension indexed using the same sequence of
   274 codes for each of the classes in a program.
   275 
   276 An alternative might be to insert descendants as special attributes into the
   277 object/attribute lookup table. This would also require an extra key to be
   278 retained, since each class would have its own attribute code.