Lichen

docs/wiki/Representations

861:f745d151a441
2018-08-17 Paul Boddie Wrapped text in the documentation for more convenient "offline" editing.
     1 = Representing Program Objects =     2      3 Certain representations have been chosen for program objects that attempt to     4 support efficient access to those objects during the execution of a program.     5      6 <<TableOfContents(2,2)>>     7      8 == Attributes ==     9     10 The principal means of referring to an object in a program is by using an    11 '''attribute''', having this name because it is the representation of an    12 attribute in classes, instances and modules. Each attribute can hold a    13 reference to an object, known as the '''value''', or other kinds of data:    14     15 {{{#!graphviz    16 //format=svg    17 //transform=notugly    18 digraph attributes {    19   node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Attributes"];    20   edge [fontsize="13.0",fontname="Helvetica",tooltip="Attributes"];    21   rankdir=TB;    22     23   attrA [label="attribute | { value |<value> reference to object }",shape=record];    24   obj1 [label="<main> object | { attr1 | value } | { attr2 | value } | ...",shape=record];    25     26   attrB [label="attribute | { intvalue |<intvalue> 12345 }",shape=record];    27     28   attrA:value -> obj1:main;    29 }    30 }}}    31     32 Although a value indicates a specific object of interest for an attribute, if    33 the object is callable then additional '''context''' information may be    34 required to call the object. Such context information is not stored in an    35 attribute record but is instead obtained from the object itself, if    36 appropriate.    37     38 === Integer Representation ===    39     40 The `intvalue` member of the attribute structure is employed instead of the    41 `value` member to store integer values. Since `value` normally holds a    42 pointer, and since pointers are often aligned to certain address boundaries on    43 many modern platforms (usually four-byte boundaries on 32-bit platforms,    44 eight-byte boundaries on 64-bit platforms, two-byte boundaries on platforms    45 with 16-bit addressing), the lowest significant bit (bit 0) will typically be    46 zero for a valid pointer. Consequently, by setting bit 0 to 1, other data can    47 be stored in the remaining bits and be distinguished from pointer information.    48 Obviously, operations on attributes first need to test whether the `value`    49 member or the `intvalue` member is in use by testing bit 0.    50     51 Thus, integers are transformed and stored directly within attributes, and they    52 are therefore passed around by value. When an attribute of an integer needs to    53 be accessed, the operation usually providing the `value` member, thus    54 obtaining an instance under normal circumstances, instead provides the address    55 of a common integer instance. This instance may then provide instance    56 attributes, whose values will be the same for all integers, or class    57 attributes through a reference to the integer (`int`) class.    58     59 Each method provided by `int`, when called, will be given the original    60 attribute for which the method was obtained as its context. In such methods,    61 operations on the context via `self` will either involve the propagation of    62 the attribute to other functions or methods or attribute accesses on `self`,    63 yielding common instance attributes or class attributes as already described.    64 Only native functions will attempt to interpret the attribute in a different    65 way, decoding the representation, performing arithmetic or logical operations,    66 and encoding the result in a new attribute.    67     68 == Contexts and Wrappers ==    69     70 The context of an object is of significance if that object is callable. For    71 example, an instance may permit access to a method via an attribute. Since the    72 method will be callable, and since the method is accessed via the instance,    73 the context of that method will be the instance. In order to retain both    74 context and value information, a '''wrapper''' may be created.    75     76 {{{#!graphviz    77 //format=svg    78 //transform=notugly    79 digraph wrappers {    80   node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Wrappers"];    81   edge [fontsize="13.0",fontname="Helvetica",tooltip="Wrappers"];    82   rankdir=TB;    83     84   inst [label="<main> instance | { attr1 |<attr1> reference to method } | { attr2 | value } | ...",shape=record];    85   method [label="<main> method | ...",shape=record];    86   wrapper [label="<main> wrapper | { __context__ |<context> reference to instance } | { __value__ |<value> reference to method } | ...",shape=record];    87     88   inst:attr1 -> method:main;    89   wrapper:context -> inst:main;    90   wrapper:value -> method:main;    91 }    92 }}}    93     94 The context is not always the accessor of the object - in this case, the    95 instance - because the object may already be a wrapper with its own context.    96     97 == Objects ==    98     99 Classes, instances and modules are objects, and all of these kinds of objects   100 provide metadata describing the type of each object, together with a   101 collection of attributes forming the contents of such objects.   102    103 {{{#!graphviz   104 //format=svg   105 //transform=notugly   106 digraph objects {   107   node [shape=box,fontsize="13.0",fontname="Helvetica",tooltip="Objects"];   108   edge [fontsize="13.0",fontname="Helvetica",tooltip="Objects"];   109   rankdir=TB;   110    111   instC [label="<main> instance of C | { 0 | reference to\ninstance table } | { __class__ |<cls> reference\nto C } | { a | value } | { b | value } | ...",shape=record];   112   clsC [label="<main> class C | { class identifier | reference to\nclass table } | { __class__ |<cls> reference\nto type } | { __fn__ | instantiator\nreference } | { __args__ | reference to\nparameter table } | { f | <f> reference\nto f } | { g | value } | ...",shape=record];   113   methodF [label="<main> function f | { 0 | reference to\ninstance table } | { __class__ |<cls> reference\nto function } | { __fn__ | method\nreference } | { __args__ | reference to\nparameter table } | ...",shape=record];   114   function [label="<main> class function | { class identifier | reference to\nclass table } | { __class__ |<cls> reference\nto type } | ...",shape=record];   115   type [label="<main> class type | { class identifier | reference to\nclass table } | { __class__ |<cls> reference\nto type } | ...",shape=record];   116    117   instC:cls -> clsC:main;   118   clsC:cls -> type:main;   119   clsC:f -> methodF:main;   120   methodF:cls -> function:main;   121 }   122 }}}   123    124 Classes are represented by structures whose members reference class attributes   125 and class metadata (the class table), as well as incorporating invocation   126 metadata (the `__args__` and `__fn__` special attributes).   127    128 Instances are represented by structures whose members reference instance   129 attributes (including `__class__` which indicates the class instantiated by a   130 given instance) and instance metadata (the instance table), as well as   131 incorporating invocation metadata (the `__args__` and `__fn__` special   132 attributes).   133    134 Functions are instances of a general function type that does not permit   135 additional, general instance attributes. However, function instance structures   136 may have extra members corresponding to default parameter values. Access to   137 such extra members is performed using the minimum and maximum values provided   138 via `__args__` and with knowledge of the number of declared instance   139 attributes indicated by the instance table for the function type.   140    141 Modules are represented by structures whose members reference module   142 attributes and module metadata (the module table).   143    144 == Special Members ==   145    146 All object representations support the following special members describing   147 the invocation properties of each object:   148    149 {{{#!table   150 `__args__` || the minimum number of arguments supported in an invocation and a   151            .. reference to the parameter table for the object   152 ==   153 `__fn__` || a reference to a native function containing the actual code run   154          .. when calling the object   155 }}}   156    157 Classes are invoked in order to create instances of each class   158 ('''instantiation'''). Instances may support invocation by providing a   159 `__call__` method. Functions are supported by instances of a general function   160 class. Modules are generally not callable and will not actually provide these   161 special members in practice.   162    163 All object representations support information about their type:   164    165 {{{#!table   166 `__class__`   167 || the class of the object: instances refer to their classes, classes refer to   168 .. the `type` class, functions are instances that refer to the `function`   169 .. class, modules refer to the `module` class   170 }}}   171    172 Certain kinds of object support other descriptive attributes:   173    174 {{{#!table   175 `__name__` || the name of a class or a function   176 ==   177 `__parent__` || the parent scope of a class or a function   178 }}}   179    180 Objects supported by native, system-level functionality require a means of   181 retaining information in special attributes:   182    183 {{{#!table   184 `__data__` || private data manipulated at the native level   185 }}}   186    187 Strings support special annotation attributes that permit their use in   188 dynamically resolving attributes:   189    190 {{{#!table   191 `__key__` || the code and position of the attribute whose name is represented   192           .. by the string   193 }}}   194    195 Such "key" attributes provide information that can be used to inspect an   196 object table and to test for the presence of an attribute. With such   197 information, the `getattr` and `hasattr` functions can be supported.   198    199 == Attribute Tables ==   200    201 In order to provide information about the attributes supported by each object,   202 the structure of each object will reference a table containing entries   203 describing these supported attributes. The size of this table is declared   204 within the table structure, and for each position in the table an entry   205 corresponding to the same position within an actual object structure describes   206 the nature of the attribute at that position.   207    208 == Parameter Tables ==   209    210 In order to support argument validation and keyword arguments in invocations,   211 a structure is referenced by `__args__` that indicates...   212    213  * The minimum number of parameters supported by a callable   214  * The maximum number of parameters supported by a callable   215  * The size of the table describing the parameters   216  * A table of entries with each entry indicating the nature of a parameter (in   217    effect, which name it uses, albeit as a generated code instead of a string)   218    and the position of the parameter in any argument list prepared for an   219    invocation   220    221 Parameter tables only need to be consulted at run-time if the nature of a   222 callable is undetermined. By supporting a uniform interface, the arguments   223 used in an invocation can be tested against the description provided by   224 `__args__` and the table.