Lichen

docs/wiki/Deduction

1022:582d834d392d
14 months ago Paul Boddie Merged changes from the value-replacement branch. value-replacement-for-wrapper
     1 = Deducing Program Behaviour =     2      3 With information from [[../Inspection|inspection]] available, the isolated     4 observations about operations in a program may now be combined with knowledge     5 about the program's structure to produce deductions about the nature of each     6 operation.     7      8 <<TableOfContents(2,3)>>     9     10 == The Deduction Process ==    11     12 The deduction process takes observations made during the [[../Inspection|    13 inspection process]] and attempts to form deductions about the behaviour of    14 the program primarily in terms of the nature of the attribute '''accesses''',    15 with their corresponding '''accessors''', featuring in the program. Where    16 attributes are used in conjunction with names, accessors are name versions;    17 where attributes are used in conjunction with other expressions, accessors are    18 '''anonymous'''.    19     20 === Indexes ===    21     22 For efficiency, indexes are defined to establish relationships between the    23 following things:    24     25 {{{#!table    26 '''Indexes''' || '''From''' || '''To''' || '''Purpose'''    27 ==    28 `access_index`    29 || access operation    30 || accessor (name version)    31 || defining types at access locations    32 ==    33 `access_index_rev`    34 || accessor (name version)    35 || access operations    36 || determining whether names are used for accesses; establishing alias    37 .. information    38 ==    39 `location_index`    40 || accessor (name version)    41 || attribute usage patterns    42 || deducing types for names    43 ==    44 `attr_class_types`<<BR>>`attr_instance_types`<<BR>>`attr_module_types`    45 || attribute name and assignment state    46 || class, instance, module types    47 || determining types supporting name accesses and assignments    48 ==    49 `assigned_attrs`    50 || attribute usage pattern    51 || attribute assignment locations    52 || determining possibly mutated attributes on types    53 ==    54 `alias_index`    55 || alias (name version)    56 || accesses    57 || determining the identities of aliases (name versions) from initialising    58 .. name or attribute accesses    59 ==    60 `alias_index_rev`    61 || access    62 || aliases (name versions)    63 || propagating updated information from accesses to aliases    64 }}}    65     66 Various collections are also maintained:    67     68 {{{#!table    69 '''Collections''' || '''Details''' || '''Purpose'''    70 ==    71 `reference_assignments`    72 || accesses involving assignments    73 || constraining accessor types; adjusting access plans    74 ==    75 `reference_invocations`    76 || accesses involving invocations    77 || converting access types to instantiation or invocation results    78 }}}    79     80 The objective of deduction is to combine these indexes to establish new    81 relationships between the different participants of these basic index    82 relationships.    83     84 === Building Indexes ===    85     86 The building of indexes from inspection data is approximately as follows:    87     88 {{{#!graphviz    89 //format=svg    90 //transform=notugly    91 digraph indexes {    92   node [shape=box,fontsize="12.0",fontname="sans-serif",tooltip="Indexes"];    93   edge [tooltip="Indexes"];    94   rankdir=LR;    95     96   all_attr_accesses [label="all_attr_accesses\n(anonymous accesses)"];    97   attr_usage [label="attr_usage\n(attribute usage)"];    98   location_index [label="location_index\n(usage by accessor)"];    99    100   all_attrs [label="all_class_attrs | all_instance_attrs | all_module attrs | (all attributes)",shape=record];   101   attr_types [label="attr_class_types | attr_instance_types | attr_module_types | (types by attribute name)",shape=record];   102    103   attr_accessors [label="attr_accessors\n(accessors by access)"];   104   access_index [label="access_index\n(accessor locations by access location)"];   105    106   all_attr_access_modifiers [label="all_attr_access_modifiers\n(operations/modifiers by access)"];   107   reference_assignments [label="reference_assignments\n(assignment accesses)"];   108   reference_invocations [label="reference_invocations\n(invocation accesses)"];   109   assigned_attrs [label="assigned_attrs\n(assignment accesses by access)"];   110    111   all_aliased_names [label="all_aliased_names\n(accesses by alias)"];   112   alias_index [label="alias_index\n(access locations by accessor/alias location)"];   113    114   init_usage_index [label="init_usage_index",shape=ellipse];   115   init_attr_type_indexes [label="init_attr_type_indexes",shape=ellipse];   116   init_accessors [label="init_accessors",shape=ellipse];   117   init_accesses [label="init_accesses",shape=ellipse];   118   init_aliases [label="init_aliases",shape=ellipse];   119    120   all_attr_accesses -> init_usage_index;   121   attr_usage -> init_usage_index;   122   init_usage_index -> location_index;   123    124   all_attrs -> init_attr_type_indexes -> attr_types;   125    126   attr_accessors -> init_accessors -> access_index;   127    128   all_attr_access_modifiers -> init_accesses;   129   init_accesses -> reference_assignments;   130   init_accesses -> reference_invocations;   131   init_accesses -> assigned_attrs;   132    133   all_aliased_names -> init_aliases -> alias_index;   134 }   135 }}}   136    137 === Deriving Types from Indexes and Accesses ===   138    139 The indexes are employed in deduction approximately as follows:   140    141 {{{#!graphviz   142 //format=svg   143 //transform=notugly   144 digraph deduction {   145   node [shape=box,fontsize="12.0",fontname="sans-serif",tooltip="Deduction"];   146   edge [tooltip="Deduction"];   147   rankdir=LR;   148    149   all_attr_accesses [label="all_attr_accesses\n(anonymous accesses)"];   150   location_index [label="location_index\n(usage by accessor)"];   151    152   attr_types [label="attr_class_types | attr_instance_types | attr_module_types | (types by attribute name)",shape=record];   153    154   all_initialised_names [label="all_initialised_names\n(types by accessor)"];   155    156   access_index [label="access_index\n(accessor locations by access location)"];   157    158   alias_index [label="alias_index\n(access locations by accessor/alias location)"];   159    160   record_types_for_usage [label="record_types_for_usage",shape=ellipse];   161   record_types_for_attribute [label="record_types_for_attribute",shape=ellipse];   162    163   accessor_types [label="accessor_class_types | accessor_instance_types | accessor_module_types | (types by accessor)",shape=record];   164   provider_types [label="provider_class_types | provider_instance_types | provider_module_types | (provider types by accessor)",shape=record];   165    166   location_index -> record_types_for_usage;   167   attr_types -> record_types_for_usage;   168   all_initialised_names -> record_types_for_usage;   169   access_index -> record_types_for_usage;   170   alias_index -> record_types_for_usage;    171    172   record_types_for_usage -> provider_types;   173   record_types_for_usage -> accessor_types;   174    175   attr_types -> record_types_for_attribute;   176   all_attr_accesses -> record_types_for_attribute;   177    178   record_types_for_attribute -> provider_types;   179   record_types_for_attribute -> accessor_types;   180 }   181 }}}   182    183 === Converting Usage to Types ===   184    185 A particularly important operation in the deduction process is that of   186 converting attribute usage information to a set of types supporting such   187 usage. Taking the mapping of attribute names to types, each attribute name   188 provided by a usage observation can be applied, progressively narrowing the   189 set of types available to support the complete attribute usage collection.   190    191 {{{#!graphviz   192 //format=svg   193 //transform=notugly   194 digraph usage_to_types {   195   node [shape=box,fontsize="12.0",fontname="sans-serif",tooltip="Usage to types"];   196   edge [tooltip="Usage to types"];   197   rankdir=LR;   198    199   usage [label="(a, b, c)",style=filled,fillcolor=darkorange];   200    201   subgraph {   202     rank=same;   203     attr_a [label="attribute a",style=filled,fillcolor=gold];   204     attr_b [label="attribute b",style=filled,fillcolor=gold];   205     attr_c [label="attribute c",style=filled,fillcolor=gold];   206   }   207    208   index [label="types by attribute name",shape=ellipse];   209    210   subgraph {   211     rank=same;   212     type_P [label="type P"];   213     type_Q [label="type Q",style=filled,fillcolor=gold];   214     type_R [label="type R"];   215     type_S [label="type S"];   216   }   217    218   deduction [label="(a, b, c) needs type Q",style=filled,fillcolor=darkorange];   219    220   usage -> attr_a;   221   usage -> attr_b;   222   usage -> attr_c;   223    224   attr_a -> attr_b -> attr_c [style=dashed,dir=none];   225   attr_a -> index -> type_P [style=dashed,dir=none];   226   type_P -> type_Q -> type_R -> type_S [style=dashed,dir=none];   227    228   attr_a -> type_P;   229   attr_a -> type_Q;   230   attr_b -> type_Q;   231   attr_b -> type_R;   232   attr_c -> type_Q;   233   attr_c -> type_S;   234    235   type_Q -> deduction;   236 }   237 }}}   238    239 The types supporting attribute usage are the attribute '''providers'''. Where   240 providers are classes, the affected accessors in the program may also be   241 instances, since instances also support access to attributes of the   242 instantiated class (and its ancestors).   243    244 Indexes mapping attributes to types must combine consideration of class and   245 instance attributes in order to correctly identify instance providers.   246 Consider the following example:   247    248 {{{#!graphviz   249 //format=svg   250 //transform=notugly   251 digraph instance_providers {   252   node [shape=box,fontsize="12.0",fontname="sans-serif",tooltip="Instance providers"];   253   edge [tooltip="Instance providers"];   254   rankdir=LR;   255    256   usage [label="(a, b, c)",style=filled,fillcolor=darkorange];   257    258   subgraph {   259     rank=same;   260     combined [label="combined attributes",shape=ellipse];   261     attr_a [label="attribute a",style=filled,fillcolor=gold];   262     attr_c [label="attribute c",style=filled,fillcolor=gold];   263     attr_b [label="attribute b",style=filled,fillcolor=gold];   264   }   265    266   subgraph {   267     rank=same;   268     class_C [label="class C"];   269     attr_Ca [label="attribute C.a",style=filled,fillcolor=gold];   270     attr_Cc [label="attribute C.c",style=filled,fillcolor=gold];   271     instance_C [label="instance of C"];   272     attr_Ib [label="attribute (C).b",style=filled,fillcolor=gold];   273   }   274    275   type_C [label="type C",style=filled,fillcolor=darkorange];   276    277   combined -> attr_a -> attr_c -> attr_b [style=dashed,dir=none];   278   class_C -> attr_Ca -> attr_Cc [style=dashed,dir=none];   279   instance_C -> attr_Ib [style=dashed,dir=none];   280    281   usage -> attr_a -> attr_Ca;   282   usage -> attr_b -> attr_Ib;   283   usage -> attr_c -> attr_Cc;   284    285   attr_Ca -> type_C;   286   attr_Cc -> type_C;   287   attr_Ib -> type_C;   288 }   289 }}}   290    291 To recognise support by instance accessors for the usage pattern concerned,   292 attribute details must be obtained from classes as well as instances. Note   293 that the identified type cannot support such usage purely by providing class   294 or instance attributes alone.   295    296 === Attribute Assignments ===   297    298 Since attribute access operations may occur as part of assignments, the nature   299 of accesses is recorded during inspection. Combining the indexed information   300 for assignment accesses allows the deducer to determine the most pessimistic   301 effects on the program structure of such assignments.   302    303 Taking each attribute usage set employed by accessors involved in assignments,   304 the types are deduced for such accessors, and each individual attribute known   305 to be used in such assignments is then applied to the deduced types,   306 '''mutating''' them in such a way that deductions may no longer assume a fixed   307 identity for such attributes when obtained from these types.   308    309 {{{#!graphviz   310 //format=svg   311 //transform=notugly   312 digraph assignments {   313   node [shape=box,fontsize="12.0",fontname="sans-serif",tooltip="Attribute assignments"];   314   edge [tooltip="Attribute assignments"];   315   rankdir=LR;   316    317   subgraph {   318     rank=same;   319     usage [label="(a, b, c)",style=filled,fillcolor=darkorange];   320     assigned [label="b is assigned",style=filled,fillcolor=darkorange];   321   }   322    323   deduction [label="(a, b, c) needs type Q",style=filled,fillcolor=gold];   324    325   subgraph {   326     rank=same;   327     type_Q [label="type Q",style=filled,fillcolor=gold];   328     attr_Qa [label="attribute Q.a"];   329     attr_Qb [label="attribute Q.b\n(mutated)",style=filled,fillcolor=darkorange];   330     attr_Qc [label="attribute Q.c"];   331   }   332    333   type_Q -> attr_Qa -> attr_Qb -> attr_Qc [style=dashed,dir=none];   334   usage -> deduction -> type_Q;   335   assigned -> attr_Qb;   336 }   337 }}}   338    339 === Refining Type Deductions ===   340    341 In the context of a specific access, the types may be resolved further:   342    343  * Any name whose initialisation could be determined during inspection can be   344    associated with its initialised type   345    346  * Any name referring to a constant object can be associated with the type of   347    that object   348    349  * Usage of `self` in methods can result in only compatible class and instance   350    types being retained from the types obtained from usage deductions   351    352 === Reference Identification ===   353    354 The basic information about every accessor and accessed attribute in a program   355 can now be combined to produce specific '''references''' to identities   356 consistent with the inspection observations. Several different kinds of   357 accessors and access situations exist:   358    359  * Name-based accesses involving attribute usage   360    361  * Aliases to names, possibly accompanied by accesses   362    363  * Anonymous accesses involving individual attributes   364    365  * Constant or previously-identified names, possibly accompanied by accesses   366    367 === Aliases ===   368    369 Names initialised using other names or attribute accesses, or using the   370 invocation of either of these things, are known as '''aliases'''. Information   371 about aliases originates during inspection when such names are initialised   372 with expression results within the program. During the resolution activity   373 finalising the inspected details, this initialisation information is used to   374 define relationships between aliases and other names and accesses.   375    376 During deduction, attribute accesses are investigated and type information   377 computed for both attribute accesses and accessors. The relationships defined   378 between accesses and aliases can then be employed to propagate such deduced   379 information to the aliases and to define appropriate type characteristics for   380 them.   381    382 Where aliases are used as the basis of attribute accesses, this propagation   383 refines the previously deduced information about the aliases and may also   384 refine the details of the accesses with which the alias is involved.   385    386 === Invocation Target Suitability ===   387    388 Having identified accessed attributes, invocation information can be applied   389 in cases where such attributes immediately participate in an invocation,   390 comparing the specified argument details against the parameter details defined   391 for the identified attribute, which must be a callable object for this   392 technique to work. Where arguments do not appear to be suitable - either the   393 number of arguments is incorrect or any keyword argument refer to non-existent   394 parameters - the attribute providing the parameter details can be considered   395 unsuitable for the access.   396    397 === Classifying Accessors ===   398    399 Each accessor, being a particular version of a name, will have type   400 information associated with it as a consequence of the deduction process. Such   401 information takes the following forms:   402    403  * Provider types, indicating which types may provide the attributes used by   404    the accessor   405    406  * Accessor types, indicating which types will actually appear as the accessor   407    408 This information can be processed in a number of ways to produce the   409 following:   410    411  * All types (from all kinds of type) of providers able to provide attributes   412    via the accessor   413    414  * All types (from all kinds of type) of accessors compatible with the   415    accessor   416    417  * The most general types of accessors compatible with the accessor   418    419 Where many types may be associated with an accessor, identifying the most   420 general types involves eliminating those which are derived from others. Given   421 that descendant types may not remove support for attributes provided by their   422 ancestors, then where an ancestor type has been identified as a possible   423 accessor, it should follow that all of its descendants may also have been   424 identified as possible accessors. Since these descendants should be   425 compatible, identifying them individually is unnecessary: merely specifying   426 that the common ancestor or ''any'' descendant could provide an accessor is   427 sufficient.   428    429 ==== Defining Guards ====   430    431 A '''guard''' is a constraint supported by a run-time test indicating the   432 compliance of an accessor with a particular type. Thus, where a single   433 accessor type has been identified, a guard may be established for an accessor   434 that tests the type of the accessor against a specific type. Where a single   435 ''general'' accessor type is identified, a guard is established that tests the   436 accessor against a "common" type: that is, an ancestor type with which other   437 descendant types may comply.   438    439 === Classifying Accesses ===   440    441 At the point of classifying accesses, information is available about the   442 following:   443    444  * The accessors potentially involved in each access   445    446  * The types of accessors and the types providing attributes via those   447    accessors   448    449  * Any guards applying to the accessors   450    451  * Whether an access is constrained by certain program characteristics and is   452    thus guaranteed to be as deduced   453    454  * The possible attributes referenced by the access   455    456 This information can be processed in a number of ways to produce the   457 following:   458    459  * The types of accessors, both general and specific, applying to each access   460    461  * The attributes that can be provided by each access, consolidating existing   462    referenced attribute details   463    464  * The general types providing the attributes   465    466 Since more than one accessor may be involved, information from all accessors   467 must be combined to determine whether guard information still applies to the   468 access, or whether it is possible for an accessor to be used that has an   469 uncertain type at run-time.   470    471 ==== Defining Tests ====   472    473 A '''test''' at the access level is a necessary check performed on an accessor   474 before an access to determine whether it belongs to a certain type or group of   475 types.   476    477 Where guards applying to accessors apply by extension to an access, it may not   478 be enough to assume that the the attributes exposed by the accessor are the   479 same as those considered acceptable through deduction. Therefore, attributes   480 are obtained for the access using the applicable guard types as accessors. If   481 this set of attributes does not include potentially accessible attributes   482 (perhaps because the guard types are broadly defined and do not support all   483 attribute usage), a test must be generated.   484    485 Where a single attribute provider can be identified, a test for a specific   486 type is generated. Where a single general type can be identified as a   487 provider, a test against a "common" type is generated. Tests involving the   488 built-in `object` are not generated since it is the root of all classes and   489 such tests would merely identify an accessor as a class. In all cases where a   490 single, specific type cannot be tested for, the general attribute validation   491 mechanism must be used instead.   492    493 == Preparing Access Descriptions ==   494    495 The accumulated deduced knowledge is directed towards producing access   496 descriptions or plans which characterise each access in terms of the   497 following:   498    499  * The initial accessor, being the starting object for attribute accesses,   500    unless a static accessor has been identified   501  * Details of any test required on the initial accessor   502  * Details of any type employed by the test   503  * Any identified static accessor (to be used as the initial accessor)   504  * Attributes needing to be traversed from the accessor that yield   505    unambiguous objects   506  * Access modes for each of the unambiguously-traversed attributes   507  * Remaining attributes needing to be tested and traversed (after having   508    traversed the above attributes)   509  * Details of the context   510  * Any test to apply to the context (to ensure its validity)   511  * The method of obtaining the first attribute   512  * The method of obtaining the final attribute   513  * Any identified static final attribute   514  * The kinds of objects providing the final attribute   515    516 === Characterising the Accessor ===   517    518 For a given access location, the referenced attribute details established   519 during deduction are used to determine...   520    521  * Whether the initial accessor is static, originating from a constant access   522    or involving an identifiable static object   523    524  * Whether the initial accessor is dynamic but has a known, deduced identity   525    526 Some useful information about the accessor and about the actual provider of   527 the first accessed attribute can be defined:   528    529 || || '''Class''' || '''Instance''' || '''Module''' ||   530 || '''Accessor''' || Class accessor || Instance accessor || Module accessor ||   531 || '''Provider''' || Class provider || Instance provider || ||   532    533 Depending on which of these criteria are satisfied, some properties of the   534 access operation can be established:   535    536  * Object-relative accesses occur with class accessors or module accessors or   537    when attributes are provided by instances   538    539  * Class-relative accesses occur with instance accessors when attributes are   540    provided by classes   541    542 Object-relative accesses merely involve obtaining attributes directly from   543 accessors. Class-relative accesses involve obtaining the class of each   544 accessor and then obtaining an attribute from that class.   545    546 === Defining the First Access Method ===   547    548 For dynamic or unidentified accessors, the above access properties define the   549 access method on the first attribute in the chain of attributes provided.   550 However, any redefinition of the accessor to a static accessor may influence   551 the first method. For static accessors, the first method is always   552 object-relative since classes and modules do not offer transparent mechanisms   553 to expose the attributes on their own classes.   554    555 Static and identified, dynamic accessors should already be known to support   556 the specified attributes. Other accessors require an access method to be used   557 that also checks whether the accessor supports a given attribute.   558    559 === Redefining the Accessor ===   560    561 With knowledge about the initial accessor, the attributes involved in the   562 access operation are then considered in the context of the accessor. For each   563 attribute name in the chain described for an access, an attempt is made to   564 obtain the details of the attribute of the given name from the accessor,   565 determining whether these details can be used as an accessor to obtain   566 subsequent attribute details.   567    568 Where more than one attribute identity is obtained, traversal is terminated:   569 all remaining attributes must be traversed at run-time. If an attribute   570 identified during traversal is static, the first access method changes   571 accordingly.   572    573 === Defining the Final Access Method ===   574    575 An access can also involve an assignment to the accessed attribute or the   576 invocation of the accessed attribute. Such operations change the nature of the   577 access method used on the final attribute in a chain of attribute names.   578    579 === Identifying Context Information ===   580    581 Final attribute accesses involving callables need to incorporate context   582 information that can subsequently be used to invoke those callables. Where the   583 nature of an accessed attribute is not known, a simplistic attempt can be made   584 to look up all attributes stored using the attribute name in the program.   585 Otherwise, with knowledge of the attribute, its details can be inspected to   586 determine if context information plays a role in the access.   587    588 ==== Context Testing ====   589    590 Of particular interest are the following situations:   591    592  * Where class attributes are being accessed via instances, whether the   593    attributes are all methods that are bound to the instances   594    595  * Where class attributes ''may'' be accessed via instances, whether any   596    attributes ''could be'' methods   597    598 Such considerations dictate whether the context information originates from   599 the attribute or from the accessor and whether any run-time test is required   600 to determine this. Thus, for attributes in general:   601    602 {{{#!table   603 '''Accessor''' || '''Provider''' || '''Attributes'''   604 || '''Effect on Context''' || '''Remark'''   605 ==   606 Always instances || Always classes || Always methods   607 || Replacement   608 || Permit method calling using the instance as context   609 ==   610 Always instances || Always classes || Sometimes methods   611 || Test at run-time   612 || Preserve original context for non-methods   613 ==   614 Sometimes instances || Sometimes classes || Sometimes methods   615 || Test at run-time   616 || Preserve original context for non-methods, non-instance accessors   617 }}}   618    619 In all other situations, the available context is ignored, with the attribute   620 itself providing any stored context information.   621    622 ==== Context Identity ====   623    624 Where the context is ignored, no effort will be made to obtain or retain it in   625 the program for the access operation: it will be unset. Otherwise, the context   626 will be defined as one of the following:   627    628  * The "base" or static accessor where this is also the accessor for the final   629    access   630    631  * The original (or initial) accessor where this is also the accessor for the   632    final access   633    634  * The final accessor, having been identified through attribute traversal   635    636 Note that non-static accessors may be computed dynamically and thus need to be   637 stored temporarily for subsequent use.    638    639 == Preparing Instruction Plans ==   640    641 Instruction plans are sequences of program operations, encoded in a   642 higher-level form than actual program instructions, that describe the steps   643 needed to access attributes. Such sequences are produced from the details   644 provided by individual access plans.   645    646 === Original Accessor ===   647    648 The expression providing the object from which the first attribute is obtained   649 (or the only attribute if only one is specified) is known as the original   650 accessor. Where this accessor can be identified, the expression describing it   651 in the program can potentially be replaced with a static reference, and   652 subsequent mentions of the accessor can potentially be replaced with such   653 references or names used as expressions.   654    655 {{{#!table   656 '''Access Plan Information''' || '''Original Accessor'''   657 ==   658 Static accessor identified   659 || Identified accessor   660 ==   661 Named accessor access, not invocation   662 || Indicated name   663 ==   664 Named accessor invocation, accessor known to provide the attribute   665 || Indicated name   666 ==   667 Named accessor invocation, accessor not known to provide the attribute   668 || Accessor expression   669 ==   670 Other accessors   671 || Accessor expression   672 }}}   673    674 By using names or static references, the need to store the result of   675 evaluating an accessor expression is eliminated because such labels can be   676 inserted in the instruction sequence as required.   677    678 === First Access Operation ===   679    680 Although it may be possible to convert accesses into single instructions that   681 obtain attributes directly, many accesses will involve access operations that   682 must consult an accessor object and obtain an attribute from that object, at   683 least for the first attribute in a chain of attributes. This occurs when the   684 access plan indicates the following situations:   685    686  * Final method is an access (meaning that an attribute cannot be directly   687    obtained)   688    689  * Final method is an assignment (requiring the object whose attribute will be   690    updated)   691    692  * Attributes (identified or otherwise) need traversing   693    694 === Accessor Nature ===   695    696 Attribute assignments involve a single '''target accessor''' and potentially   697 many other accessors, depending on how many distinct expressions are evaluated   698 to yield the value to be set in the assignment. Such a target accessor will   699 usually be derived from the evaluation of an expression, and in some cases the   700 expression will be the result of an opaque operation such as the invocation of   701 a function. In such cases, the target accessor is stored in a temporary   702 variable for subsequent use in access operations.   703    704 === Context ===   705    706 === Access Tests ===   707    708 === Traversing Identified Attributes ===   709    710 === Traversing Unidentified Attributes ===   711    712 === Final Access Operation ===   713    714 === Context Testing ===   715    716 === Instruction Details ===   717    718 The emitted instructions are as follows.   719    720 ==== Direct Load ====   721    722 These instructions employ the attribute position for the supplied attribute   723 name.   724    725 {{{#!table   726 '''Instruction''' || '''Arguments''' || '''Operations'''   727 ==   728 `__load_via_class` || object, attribute name   729 || Obtain class from object; load attribute from class at position   730 ==   731 `__load_via_object` || object, attribute name   732 || Load attribute from object at position   733 ==   734 `__get_class_and_load` || object, attribute name   735 || Obtain class from object if instance; load attribute from result at   736 .. position   737 }}}   738    739 ==== Attribute Reference ====   740    741 Attribute references are obtained to be targets for store operations as well   742 as being exposed as result targets.   743    744 {{{#!table   745 '''Instruction''' || '''Arguments''' || '''Operations'''   746 ==   747 `__get_class_attr_ref` || object, attribute name   748 || Obtain class from object; obtain reference for attribute in class   749 ==   750 `__get_object_attr_ref` || object, attribute name   751 || Obtain reference for attribute in object   752 }}}   753    754 ==== Attribute Reference Load and Store ====   755    756 These instructions employ an attribute reference, previously obtained for a   757 given attribute in an object.   758    759 {{{#!table   760 '''Instruction''' || '''Arguments''' || '''Operations'''   761 ==   762 `__load_via_attr_ref` || attribute reference   763 || Load value from attribute reference   764 ==   765 `__store_via_attr_ref` || attribute reference, value   766 || Store value in attribute at reference   767 }}}   768    769 ==== Checked Load ====   770    771 These instructions employ the attribute position and code for the supplied   772 attribute name.   773    774 {{{#!table   775 '''Instruction''' || '''Arguments''' || '''Operations'''   776 ==   777 `__check_and_load_via_class` || object, attribute name   778 || Obtain class from object; test for attribute and load or raise type error   779 ==   780 `__check_and_load_via_object` || object, attribute name   781 || Test for attribute and load or raise type error   782 ==   783 `__check_and_load_via_any` || object, attribute name   784 || Test for attribute and load or obtain class; test for attribute and load or   785 .. raise type error   786 }}}   787    788 ==== Checked Attribute Reference ====   789    790 These instructions employ the attribute position and code for the supplied   791 attribute name, storing an attribute value.   792    793 {{{#!table   794 '''Instruction''' || '''Arguments''' || '''Operations'''   795 ==   796 `__check_and_get_object_attr_ref` || object, attribute name   797 || Test for attribute and obtain reference or raise type error   798 }}}   799    800 ==== Testing ====   801    802 These instructions employ the special attribute position and code for the   803 supplied type name.   804    805 {{{#!table   806 '''Instruction''' || '''Arguments''' || '''Operations'''   807 ==   808 `__test_common_instance` || object, type   809 || Obtain class from object; test conformance to type   810 ==   811 `__test_common_object` || object, type   812 || Test conformance to type or obtain class from object and test conformance   813 .. to type   814 ==   815 `__test_common_type` || object, type   816 || Test conformance to type   817 ==   818 `__test_specific_instance` || object, type   819 || Obtain class from object; test equivalence to type   820 ==   821 `__test_specific_object` || object, type   822 || Test equivalence to type or obtain class from object and test equivalence   823 .. to type   824 ==   825 `__test_specific_type` || object, type   826 || Test equivalence to type   827 }}}   828    829 ==== Static Load ====   830    831 These instructions obtain references to static objects, in some cases   832 employing a supplied context.   833    834 {{{#!table   835 '''Instruction''' || '''Arguments''' || '''Operations'''   836 ==   837 `__load_static_ignore` || object   838 || Load attribute populated with object, leaving the context unset   839 ==   840 `__load_static_replace` || context, object   841 || Load attribute populated with the context and object   842 ==   843 `__load_static_test` || context, object   844 || Load attribute populated with object; test context compatibility and set   845 .. the context   846 }}}   847    848 ==== Temporary Access ====   849    850 These instructions access temporary values retained to perform the attribute   851 access. The temporary storage index is generated during program translation.   852    853 {{{#!table   854 '''Instruction''' || '''Arguments''' || '''Operations'''   855 ==   856 `__get_accessor` || (temporary)   857 || Load the indicated accessor from temporary storage   858 ==   859 `__get_attr_ref` || (temporary)   860 || Load the indicated attribute reference from temporary storage   861 ==   862 `__get_context` || (temporary)   863 || Load the indicated context from temporary storage   864 ==   865 `__set_accessor` || (temporary), accessor   866 || Store the accessor in temporary storage   867 ==   868 `__set_attr_ref` || (temporary), reference   869 || Store the given attribute reference in temporary storage   870 ==   871 `__set_context` || (temporary), context   872 || Store the given context in temporary storage   873 ==   874 `__set_private_context` || context   875 || Store the context in temporary storage   876 ==   877 `__set_target_accessor` || accessor   878 || Store the assignment accessor in temporary storage   879 }}}   880    881 ==== Context Test ====   882    883 These instructions perform tests on the available context object. The   884 temporary storage index is generated during program translation.   885    886 {{{#!table   887 '''Instruction''' || '''Arguments''' || '''Operations'''   888 ==   889 `__test_context_revert` || (temporary), context, attribute   890 || Test compatibility of context; revert temporary to attribute context if   891 .. incompatible   892 ==   893 `__test_context_static` || (temporary), context, value   894 || Test compatibility of context; set temporary to specified context if   895 .. compatible   896 }}}   897    898 == Deduction Products ==   899    900 The deduction process should produce a complete catalogue of accessor and   901 access references that may then be consulted by the [[../Translation|   902 translation]] process needing to know the nature of any operation within the   903 program. Central to the translation process's understanding of references is   904 the '''attribute access plan''' for each reference which characterises each   905 access and provides the basis for the formulation of the '''instruction   906 plan''' used to replicate it in the final program.