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.