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