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