1 #!/usr/bin/env python 2 3 """ 4 Program data structures. There are two separate kinds of structures: those with 5 context, which are the values manipulated by programs, and those without 6 context, which are typically constant things which are stored alongside the 7 program but which are wrapped in context-dependent structures in the running 8 program. 9 10 Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 Paul Boddie <paul@boddie.org.uk> 11 12 This program is free software; you can redistribute it and/or modify it under 13 the terms of the GNU General Public License as published by the Free Software 14 Foundation; either version 3 of the License, or (at your option) any later 15 version. 16 17 This program is distributed in the hope that it will be useful, but WITHOUT 18 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 19 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 20 details. 21 22 You should have received a copy of the GNU General Public License along with 23 this program. If not, see <http://www.gnu.org/licenses/>. 24 25 -------- 26 27 The principal value structure class in this module is the Attr class which 28 represents attributes of objects and retains the context of each reference to an 29 attribute. This class models program behaviour at run-time. 30 31 The central data structure classes in this module are the following: 32 33 * Class 34 * Function 35 * Module 36 37 All of the above support the Naming interface either explicitly or through 38 general conformance, meaning that all can be asked to provide their 'full_name' 39 using the method of that name. 40 41 Additionally, all of the above also support a dictionary interface in order to 42 access names within their defined scopes. Specific methods also exist in order 43 to distinguish between certain kinds of attributes: 44 45 * Class: class_attributes, all_class_attributes, instance_attributes, all_attributes 46 * Function: parameters, locals, all_locals 47 * Module: module_attributes 48 49 These specific methods are useful in certain situations. 50 51 The above classes also provide an 'astnode' attribute, indicating the AST node 52 where each such object is defined. 53 """ 54 55 from micropython.program import ReplaceableContext, PlaceholderContext 56 from micropython.common import * 57 58 def shortrepr(obj): 59 if obj is None: 60 return repr(None) 61 else: 62 return obj.__shortrepr__() 63 64 lambda_index = 0 65 66 def new_lambda(): 67 68 "Return a new sequence number for a lambda definition." 69 70 global lambda_index 71 lambda_index += 1 72 return lambda_index 73 74 # Mix-ins and abstract classes. 75 76 class Naming: 77 78 "A mix-in providing naming conveniences." 79 80 def full_name(self): 81 if self.name is not None: 82 return self.parent.full_name() + "." + self.name 83 else: 84 return self.parent.full_name() 85 86 class NamespaceDict: 87 88 "A mix-in providing dictionary methods." 89 90 def __init__(self, module=None): 91 self.module = module 92 self.namespace = {} 93 self.globals = set() 94 self.lambdas = {} # only really useful for functions 95 self.finalised = 0 96 97 # Attributes accessed on objects, potentially narrowing their types. 98 # Specific namespaces should define known names during initialisation. 99 # For example, functions can define names belonging to parameters. 100 101 # Attribute users, defining names which use attributes. 102 103 self.attribute_users = [{}] # stack of assignments and branches 104 self.attribute_user_shelves = [] 105 106 # Suspended user details plus loop details. 107 108 self.suspended_broken_users = [] # stack of lists of user dicts 109 self.suspended_continuing_users = [] # stack of lists of user dicts 110 111 # Scope usage, indicating the origin of names. 112 113 self.scope_usage = [{}] # stack of scope usage 114 self.scope_shelves = [] 115 116 # Define attribute usage to identify active program sections. 117 # Attribute users are AST nodes defining names. 118 119 self.all_attribute_users = set() 120 121 # Attribute/name definition and access. 122 123 def __delitem__(self, name): 124 del self.namespace[name] 125 126 def has_key(self, name): 127 return self.namespace.has_key(name) 128 129 def keys(self): 130 return self.namespace.keys() 131 132 def values(self): 133 return self.namespace.values() 134 135 def items(self): 136 return self.namespace.items() 137 138 def __getitem__(self, name): 139 return self.namespace[name] 140 141 def get(self, name, default=None): 142 return self.namespace.get(name, default) 143 144 # Administrative methods. 145 146 def finalise(self, objtable): 147 self.finalise_attributes() 148 self.finalise_users(objtable) 149 150 def items_for_vacuum(self): 151 return self.items() + self.lambdas.items() 152 153 def vacuum_item(self, name): 154 if self.has_key(name): 155 del self[name] 156 return 1 157 else: 158 return 0 159 160 def add_lambda(self, obj): 161 attr = Attr(None, self, obj.name) 162 attr.update([self.get_context_and_value(obj)], single_assignment=1) 163 self.lambdas[obj.name] = attr 164 165 # Specialised access methods. 166 167 def get_using_node(self, name, node): 168 169 """ 170 Access the given 'name' through this namespace, making use of the module 171 and builtins namespaces if necessary, annotating the given 'node' with 172 the scope involved. 173 """ 174 175 attr, scope, full_name = self._get_with_scope(name) 176 177 if scope is not None: 178 node._scope = scope 179 self.note_scope(name, scope) 180 181 if full_name is not None and (scope != "local" or self is self.module): 182 self.use_specific_attribute(full_name, name) 183 184 return attr 185 186 def _get_with_scope(self, name, external=0): 187 188 """ 189 Find the source of the given 'name', returning the attribute object, 190 scope (constant, local, global or builtins), and the full name of the 191 source namespace (or None for constants). 192 193 If the optional 'external' flag is set to a true value, only external 194 (non-local) namespaces will be involved in the search. 195 """ 196 197 module = self.module 198 builtins = module and module.builtins or None 199 importer = module and module.importer or None 200 201 # Constants. 202 203 if importer is not None and importer.predefined_constants.has_key(name): 204 return importer.get_predefined_constant(name), "constant", None 205 206 # Locals. 207 208 elif not external and self.has_key(name): 209 return self[name], "local", self.full_name() 210 211 # Globals. 212 213 elif module is not None and module is not self and module.has_key(name): 214 return module[name], "global", module.full_name() 215 216 # Builtins. 217 218 elif builtins is not None and builtins.has_key(name): 219 return builtins[name], "builtins", builtins.full_name() 220 221 # Unknown. 222 223 else: 224 return None, None, None 225 226 # Attribute definition methods. 227 228 def __setitem__(self, name, value): 229 self.set(name, value) 230 231 def set(self, name, value, single_assignment=1): 232 233 """ 234 A more powerful set operation, making 'name' refer to 'value' whilst 235 indicating whether a 'single_assignment' (true by default) occurs in 236 this operation (or whether the operation covers potentially many 237 assignments in the lifetime of a program). 238 """ 239 240 if value is None: 241 print "Warning: name %r in namespace %r has an unknown value (evaluated to None)." % (name, self.full_name()) 242 value = make_instance() 243 244 if name in self.globals: 245 self.module.set(name, value, 0) 246 else: 247 self._set(name, value, single_assignment) 248 self.define_scope(name, "local") 249 250 def set_module(self, name, value): 251 252 """ 253 A specialised set operation, making 'name' refer to 'value' in the 254 context of making a module reference available in association with 255 'name' as part of the import of that module or a submodule of that 256 module. 257 """ 258 259 self._set(name, value, 1) 260 261 def _set(self, name, attr_or_value, single_assignment=1): 262 263 """ 264 The underlying set operation associating 'name' with the given 265 'attr_or_value'. 266 See: docs/assignment.txt 267 """ 268 269 # Add and/or obtain the namespace entry. 270 271 if not self.namespace.has_key(name): 272 self.namespace[name] = Attr(None, self, name) 273 274 attr = self.namespace[name] 275 self._set_using_attr(attr, attr_or_value, single_assignment) 276 277 def _set_using_attr(self, attr, attr_or_value, single_assignment=1): 278 279 # Handle attribute assignment as well as assignment of basic objects. 280 # Attempt to fix the context if not explicitly defined. 281 282 if isinstance(attr_or_value, Attr): 283 context_values = self.get_updated_context_values(attr_or_value.context_values) 284 else: 285 context_values = self.get_updated_context_values([self.get_context_and_value(attr_or_value)]) 286 287 attr.update(context_values, single_assignment) 288 289 def get_context_and_value(self, value): 290 291 "Return a context, value tuple for the given 'value'." 292 293 # Functions have a replaceable context. 294 295 if isinstance(value, Function): 296 return (ReplaceableContext, value) 297 298 # Classes use placeholder contexts which cannot be replaced but which 299 # do not communicate useful contextual information. 300 301 elif isinstance(value, Class): 302 return (PlaceholderContext, value) 303 304 # Other values employ themselves as the context. 305 306 else: 307 return (value, value) 308 309 def get_updated_context_values(self, context_values): 310 311 """ 312 Adapt the contexts found in the given 'context_values', returning a new 313 set. 314 See: docs/assignment.txt 315 """ 316 317 results = set() 318 319 for context, value in context_values: 320 321 # Set the context of instances to themselves. 322 323 if isinstance(value, Instance): 324 results.add((value, value)) 325 else: 326 results.add((context, value)) 327 328 return results 329 330 def make_global(self, name): 331 332 "Declare 'name' as a global in the current namespace." 333 334 if not self.namespace.has_key(name): 335 self.globals.add(name) 336 self.define_scope(name, "global") 337 return 1 338 else: 339 return 0 340 341 # Attribute positioning. 342 343 def attributes_as_list(self): 344 345 "Return the attributes in a list." 346 347 self.finalise_attributes() 348 l = [None] * len(self.keys()) 349 for attr in self.values(): 350 l[attr.position] = attr 351 return l 352 353 def finalise_attributes(self): 354 355 "Make sure all attributes are fully defined." 356 357 if self.finalised: 358 return 359 360 # The default action is to assign attribute positions sequentially. 361 362 for i, attr in enumerate(self.values()): 363 attr.position = i 364 365 self.finalised = 1 366 367 def unfinalise_attributes(self): 368 369 "Open attribute definitions to editing and subsequent finalisation." 370 371 self.finalised = 0 372 373 # Attribute usage methods. 374 375 def finalise_attribute_usage(self): 376 377 "Propagate attribute usage for the namespace to the importer." 378 379 module = self.module 380 importer = module and module.importer 381 382 if importer is not None: 383 384 # Visit each user and examine the attribute usage for each name. 385 386 for user in self.all_attribute_users: 387 388 # First, visit the contributors and combine their attribute 389 # usage with the usage recorded directly on the user. 390 391 contributors, combined_usage = self.get_usage_from_contributors(user) 392 393 # Record the defining user on each contributor. 394 395 for contributor in contributors: 396 contributor._attrdefs.append(user) 397 398 # Then, tell the importer about the usage. 399 400 for name in user._attrnames.keys(): 401 402 # Only provide information about names defined by this user. 403 404 usage = combined_usage.get(name, []) 405 406 # Skip reporting where no actual usage occurs. 407 408 if usage is None: 409 continue 410 411 # Eliminate non-usage. 412 413 importer.use_names(user, name, tuple([attrnames for attrnames in usage if attrnames]), self.full_name()) 414 415 def finalise_users(self, objtable): 416 417 "Record the object types for generating guards." 418 419 # Visit each user and examine the attribute usage for each name. 420 421 for user in self.all_attribute_users: 422 user._attrtypes = self._deduce_types(user._attrcombined, objtable) 423 self._finalise_contributor(user, objtable) 424 425 def _finalise_contributors(self, node, objtable): 426 427 """ 428 Visit the contributing branches of 'node', finalising them using the 429 given 'objtable'. 430 """ 431 432 for contributor in node._attrbranches: 433 self._finalise_contributor(contributor, objtable) 434 435 def _finalise_contributor(self, node, objtable): 436 437 """ 438 Record the specific object types being used in various regions of a 439 program unit. 440 """ 441 442 if not hasattr(node, "_attrspecifictypes"): 443 merged = {} 444 for user in node._attrdefs: 445 merged.update(user._attrnames) 446 node._attrmerged = combine_mapping_dicts(deepen_mapping_dict(node._attrnames), deepen_mapping_dict(merged)) 447 node._attrspecifictypes = self._deduce_types(node._attrmerged, objtable) 448 449 self._finalise_contributors(node, objtable) 450 451 def _deduce_types(self, usage, objtable): 452 453 """ 454 Deduce the types for names from the given attribute 'usage' and using 455 the given 'objtable'. 456 """ 457 458 attrtypes = {} 459 for name, combined_usage in usage.items(): 460 if combined_usage is not None: 461 attrtypes[name] = get_object_types_for_usage(combined_usage, objtable, name, self.full_name()) 462 return attrtypes 463 464 def get_usage_from_contributors(self, node): 465 466 """ 467 Obtain usage information from the given 'node', combined with usage 468 details from its contributors, returning a tuple containing a set of all 469 contributors employed along with a dictionary mapping names to lists of 470 usage possibilities (each a collection of attribute names). 471 """ 472 473 if not hasattr(node, "_attrcombined"): 474 475 node._attrcontributors = set() 476 node._attrcombined = {} 477 478 contributor_usage = {} 479 all_contributors = set() 480 481 # Visit each contributor, gathering usage for each name. 482 483 for contributor in node._attrbranches: 484 485 # Get contributed usage for each contributor. 486 # This gathers usage for each name such as {(a, b), (c, d)} and 487 # {(a, b), (e, f)} into a single set {(a, b), (c, d), (e, f)}. 488 489 contributors, contributed_usage = self.get_usage_from_contributors(contributor) 490 update_mapping_dict(contributor_usage, [contributed_usage]) 491 492 # Record all contributors. 493 494 all_contributors.add(contributor) 495 all_contributors.update(contributors) 496 497 # Then get the resulting usage. 498 # First, make the current usage compatible with the contributed 499 # usage: this makes the attribute usage for each name merely one 500 # member in a list of many possibilities. 501 # Then, combine the current usage with the contributed usage. 502 # Thus, usage of {(f, g)} combined with {(a, b), (c, d)} would give 503 # {(f, g, a, b), (f, g, c, d)}. 504 505 usage = combine_mapping_dicts(deepen_mapping_dict(node._attrnames), contributor_usage) 506 507 node._attrcontributors = all_contributors 508 node._attrcombined = usage 509 510 return node._attrcontributors, node._attrcombined 511 512 def use_attribute(self, name, attrname, value=None): 513 514 """ 515 Note usage on the attribute user 'name' of the attribute 'attrname', 516 noting an assignment if 'value' is specified. 517 """ 518 519 return self._use_attribute(name, attrname, value) 520 521 def use_specific_attribute(self, objname, attrname): 522 523 "Declare the usage on 'objname' of the given 'attrname'." 524 525 self._use_specific_attribute(objname, attrname) 526 527 # These shadow various methods in the InspectedModule class, and provide 528 # implementations generally. 529 530 def _use_specific_attribute(self, objname, attrname, from_name=None): 531 532 """ 533 Note attribute usage specifically on 'objname' - an object which is 534 known at inspection time - or in the current unit if 'objname' is None, 535 nominating a specific attribute 'attrname'. 536 537 This bypasses attribute user mechanisms. 538 """ 539 540 from_name = from_name or self.full_name() 541 objname = objname or from_name 542 module = self.module 543 importer = module and module.importer 544 545 if importer is not None: 546 importer.use_specific_name(objname, attrname, from_name) 547 548 def _use_attribute(self, name, attrname, value=None): 549 550 """ 551 Indicate the use of the given 'name' in this namespace of an attribute 552 with the given 'attrname'. If the optional 'value' is specified, an 553 assignment using the given 'value' is recorded. 554 """ 555 556 users = self.attribute_users[-1] 557 558 # Add the usage to all current users. 559 560 if users.has_key(name): 561 for user in users[name]: 562 values = user._attrnames[name] 563 if values is None: 564 values = user._attrnames[name] = ObjectSet() 565 566 # Add an entry for the attribute, optionally with an assigned 567 # value. 568 569 values.add(attrname) 570 if value is not None: 571 values[attrname].add(value) 572 573 return users[name] 574 else: 575 return [] 576 577 def _define_attribute_user(self, node): 578 579 """ 580 Define 'node' as the user of attributes, indicating the point where the 581 user is defined. 582 """ 583 584 name = node.name 585 self._define_attribute_user_for_name(node, name) 586 587 def _define_attribute_user_for_name(self, node, name): 588 589 "Define 'node' as the user of attributes for the given 'name'." 590 591 users = self.attribute_users[-1] 592 593 # This node overrides previous definitions. 594 595 users[name] = set([node]) 596 597 # Record the attribute combinations for the name. 598 599 self._init_attribute_user_for_name(node, name) 600 601 # Remember this user. 602 603 self.all_attribute_users.add(node) 604 605 def _init_attribute_user_for_name(self, node, name): 606 607 "Make sure that 'node' is initialised for 'name'." 608 609 self._init_attribute_user(node) 610 node._attrnames[name] = None 611 612 def _init_attribute_user(self, node): 613 614 # Attribute usage for names. 615 616 if not hasattr(node, "_attrnames"): 617 node._attrnames = {} 618 node._attrmerged = {} 619 620 # Branches contributing usage to this node. 621 622 if not hasattr(node, "_attrbranches"): 623 node._attrbranches = [] 624 625 # Definitions receiving usage from this node. 626 627 if not hasattr(node, "_attrdefs"): 628 node._attrdefs = [] 629 630 # Branch management methods. 631 632 def _new_branchpoint(self, loop_node=None): 633 634 """ 635 Establish a new branchpoint where several control-flow branches diverge 636 and subsequently converge. 637 """ 638 639 self.attribute_user_shelves.append([]) 640 self.scope_shelves.append([]) 641 642 if loop_node is not None: 643 self.suspended_broken_users.append([]) 644 self.suspended_continuing_users.append((loop_node, [])) 645 646 def _new_branch(self, node): 647 648 """ 649 Establish a new control-flow branch, transferring attribute usage to 650 the new branch so that it may be augmented for each name locally. 651 652 Add the given 'node' as an active user to be informed of attribute 653 usage. 654 """ 655 656 attribute_users = self.attribute_users[-1] 657 658 # Define this node as the active attribute user for all currently 659 # defined names. 660 661 new_users = {} 662 663 for name in attribute_users.keys(): 664 new_users[name] = [node] 665 self._init_attribute_user_for_name(node, name) 666 667 self._init_attribute_user(node) 668 self.attribute_users.append(new_users) 669 670 # Add this user as a contributor to the previously active users. 671 672 self._connect_users_to_branch(attribute_users, node) 673 674 # Retain a record of scope usage. 675 676 scope_usage = {} 677 scope_usage.update(self.scope_usage[-1]) 678 self.scope_usage.append(scope_usage) 679 680 def _connect_users_to_branch(self, attribute_users, node): 681 682 """ 683 Given the 'attribute_users' mapping, connect the users referenced in the 684 mapping to the given branch 'node'. 685 """ 686 687 all_users = set() 688 689 for users in attribute_users.values(): 690 all_users.update(users) 691 692 for user in all_users: 693 self._init_attribute_user(user) 694 user._attrbranches.append(node) 695 696 def _abandon_branch(self): 697 698 """ 699 Abandon scope usage, permitting locally different scopes for names, 700 provided these cannot "escape" from the branch. 701 """ 702 703 self.attribute_users[-1] = abandoned_branch_users 704 self.scope_usage[-1] = abandoned_branch_scope 705 706 def _suspend_broken_branch(self): 707 708 """ 709 Suspend a branch for resumption after the current loop. 710 """ 711 712 attribute_users = self.attribute_users[-1] 713 714 if not isinstance(attribute_users, AbandonedBranchUsers): 715 users = self.suspended_broken_users[-1] 716 users.append(attribute_users) 717 self._abandon_branch() 718 719 def _suspend_continuing_branch(self): 720 721 """ 722 Suspend a branch for resumption after the current iteration. 723 """ 724 725 attribute_users = self.attribute_users[-1] 726 727 if not isinstance(attribute_users, AbandonedBranchUsers): 728 loop_node, users = self.suspended_continuing_users[-1] 729 users.append(attribute_users) 730 self._abandon_branch() 731 732 def _shelve_branch(self): 733 734 """ 735 Shelve the current control-flow branch, recording the attribute usage 736 for subsequent merging. If this branch should be abandoned, the usage 737 observations are still recorded but will not contribute to subsequent 738 observations after a merge. 739 """ 740 741 users = self.attribute_users.pop() 742 self.attribute_user_shelves[-1].append(users) 743 744 scope_usage = self.scope_usage.pop() 745 self.scope_shelves[-1].append(scope_usage) 746 747 def _merge_branches(self): 748 749 """ 750 Merge control-flow branches. This should find the users active within 751 each branch, which have been "shelved", and update the active users 752 dictionary with these contributions. 753 """ 754 755 # Combine the attribute users. This ensures that a list of users 756 # affected by attribute usage is maintained for the current branch. 757 758 all_shelved_users = self.attribute_user_shelves.pop() 759 new_users = merge_mapping_dicts(all_shelved_users) 760 self.attribute_users[-1] = new_users 761 762 # Combine the scope usage. 763 764 scope_usage = self.scope_usage[-1] 765 new_scope_usage = {} 766 767 all_scope_usage = self.scope_shelves.pop() 768 all_scope_names = set() 769 770 # Find all the names for whom scope information has been defined. 771 772 for shelved_usage in all_scope_usage: 773 all_scope_names.update(shelved_usage.keys()) 774 775 for shelved_usage in all_scope_usage: 776 for name in all_scope_names: 777 778 # Find the recorded scope for the name. 779 780 if shelved_usage.has_key(name): 781 scope = shelved_usage[name] 782 elif scope_usage.has_key(name): 783 scope = scope_usage[name] 784 785 # For abandoned branches, no scope is asserted for a name. 786 787 elif isinstance(shelved_usage, AbandonedBranchScope): 788 scope = None 789 790 # If no scope is recorded, find a suitable external source. 791 792 else: 793 attr, scope, full_name = self._get_with_scope(name, external=1) 794 795 # Attempt to record the scope, testing for conflicts. 796 797 if scope: 798 if not new_scope_usage.has_key(name): 799 new_scope_usage[name] = scope 800 elif new_scope_usage[name] != scope: 801 new_scope_usage[name] = ScopeConflict(scope, new_scope_usage[name]) 802 803 self.scope_usage[-1] = new_scope_usage 804 805 def _resume_broken_branches(self): 806 807 """ 808 Incorporate users from suspended broken branches into the current set of 809 active users. 810 """ 811 812 suspended_users = self.suspended_broken_users.pop() 813 current_users = self.attribute_users[-1] 814 new_users = merge_mapping_dicts(suspended_users + [current_users]) 815 self.attribute_users[-1] = new_users 816 817 def _resume_continuing_branches(self): 818 819 """ 820 Incorporate users from suspended continuing branches into the current 821 set of active users, merging usage from the latter with the former. 822 """ 823 824 loop_node, suspended_users = self.suspended_continuing_users.pop() 825 current_users = self.attribute_users[-1] 826 827 # Connect the suspended users to the loop node. 828 829 for users in suspended_users: 830 self._connect_users_to_branch(users, loop_node) 831 832 # Merge suspended branches with the current branch. 833 834 new_users = merge_mapping_dicts(suspended_users + [current_users]) 835 self.attribute_users[-1] = new_users 836 837 # Scope usage methods. 838 839 def define_scope(self, name, scope): 840 841 """ 842 Define 'name' as being from the given 'scope' in the current namespace. 843 """ 844 845 self.scope_usage[-1][name] = scope 846 847 def note_scope(self, name, scope): 848 849 """ 850 Note usage of 'name' from the given 'scope' in the current namespace. 851 If a conflict has been recorded previously, raise an exception. 852 """ 853 854 scope_usage = self.scope_usage[-1] 855 856 if scope_usage.has_key(name): 857 found_scope = scope_usage[name] 858 if isinstance(found_scope, ScopeConflict): 859 raise InspectError("Scope conflict for %r: defined as both %s and %s." % ( 860 name, found_scope.old_scope, found_scope.new_scope)) 861 862 scope_usage[name] = scope 863 864 def used_in_scope(self, name, scope): 865 866 """ 867 Return whether 'name' is used from the given 'scope' in the current 868 namespace. 869 """ 870 871 scope_usage = self.scope_usage[-1] 872 return scope_usage.get(name) == scope 873 874 # Special helper classes for usage and scope resolution. 875 876 class EmptyDict: 877 878 "A class providing dictionaries which retain no information." 879 880 def has_key(self, name): 881 return 0 882 883 def __setitem__(self, name, value): 884 pass 885 886 def __getitem__(self, name): 887 raise KeyError, name 888 889 def get(self, name, default=None): 890 return default 891 892 def keys(self): 893 return [] 894 895 values = items = keys 896 897 class AbandonedBranchUsers(EmptyDict): 898 899 """ 900 A class providing a value or state for an abandoned branch distinct from an 901 empty usage dictionary. 902 """ 903 904 pass 905 906 class AbandonedBranchScope(EmptyDict): 907 908 """ 909 A class providing a value or state for an abandoned branch distinct from an 910 empty scope dictionary. 911 """ 912 913 pass 914 915 abandoned_branch_users = AbandonedBranchUsers() 916 abandoned_branch_scope = AbandonedBranchScope() 917 918 class ScopeConflict: 919 920 """ 921 A scope conflict caused when different code branches contribute different 922 sources of names. 923 """ 924 925 def __init__(self, old_scope, new_scope): 926 self.old_scope = old_scope 927 self.new_scope = new_scope 928 929 class NullBranch: 930 931 "A class representing an attribute user for a non-existent branch." 932 933 pass 934 935 # Program data structures. 936 937 class Attr: 938 939 "An attribute entry having a context." 940 941 def __init__(self, position, parent, name): 942 943 """ 944 Initialise the attribute with the given 'position' within the collection 945 of attributes of its 'parent', indicating its 'name'. 946 """ 947 948 self.position = position 949 self.parent = parent 950 self.name = name 951 952 # Possible values. 953 954 self.context_values = set() 955 956 # Number of assignments per name. 957 958 self.assignments = None 959 960 # Value-related methods. 961 962 def get_contexts(self): 963 return [c for (c, v) in self.context_values] 964 965 def get_values(self): 966 return [v for (c, v) in self.context_values] 967 968 def get_context(self): 969 if len(self.context_values) == 1: 970 return self.get_contexts()[0] 971 else: 972 return None 973 974 def get_value(self): 975 if len(self.context_values) == 1: 976 return self.get_values()[0] 977 else: 978 return None 979 980 def update(self, context_values, single_assignment): 981 982 """ 983 Update the attribute, adding the 'context_values' provided to the 984 known details associated with the attribute, changing the number of 985 assignments according to the 'single_assignment' status of the 986 operation, where a true value indicates that only one assignment is 987 associated with the update, and a false value indicates that potentially 988 many assignments may be involved. 989 """ 990 991 if self.context_values.issuperset(context_values) and \ 992 not (make_instance(), make_instance()) in context_values: 993 return 994 995 if self.assignments is None: 996 if single_assignment: 997 self.assignments = len(set(context_values)) 998 else: 999 self.assignments = AtLeast(len(set(context_values))) 1000 else: 1001 if single_assignment: 1002 self.assignments += 1 1003 else: 1004 self.assignments += AtLeast(1) 1005 1006 self.context_values.update(context_values) 1007 1008 def is_constant(self): 1009 1010 """ 1011 Return whether this attribute references something that can be regarded 1012 as being constant within a particular scope. 1013 """ 1014 1015 return self.assignments == 1 1016 1017 def is_strict_constant(self): 1018 1019 """ 1020 Return whether this attribute references something that can be regarded 1021 as being constant. 1022 """ 1023 1024 value = self.get_value() 1025 return not (value is None or (isinstance(value, Instance) and not isinstance(value, Constant))) 1026 1027 def is_static_attribute(self): 1028 1029 """ 1030 Return whether this attribute is defined on a fixed/static object such 1031 as a class or a module. 1032 """ 1033 1034 return isinstance(self.parent, (Class, Module)) 1035 1036 def defines_ambiguous_class(self): 1037 1038 "Return whether this attribute defines more than one class." 1039 1040 if self.assignments > 1: 1041 have_class = 0 1042 for obj in self.get_values(): 1043 if isinstance(obj, Class): 1044 if have_class: 1045 return 1 1046 have_class = 1 1047 1048 return 0 1049 1050 def defined_within_hierarchy(self): 1051 1052 """ 1053 Return whether the parent and context of the attribute belong to the 1054 same class hierarchy. 1055 """ 1056 1057 # Must be defined within a class. 1058 1059 if isinstance(self.parent, Class): 1060 1061 # To be sure, all contexts must be classes and be the same as the 1062 # parent, or be a superclass of the parent, or be a subclass of the 1063 # parent. 1064 1065 for context in self.get_contexts(): 1066 if not ( 1067 isinstance(context, Class) and ( 1068 context is self.parent or 1069 context.has_subclass(self.parent) or 1070 self.parent.has_subclass(context)) 1071 ): 1072 return 0 1073 1074 return 1 1075 1076 # Instance attributes are not defined within a hierarchy. 1077 1078 else: 1079 return 0 1080 1081 def defined_outside_hierarchy(self): 1082 1083 """ 1084 Return whether the parent and context of the attribute never belong to 1085 the same class hierarchy. 1086 """ 1087 1088 # Must be defined within a class. 1089 1090 if isinstance(self.parent, Class): 1091 1092 # To be sure, all contexts must be classes and be the same as the 1093 # parent, or be a superclass of the parent, or be a subclass of the 1094 # parent. 1095 1096 for context in self.get_contexts(): 1097 if not ( 1098 isinstance(context, Class) and not ( 1099 context is self.parent or 1100 context.has_subclass(self.parent) or 1101 self.parent.has_subclass(context)) 1102 ): 1103 return 0 1104 1105 return 1 1106 1107 # Instance attributes are not defined within a hierarchy. 1108 1109 else: 1110 return 0 1111 1112 def __repr__(self): 1113 if self.position is not None: 1114 position = "at %r, " % self.position 1115 else: 1116 position = "" 1117 return "<attribute %s.%s (%sassigned %r)>" % ( 1118 shortrepr(self.parent), self.name, 1119 position, self.assignments 1120 ) 1121 1122 def __shortrepr__(self): 1123 return "%s.%s (at %r)" % (shortrepr(self.parent), self.name, self.position) 1124 1125 def _context_values_str(self): 1126 l = [] 1127 for (c, v) in self.context_values: 1128 l.append("(c=%s, v=%s)" % (shortrepr(c), shortrepr(v))) 1129 return ", ".join(l) 1130 1131 # Instances are special in that they need to be wrapped together with context in 1132 # a running program, but they are not generally constant. 1133 1134 class Instance: 1135 1136 "A placeholder indicating the involvement of an instance." 1137 1138 def __init__(self): 1139 self.parent = None 1140 1141 # Image generation details. 1142 1143 self.location = None 1144 1145 def __repr__(self): 1146 return "<instance>" 1147 1148 def __eq__(self, other): 1149 return other.__class__ is Instance 1150 1151 def __ne__(self, other): 1152 return not self.__eq__(other) 1153 1154 def __hash__(self): 1155 return 0 1156 1157 __shortrepr__ = __repr__ 1158 1159 common_instance = Instance() 1160 1161 def make_instance(): 1162 return common_instance 1163 1164 class Constant: 1165 1166 "A superclass for all constant or context-free structures." 1167 1168 pass 1169 1170 # Data objects appearing in programs before run-time. 1171 1172 class Const(Constant, Instance): 1173 1174 "A constant object with no context." 1175 1176 def __init__(self, value): 1177 Instance.__init__(self) 1178 self.value = value 1179 1180 def get_value(self): 1181 return self.value 1182 1183 def __repr__(self): 1184 if self.location is not None: 1185 return "Const(%r, location=%r)" % (self.value, self.location) 1186 else: 1187 return "Const(%r)" % self.value 1188 1189 __shortrepr__ = __repr__ 1190 1191 # Support constants as dictionary keys in order to build constant tables. 1192 1193 def __eq__(self, other): 1194 return other is not None and isinstance(other, Const) and \ 1195 self.value == other.value and self.value.__class__ is other.value.__class__ 1196 1197 def __ne__(self, other): 1198 return not self.__eq__(other) 1199 1200 def __hash__(self): 1201 return hash(self.value) 1202 1203 # Constants are instances of various built-in types. 1204 1205 def value_type_name(self): 1206 return ".".join(self.value_type_name_parts()) 1207 1208 def value_type_name_parts(self): 1209 return "__builtins__", self.value.__class__.__name__ 1210 1211 class Class(NamespaceDict, Naming, Constant): 1212 1213 "A base class for common/normal classes and the type class." 1214 1215 def __init__(self, name, parent=None, module=None, node=None): 1216 1217 """ 1218 Initialise the class with the given 'name', optional 'parent' object, 1219 'module' and AST 'node'. The optional information must be set at a later 1220 point using the 'set_context' method if omitted. 1221 """ 1222 1223 NamespaceDict.__init__(self, module) 1224 self.name = name 1225 self.parent = parent 1226 self.astnode = node 1227 1228 # Superclasses, descendants and attributes. 1229 1230 self.bases = [] 1231 self.descendants = set() 1232 self.instattr = set() # instance attributes 1233 self.relocated = set() # attributes which do not have the same 1234 # position as those of the same name in 1235 # some superclasses 1236 1237 # Caches. 1238 1239 self.reset_caches() 1240 1241 # Image generation details. 1242 1243 self.location = None 1244 self.code_location = None 1245 self.code_body_location = None # corresponds to the instantiator 1246 1247 self.instantiator = None 1248 self.instance_template_location = None # for creating instances at run-time 1249 1250 # Program-related details. 1251 1252 self.blocks = None 1253 self.temp_usage = 0 1254 self.local_usage = 0 1255 self.all_local_usage = 0 1256 1257 # Add an attribute to this class for use by instances. 1258 1259 self.set("__class__", self) 1260 1261 def set_context(self, parent, module, node): 1262 1263 "Set the 'parent', 'module' and 'node' of a class created in advance." 1264 1265 self.parent = parent 1266 self.module = module 1267 self.astnode = node 1268 1269 def reset_caches(self): 1270 1271 "Reset the caches." 1272 1273 self.all_instattr = None # cache for instance_attributes 1274 self.all_instattr_names = None # from all_instattr 1275 self.all_classattr = None # cache for all_class_attributes 1276 self.all_classattr_names = None # from all_classattr 1277 self.allattr = None # cache for all_attributes 1278 self.allattr_names = None # from allattr 1279 1280 def __repr__(self): 1281 if self.location is not None: 1282 return "<class %s (at %r)>" % (shortrepr(self), self.location) 1283 else: 1284 return "<class %s>" % shortrepr(self) 1285 1286 def __shortrepr__(self): 1287 return "%s.%s" % (shortrepr(self.parent), self.name) 1288 1289 def get_body_block(self): 1290 return self.get_instantiator().blocks[0] 1291 1292 # Namespace-related methods. 1293 1294 def get_updated_context_values(self, context_values): 1295 1296 """ 1297 Adapt the contexts found in the given 'context_values', returning a new 1298 set. 1299 See: docs/assignment.txt 1300 """ 1301 1302 results = set() 1303 1304 for context, value in context_values: 1305 1306 # Change the ownership of functions. 1307 1308 if context is ReplaceableContext and value is not None and isinstance(value, Function): 1309 results.add((self, value)) 1310 else: 1311 results.add((context, value)) 1312 1313 return NamespaceDict.get_updated_context_values(self, results) 1314 1315 # Administrative methods. 1316 1317 def items_for_vacuum(self): 1318 1319 "Consider both class and instance attributes for vacuuming." 1320 1321 items = [] 1322 for name in self.instattr: 1323 items.append((name, None)) 1324 return NamespaceDict.items_for_vacuum(self) + items 1325 1326 def vacuum_item(self, name): 1327 1328 "Vacuum 'name' from the class or instance attribute collections." 1329 1330 # NOTE: Hack to prevent damage to exceptions. 1331 1332 if name == "_pc": 1333 return 0 1334 1335 if not NamespaceDict.vacuum_item(self, name): 1336 self.instattr.remove(name) 1337 return 1 1338 1339 def finalise_attributes(self): 1340 1341 "Make sure that all attributes are fully defined." 1342 1343 if self.finalised: 1344 return 1345 1346 self.finalise_class_attributes() 1347 self.finalise_instance_attributes() 1348 self.finalised = 1 1349 1350 def unfinalise_attributes(self): 1351 1352 "Open attribute definitions to editing and subsequent finalisation." 1353 1354 self.reset_caches() 1355 self.finalised = 0 1356 1357 # Convenience methods for accessing functions and methods. 1358 1359 def get_instantiator(self): 1360 1361 "Return a function which can be used to instantiate the class." 1362 1363 if self.instantiator is None: 1364 self.instantiator = self.get_init_method().as_instantiator() 1365 return self.instantiator 1366 1367 def get_init_method(self): 1368 return self.all_class_attributes()["__init__"].get_value() 1369 1370 # Class-specific methods. 1371 1372 def add_base(self, base): 1373 self.bases.append(base) 1374 base.add_descendant(self) 1375 1376 def add_instance_attribute(self, name): 1377 self.instattr.add(name) 1378 1379 def add_descendant(self, cls): 1380 self.descendants.add(cls) 1381 for base in self.bases: 1382 base.add_descendant(cls) 1383 1384 def has_subclass(self, other): 1385 return other in self.descendants 1386 1387 def all_descendants(self): 1388 d = {} 1389 for cls in self.descendants: 1390 d[cls.full_name()] = cls 1391 return d 1392 1393 "Return the attribute names provided by this class only." 1394 1395 class_attribute_names = NamespaceDict.keys 1396 1397 def class_attributes(self): 1398 1399 "Return class attributes provided by this class only." 1400 1401 return dict(self) 1402 1403 def all_class_attribute_names(self): 1404 1405 "Return the attribute names provided by classes in this hierarchy." 1406 1407 if self.all_classattr_names is None: 1408 self.all_class_attributes() 1409 self.all_classattr_names = self.all_classattr.keys() 1410 return self.all_classattr_names 1411 1412 def all_class_attributes(self): 1413 1414 "Return all class attributes, indicating the class which provides them." 1415 1416 self.finalise_class_attributes() 1417 return self.all_classattr 1418 1419 def finalise_class_attributes(self): 1420 1421 "Make sure that the class attributes are fully defined." 1422 1423 if self.all_classattr is None: 1424 self.all_classattr = {} 1425 clsattr = {} 1426 1427 # Record provisional position information for attributes of this 1428 # class. 1429 1430 for name in self.class_attributes().keys(): 1431 1432 # Special case: __class__ has to be at position 0. 1433 1434 if name == "__class__": 1435 clsattr[name] = set([0]) 1436 else: 1437 clsattr[name] = set() # position not yet defined 1438 1439 reversed_bases = self.bases[:] 1440 reversed_bases.reverse() 1441 1442 # For the bases in reverse order, acquire class attribute details. 1443 1444 for cls in reversed_bases: 1445 for name, attr in cls.all_class_attributes().items(): 1446 self.all_classattr[name] = attr 1447 1448 # Record previous attribute information. 1449 1450 if clsattr.has_key(name): 1451 clsattr[name].add(attr.position) 1452 1453 # Record class attributes provided by this class and its bases, 1454 # along with their positions. 1455 1456 self.all_classattr.update(self.class_attributes()) 1457 1458 if clsattr: 1459 for i, name in enumerate(self._get_position_list(clsattr)): 1460 self.all_classattr[name].position = i 1461 1462 return self.all_classattr 1463 1464 def instance_attribute_names(self): 1465 1466 "Return the instance attribute names provided by the class." 1467 1468 if self.all_instattr_names is None: 1469 self.instance_attributes() 1470 return self.all_instattr_names 1471 1472 def instance_attributes(self): 1473 1474 "Return instance-only attributes for instances of this class." 1475 1476 self.finalise_instance_attributes() 1477 return self.all_instattr 1478 1479 def finalise_instance_attributes(self): 1480 1481 "Make sure that the instance attributes are fully defined." 1482 1483 # Cache the attributes by converting the positioned attributes into a 1484 # dictionary. 1485 1486 if self.all_instattr is None: 1487 self.all_instattr = self._get_attributes() 1488 self.all_instattr_names = self.all_instattr.keys() 1489 1490 return self.all_instattr 1491 1492 def _get_attributes(self): 1493 1494 """ 1495 Return a dictionary mapping names to Attr instances incorporating 1496 information about their positions in the final instance structure. 1497 """ 1498 1499 instattr = {} 1500 1501 # Record provisional position information for attributes of this 1502 # instance. 1503 1504 for name in self.instattr: 1505 instattr[name] = set() # position not yet defined 1506 1507 reversed_bases = self.bases[:] 1508 reversed_bases.reverse() 1509 1510 # For the bases in reverse order, acquire instance attribute 1511 # details. 1512 1513 for cls in reversed_bases: 1514 for name, attr in cls.instance_attributes().items(): 1515 1516 # Record previous attribute information. 1517 1518 if instattr.has_key(name): 1519 instattr[name].add(attr.position) 1520 else: 1521 instattr[name] = set([attr.position]) 1522 1523 # Build the dictionary of attributes using the existing positions known 1524 # for each name. 1525 1526 d = {} 1527 for i, name in enumerate(self._get_position_list(instattr)): 1528 d[name] = Attr(i, make_instance(), name) 1529 return d 1530 1531 def _get_position_list(self, positions): 1532 1533 """ 1534 Return a list of attribute names for the given 'positions' mapping from 1535 names to positions, indicating the positions of the attributes in the 1536 final instance structure. 1537 """ 1538 1539 position_items = positions.items() 1540 namearray = [None] * len(position_items) 1541 1542 # Get the positions in ascending order of list size, with lists 1543 # of the same size ordered according to their smallest position 1544 # value. 1545 1546 position_items.sort(self._cmp_positions) 1547 1548 # Get the names in position order. 1549 1550 held = [] 1551 1552 for name, pos in position_items: 1553 pos = list(pos) 1554 pos.sort() 1555 if pos and pos[0] < len(namearray) and namearray[pos[0]] is None: 1556 namearray[pos[0]] = name 1557 else: 1558 if pos: 1559 self.relocated.add(name) 1560 held.append((name, pos)) 1561 1562 for i, attr in enumerate(namearray): 1563 if attr is None: 1564 name, pos = held.pop() 1565 namearray[i] = name 1566 1567 return namearray 1568 1569 def _cmp_positions(self, a, b): 1570 1571 "Compare name plus position list operands 'a' and 'b'." 1572 1573 name_a, list_a = a 1574 name_b, list_b = b 1575 if len(list_a) < len(list_b): 1576 return -1 1577 elif len(list_a) > len(list_b): 1578 return 1 1579 elif not list_a: 1580 return 0 1581 else: 1582 return cmp(min(list_a), min(list_b)) 1583 1584 def all_attribute_names(self): 1585 1586 """ 1587 Return the names of all attributes provided by instances of this class. 1588 """ 1589 1590 self.allattr_names = self.allattr_names or self.all_attributes().keys() 1591 return self.allattr_names 1592 1593 def all_attributes(self): 1594 1595 """ 1596 Return all attributes for an instance, indicating either the class which 1597 provides them or that the instance itself provides them. 1598 1599 Note that __class__ acts like a class attribute for both instances and 1600 classes, and must be able to convey distinct values. 1601 """ 1602 1603 if self.allattr is None: 1604 self.allattr = {} 1605 self.allattr.update(self.all_class_attributes()) 1606 for name, attr in self.instance_attributes().items(): 1607 if self.allattr.has_key(name) and name != "__class__": 1608 print "Warning: instance attribute %r in %r overrides class attribute." % (name, self) 1609 self.allattr[name] = attr 1610 return self.allattr 1611 1612 class TypeClass(Class): 1613 1614 "A special class for the type class." 1615 1616 pass 1617 1618 class CommonClass(Class): 1619 1620 "An inspected class." 1621 1622 pass 1623 1624 class Function(NamespaceDict, Naming, Constant): 1625 1626 "An inspected function." 1627 1628 def __init__(self, name, parent, argnames, defaults, has_star, has_dstar, 1629 dynamic_def=0, module=None, node=None): 1630 1631 """ 1632 Initialise the function with the given 'name', 'parent', list of 1633 'argnames', list of 'defaults', the 'has_star' flag (indicating the 1634 presence of a * parameter), the 'has_dstar' flag (indicating the 1635 presence of a ** parameter), optional 'dynamic_def' (indicating that the 1636 function must be handled dynamically), optional 'module', and optional 1637 AST 'node'. 1638 """ 1639 1640 NamespaceDict.__init__(self, module) 1641 1642 if name is None: 1643 self.name = "lambda#%d" % new_lambda() 1644 self._is_lambda = 1 1645 else: 1646 self.name = name 1647 self._is_lambda = 0 1648 1649 self.parent = parent 1650 self.argnames = argnames 1651 self.defaults = defaults 1652 self.has_star = has_star 1653 self.has_dstar = has_dstar 1654 self.dynamic_def = dynamic_def 1655 self.astnode = node 1656 1657 # Initialise the positional names. 1658 1659 self.positional_names = self.argnames[:] 1660 if has_dstar: 1661 self.dstar_name = self.positional_names[-1] 1662 del self.positional_names[-1] 1663 if has_star: 1664 self.star_name = self.positional_names[-1] 1665 del self.positional_names[-1] 1666 1667 # Initialise default storage. 1668 # NOTE: This must be initialised separately due to the reliance on node 1669 # NOTE: visiting. 1670 1671 self.default_attrs = [] 1672 1673 # Initialise attribute usage. 1674 1675 if node is not None: 1676 for arg in argnames: 1677 1678 # Define attribute users. 1679 1680 self._define_attribute_user_for_name(node, arg) 1681 1682 # Caches. 1683 1684 self.localnames = None # cache for locals 1685 1686 # Add parameters to the namespace. 1687 1688 self._add_parameters(argnames) 1689 1690 # Image generation details. 1691 1692 self.dynamic = None 1693 self.location = None 1694 self.code_location = None 1695 self.code_body_location = None 1696 1697 # Program-related details. 1698 1699 self.blocks = None 1700 self.body_block = None 1701 1702 self.temp_usage = 0 1703 self.local_usage = 0 1704 self.all_local_usage = 0 1705 1706 def _add_parameters(self, argnames): 1707 1708 "Add 'argnames' to the namespace." 1709 1710 for name in argnames: 1711 self.set(name, make_instance()) 1712 1713 for name, top_level in self._flattened_parameters(argnames): 1714 if not top_level: 1715 self.set(name, make_instance()) 1716 1717 def _flattened_parameters(self, argnames, top_level=1): 1718 l = [] 1719 for name in argnames: 1720 if isinstance(name, tuple): 1721 l += self._flattened_parameters(name, 0) 1722 else: 1723 l.append((name, top_level)) 1724 return l 1725 1726 def __repr__(self): 1727 if self.location is not None: 1728 return "<function %s (at %r, code at %r)>" % ( 1729 shortrepr(self), self.location, self.code_location 1730 ) 1731 else: 1732 return "<function %s>" % shortrepr(self) 1733 1734 def __shortrepr__(self): 1735 return "%s.%s(%s)" % (shortrepr(self.parent), self.name, ", ".join(self.argnames)) 1736 1737 def get_body_block(self): 1738 return self.body_block 1739 1740 def is_lambda(self): 1741 return self._is_lambda 1742 1743 # Defaults-related methods. 1744 1745 def store_default(self, attr_or_value): 1746 1747 """ 1748 Reserve space for defaults, set outside the function, potentially on a 1749 dynamic basis, using the 'attr_or_value'. 1750 """ 1751 1752 attr = Attr(None, self, None) 1753 self._set_using_attr(attr, attr_or_value) 1754 self.default_attrs.append(attr) 1755 1756 def make_dynamic(self): 1757 1758 "Return whether this function must be handled using a dynamic object." 1759 1760 if self.dynamic is None: 1761 for attr in self.default_attrs: 1762 if not attr.is_strict_constant() and self.dynamic_def: 1763 self.dynamic = 1 1764 self._make_dynamic() 1765 break 1766 else: 1767 self.dynamic = 0 1768 1769 return self.dynamic 1770 1771 is_dynamic = make_dynamic 1772 1773 def _make_dynamic(self): 1774 1775 "Where functions have dynamic defaults, add a context argument." 1776 1777 name = "<context>" 1778 self.argnames.insert(0, name) 1779 self.positional_names.insert(0, name) 1780 self.set(name, make_instance()) 1781 1782 # Namespace-related methods. 1783 1784 def make_global(self, name): 1785 1786 "Declare 'name' as a global in the current namespace." 1787 1788 if name not in self.argnames and not self.has_key(name): 1789 self.globals.add(name) 1790 return 1 1791 else: 1792 return 0 1793 1794 def parameters(self): 1795 1796 """ 1797 Return a dictionary mapping parameter names to their position in the 1798 parameter list. 1799 """ 1800 1801 parameters = {} 1802 for i, name in enumerate(self.argnames): 1803 parameters[name] = i 1804 return parameters 1805 1806 def tuple_parameters(self, argnames=None): 1807 1808 """ 1809 Return a list of (position, parameter) entries corresponding to tuple 1810 parameters, where each parameter may either be a string or another such 1811 list of entries. 1812 """ 1813 1814 names = argnames or self.argnames 1815 1816 l = [] 1817 for i, name in enumerate(names): 1818 if isinstance(name, tuple): 1819 l.append((i, self.tuple_parameters(name))) 1820 elif argnames: 1821 l.append((i, name)) 1822 return l 1823 1824 def all_locals(self): 1825 1826 "Return a dictionary mapping names to local and parameter details." 1827 1828 return dict(self) 1829 1830 def locals(self): 1831 1832 "Return a dictionary mapping names to local details." 1833 1834 if self.localnames is None: 1835 self.localnames = {} 1836 self.localnames.update(self.all_locals()) 1837 for name in self.argnames: 1838 del self.localnames[name] 1839 return self.localnames 1840 1841 def is_method(self): 1842 1843 """ 1844 Return whether this function is a method explicitly defined in a class. 1845 """ 1846 1847 return isinstance(self.parent, Class) 1848 1849 def is_relocated(self, name): 1850 1851 """ 1852 Determine whether the given attribute 'name' is relocated for instances 1853 having this function as a method. 1854 """ 1855 1856 for cls in self.parent.descendants: 1857 if name in cls.relocated: 1858 return 1 1859 return 0 1860 1861 # Administrative methods. 1862 1863 def items_for_vacuum(self): 1864 return self.lambdas.items() 1865 1866 def vacuum_item(self, name): 1867 del self.lambdas[name] 1868 return 1 1869 1870 def finalise_attributes(self): 1871 1872 """ 1873 Make sure all attributes (locals) are fully defined. Note that locals 1874 are not attributes in the sense of class, module or instance attributes. 1875 Defaults are also finalised by this method. 1876 """ 1877 1878 if self.finalised: 1879 return 1880 1881 # Defaults. 1882 1883 for i, default in enumerate(self.default_attrs): 1884 default.position = i 1885 1886 # Parameters. 1887 1888 i = self._finalise_parameters() 1889 1890 if i is not None: 1891 nparams = i + 1 1892 else: 1893 nparams = 0 1894 1895 # Locals (and tuple parameter names). 1896 1897 i = None 1898 for i, attr in enumerate(self.locals().values()): 1899 attr.position = i + nparams 1900 1901 if i is not None: 1902 nothers = i + 1 1903 else: 1904 nothers = 0 1905 1906 self.local_usage = nothers 1907 self.all_local_usage = nparams + nothers 1908 self.finalised = 1 1909 1910 def _finalise_parameters(self): 1911 if not self.argnames: 1912 return None 1913 1914 for i, name in enumerate(self.argnames): 1915 self[name].position = i 1916 1917 return i 1918 1919 def as_instantiator(self): 1920 1921 "Make an instantiator function from a method, keeping all arguments." 1922 1923 function = Function(self.parent.name, self.parent.parent, self.argnames, self.defaults, 1924 self.has_star, self.has_dstar, self.dynamic_def, self.module) 1925 function.default_attrs = self.default_attrs 1926 return function 1927 1928 class UnresolvedName(NamespaceDict, Constant): 1929 1930 "A module, class or function which was mentioned but could not be imported." 1931 1932 def __init__(self, name, parent_name, module=None): 1933 NamespaceDict.__init__(self, module) 1934 self.name = name 1935 self.parent_name = parent_name 1936 self.parent = None 1937 1938 self.descendants = set() 1939 1940 def add_descendant(self, cls): 1941 self.descendants.add(cls) 1942 1943 def all_attributes(self): 1944 return {} 1945 1946 def all_attribute_names(self): 1947 return [] 1948 1949 all_class_attributes = class_attributes = instance_attributes = all_attributes 1950 all_class_attribute_names = class_attribute_names = instance_attribute_names = all_attribute_names 1951 1952 def __repr__(self): 1953 return "<unknown %s>" % shortrepr(self) 1954 1955 def __shortrepr__(self): 1956 return "%s.%s" % (self.parent_name, self.name) 1957 1958 def full_name(self): 1959 if self.name is not None: 1960 return self.parent_name + "." + self.name 1961 else: 1962 return self.parent_name 1963 1964 class Module(NamespaceDict, Constant): 1965 1966 "An inspected module's core details." 1967 1968 def __init__(self, name, importer): 1969 NamespaceDict.__init__(self, self) 1970 self.name = name 1971 self.importer = importer 1972 self.parent = None 1973 1974 # Original location details. 1975 1976 self.astnode = None 1977 1978 # Complete lists of classes and functions. 1979 1980 self.all_objects = set() 1981 1982 # Keyword records. 1983 1984 self.keyword_names = set() 1985 1986 # Image generation details. 1987 1988 self.location = None 1989 self.code_location = None 1990 1991 # Program-related details. 1992 1993 self.blocks = None 1994 self.temp_usage = 0 1995 self.local_usage = 0 1996 self.all_local_usage = 0 1997 1998 def full_name(self): 1999 return self.name 2000 2001 def __repr__(self): 2002 if self.location is not None: 2003 return "<module %s (at %r)>" % (self.name, self.location) 2004 else: 2005 return "<module %s>" % shortrepr(self) 2006 2007 def __shortrepr__(self): 2008 return self.name 2009 2010 # Attribute methods. 2011 2012 "Return the module attribute names provided by the module." 2013 2014 module_attribute_names = NamespaceDict.keys 2015 2016 def module_attributes(self): 2017 2018 "Return a dictionary mapping names to module attributes." 2019 2020 return dict(self) 2021 2022 # Pre-made instances. 2023 2024 type_class = TypeClass("type") # details to be filled in later 2025 2026 # Class construction. 2027 2028 def get_class(name, parent, module, node): 2029 2030 """ 2031 Return a Class instance for the class with the given 'name', 'parent', 2032 'module' and 'node'. 2033 """ 2034 2035 if name == "type" and module.full_name() == "__builtins__": 2036 type_class.set_context(parent, module, node) 2037 return type_class 2038 else: 2039 return CommonClass(name, parent, module, node) 2040 2041 # vim: tabstop=4 expandtab shiftwidth=4