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 "__builtins__." + self.value.__class__.__name__ 1112 1113 class Class(NamespaceDict, Naming, Constant): 1114 1115 "A base class for common/normal classes and the type class." 1116 1117 def __init__(self, name, parent=None, module=None, node=None): 1118 1119 """ 1120 Initialise the class with the given 'name', optional 'parent' object, 1121 'module' and AST 'node'. The optional information must be set at a later 1122 point using the 'set_context' method if omitted. 1123 """ 1124 1125 NamespaceDict.__init__(self, module) 1126 self.name = name 1127 self.parent = parent 1128 self.astnode = node 1129 1130 # Superclasses, descendants and attributes. 1131 1132 self.bases = [] 1133 self.descendants = set() 1134 self.instattr = set() # instance attributes 1135 self.relocated = set() # attributes which do not have the same 1136 # position as those of the same name in 1137 # some superclasses 1138 1139 # Caches. 1140 1141 self.reset_caches() 1142 1143 # Image generation details. 1144 1145 self.location = None 1146 self.code_location = None 1147 self.code_body_location = None # corresponds to the instantiator 1148 1149 self.instantiator = None 1150 self.instance_template_location = None # for creating instances at run-time 1151 1152 # Program-related details. 1153 1154 self.blocks = None 1155 self.temp_usage = 0 1156 self.local_usage = 0 1157 self.all_local_usage = 0 1158 1159 # Add __class__ attributes to this class and to instances of it. 1160 1161 if self.parent is not None: 1162 self.initialise_class_attribute() 1163 self.add_instance_attribute("__class__") 1164 1165 def set_context(self, parent, module, node): 1166 self.parent = parent 1167 self.module = module 1168 self.astnode = node 1169 1170 self.initialise_class_attribute() 1171 self.add_instance_attribute("__class__") 1172 1173 def reset_caches(self): 1174 1175 "Reset the caches." 1176 1177 self.all_instattr = None # cache for instance_attributes 1178 self.all_instattr_names = None # from all_instattr 1179 self.all_classattr = None # cache for all_class_attributes 1180 self.all_classattr_names = None # from all_classattr 1181 self.allattr = None # cache for all_attributes 1182 self.allattr_names = None # from allattr 1183 1184 def __repr__(self): 1185 if self.location is not None: 1186 return "Class(%r, %s, location=%r)" % (self.name, shortrepr(self.parent), self.location) 1187 else: 1188 return "Class(%r, %s)" % (self.name, shortrepr(self.parent)) 1189 1190 def __shortrepr__(self): 1191 return "Class(%r, %s)" % (self.name, shortrepr(self.parent)) 1192 1193 def get_body_block(self): 1194 return self.get_instantiator().blocks[0] 1195 1196 # Namespace-related methods. 1197 1198 def get_updated_context_values(self, context_values): 1199 1200 """ 1201 Adapt the contexts found in the given 'context_values', returning a new 1202 set. 1203 See: docs/assignment.txt 1204 """ 1205 1206 results = set() 1207 1208 for context, value in context_values: 1209 1210 # Change the ownership of functions. 1211 1212 if context is ReplaceableContext and value is not None and isinstance(value, Function): 1213 results.add((self, value)) 1214 else: 1215 results.add((context, value)) 1216 1217 return NamespaceDict.get_updated_context_values(self, results) 1218 1219 # Administrative methods. 1220 1221 def items_for_vacuum(self): 1222 items = [] 1223 for name in self.instattr: 1224 items.append((name, None)) 1225 return NamespaceDict.items_for_vacuum(self) + items 1226 1227 def vacuum_item(self, name): 1228 if not NamespaceDict.vacuum_item(self, name): 1229 self.instattr.remove(name) 1230 return 1 1231 1232 def finalise_attributes(self): 1233 1234 "Make sure that all attributes are fully defined." 1235 1236 if self.finalised: 1237 return 1238 1239 self.finalise_class_attributes() 1240 self.finalise_instance_attributes() 1241 self.finalised = 1 1242 1243 def unfinalise_attributes(self): 1244 1245 "Open attribute definitions to editing and subsequent finalisation." 1246 1247 self.reset_caches() 1248 self.finalised = 0 1249 1250 # Convenience methods for accessing functions and methods. 1251 1252 def get_instantiator(self): 1253 1254 "Return a function which can be used to instantiate the class." 1255 1256 if self.instantiator is None: 1257 self.instantiator = self.get_init_method().as_instantiator() 1258 return self.instantiator 1259 1260 def get_init_method(self): 1261 return self.all_class_attributes()["__init__"].get_value() 1262 1263 # Class-specific methods. 1264 1265 def add_base(self, base): 1266 self.bases.append(base) 1267 base.add_descendant(self) 1268 1269 def add_instance_attribute(self, name): 1270 self.instattr.add(name) 1271 1272 def add_descendant(self, cls): 1273 self.descendants.add(cls) 1274 for base in self.bases: 1275 base.add_descendant(cls) 1276 1277 def has_subclass(self, other): 1278 return other in self.descendants 1279 1280 def all_descendants(self): 1281 d = {} 1282 for cls in self.descendants: 1283 d[cls.full_name()] = cls 1284 return d 1285 1286 "Return the attribute names provided by this class only." 1287 1288 class_attribute_names = NamespaceDict.keys 1289 1290 def class_attributes(self): 1291 1292 "Return class attributes provided by this class only." 1293 1294 return dict(self) 1295 1296 def all_class_attribute_names(self): 1297 1298 "Return the attribute names provided by classes in this hierarchy." 1299 1300 if self.all_classattr_names is None: 1301 self.all_class_attributes() 1302 self.all_classattr_names = self.all_classattr.keys() 1303 return self.all_classattr_names 1304 1305 def all_class_attributes(self): 1306 1307 "Return all class attributes, indicating the class which provides them." 1308 1309 self.finalise_class_attributes() 1310 return self.all_classattr 1311 1312 def finalise_class_attributes(self): 1313 1314 "Make sure that the class attributes are fully defined." 1315 1316 if self.all_classattr is None: 1317 self.all_classattr = {} 1318 clsattr = {} 1319 1320 # Record provisional position information for attributes of this 1321 # class. 1322 1323 for name in self.class_attributes().keys(): 1324 1325 # Special case: __class__ has to be at position 0. 1326 1327 if name == "__class__": 1328 clsattr[name] = set([0]) 1329 else: 1330 clsattr[name] = set() # position not yet defined 1331 1332 reversed_bases = self.bases[:] 1333 reversed_bases.reverse() 1334 1335 # For the bases in reverse order, acquire class attribute details. 1336 1337 for cls in reversed_bases: 1338 for name, attr in cls.all_class_attributes().items(): 1339 self.all_classattr[name] = attr 1340 1341 # Record previous attribute information. 1342 1343 if clsattr.has_key(name): 1344 clsattr[name].add(attr.position) 1345 1346 # Record class attributes provided by this class and its bases, 1347 # along with their positions. 1348 1349 self.all_classattr.update(self.class_attributes()) 1350 1351 if clsattr: 1352 for i, name in enumerate(self._get_position_list(clsattr)): 1353 self.all_classattr[name].position = i 1354 1355 return self.all_classattr 1356 1357 def instance_attribute_names(self): 1358 1359 "Return the instance attribute names provided by the class." 1360 1361 if self.all_instattr_names is None: 1362 self.instance_attributes() 1363 return self.all_instattr_names 1364 1365 def instance_attributes(self): 1366 1367 "Return instance-only attributes for instances of this class." 1368 1369 self.finalise_instance_attributes() 1370 return self.all_instattr 1371 1372 def finalise_instance_attributes(self): 1373 1374 "Make sure that the instance attributes are fully defined." 1375 1376 # Cache the attributes by converting the positioned attributes into a 1377 # dictionary. 1378 1379 if self.all_instattr is None: 1380 self.all_instattr = self._get_attributes() 1381 self.all_instattr_names = self.all_instattr.keys() 1382 1383 return self.all_instattr 1384 1385 def _get_attributes(self): 1386 1387 """ 1388 Return a dictionary mapping names to Attr instances incorporating 1389 information about their positions in the final instance structure. 1390 """ 1391 1392 instattr = {} 1393 1394 # Record provisional position information for attributes of this 1395 # instance. 1396 1397 for name in self.instattr: 1398 1399 # Special case: __class__ has to be at position 0. 1400 1401 if name == "__class__": 1402 instattr[name] = set([0]) 1403 else: 1404 instattr[name] = set() # position not yet defined 1405 1406 reversed_bases = self.bases[:] 1407 reversed_bases.reverse() 1408 1409 # For the bases in reverse order, acquire instance attribute 1410 # details. 1411 1412 for cls in reversed_bases: 1413 for name, attr in cls.instance_attributes().items(): 1414 1415 # Record previous attribute information. 1416 1417 if instattr.has_key(name): 1418 instattr[name].add(attr.position) 1419 else: 1420 instattr[name] = set([attr.position]) 1421 1422 # Build the dictionary of attributes using the existing positions known 1423 # for each name. 1424 1425 d = {} 1426 for i, name in enumerate(self._get_position_list(instattr)): 1427 d[name] = Attr(i, Instance(), name) 1428 return d 1429 1430 def _get_position_list(self, positions): 1431 1432 """ 1433 Return a list of attribute names for the given 'positions' mapping from 1434 names to positions, indicating the positions of the attributes in the 1435 final instance structure. 1436 """ 1437 1438 position_items = positions.items() 1439 namearray = [None] * len(position_items) 1440 1441 # Get the positions in ascending order of list size, with lists 1442 # of the same size ordered according to their smallest position 1443 # value. 1444 1445 position_items.sort(self._cmp_positions) 1446 1447 # Get the names in position order. 1448 1449 held = [] 1450 1451 for name, pos in position_items: 1452 pos = list(pos) 1453 pos.sort() 1454 if pos and pos[0] < len(namearray) and namearray[pos[0]] is None: 1455 namearray[pos[0]] = name 1456 else: 1457 if pos: 1458 self.relocated.add(name) 1459 held.append((name, pos)) 1460 1461 for i, attr in enumerate(namearray): 1462 if attr is None: 1463 name, pos = held.pop() 1464 namearray[i] = name 1465 1466 return namearray 1467 1468 def _cmp_positions(self, a, b): 1469 1470 "Compare name plus position list operands 'a' and 'b'." 1471 1472 name_a, list_a = a 1473 name_b, list_b = b 1474 if len(list_a) < len(list_b): 1475 return -1 1476 elif len(list_a) > len(list_b): 1477 return 1 1478 elif not list_a: 1479 return 0 1480 else: 1481 return cmp(min(list_a), min(list_b)) 1482 1483 def all_attribute_names(self): 1484 1485 """ 1486 Return the names of all attributes provided by instances of this class. 1487 """ 1488 1489 self.allattr_names = self.allattr_names or self.all_attributes().keys() 1490 return self.allattr_names 1491 1492 def all_attributes(self): 1493 1494 """ 1495 Return all attributes for an instance, indicating either the class which 1496 provides them or that the instance itself provides them. 1497 1498 Note that __class__ acts like an instance attribute for both instances 1499 and classes. 1500 """ 1501 1502 if self.allattr is None: 1503 self.allattr = {} 1504 self.allattr.update(self.all_class_attributes()) 1505 for name, attr in self.instance_attributes().items(): 1506 if self.allattr.has_key(name) and name != "__class__": 1507 print "Warning: instance attribute %r in %r overrides class attribute." % (name, self) 1508 self.allattr[name] = attr 1509 return self.allattr 1510 1511 class TypeClass(Class): 1512 1513 "A special class for the type class." 1514 1515 def initialise_class_attribute(self): 1516 self.set("__class__", self) 1517 1518 class CommonClass(Class): 1519 1520 "An inspected class." 1521 1522 def initialise_class_attribute(self): 1523 self.set("__class__", type_class) 1524 1525 class Function(NamespaceDict, Naming, Constant): 1526 1527 "An inspected function." 1528 1529 def __init__(self, name, parent, argnames, defaults, has_star, has_dstar, 1530 dynamic_def=0, module=None, node=None): 1531 1532 """ 1533 Initialise the function with the given 'name', 'parent', list of 1534 'argnames', list of 'defaults', the 'has_star' flag (indicating the 1535 presence of a * parameter), the 'has_dstar' flag (indicating the 1536 presence of a ** parameter), optional 'dynamic_def' (indicating that the 1537 function must be handled dynamically), optional 'module', and optional 1538 AST 'node'. 1539 """ 1540 1541 NamespaceDict.__init__(self, module) 1542 1543 if name is None: 1544 self.name = "lambda#%d" % new_lambda() 1545 self._is_lambda = 1 1546 else: 1547 self.name = name 1548 self._is_lambda = 0 1549 1550 self.parent = parent 1551 self.argnames = argnames 1552 self.defaults = defaults 1553 self.has_star = has_star 1554 self.has_dstar = has_dstar 1555 self.dynamic_def = dynamic_def 1556 self.astnode = node 1557 1558 # Initialise the positional names. 1559 1560 self.positional_names = self.argnames[:] 1561 if has_dstar: 1562 self.dstar_name = self.positional_names[-1] 1563 del self.positional_names[-1] 1564 if has_star: 1565 self.star_name = self.positional_names[-1] 1566 del self.positional_names[-1] 1567 1568 # Initialise default storage. 1569 # NOTE: This must be initialised separately due to the reliance on node 1570 # NOTE: visiting. 1571 1572 self.default_attrs = [] 1573 1574 # Initialise attribute usage. 1575 1576 if node is not None: 1577 for arg in argnames: 1578 1579 # Define attribute users. 1580 1581 self._define_attribute_user_for_name(node, arg) 1582 1583 # Caches. 1584 1585 self.localnames = None # cache for locals 1586 1587 # Add parameters to the namespace. 1588 1589 self._add_parameters(argnames) 1590 1591 # Image generation details. 1592 1593 self.dynamic = None 1594 self.location = None 1595 self.code_location = None 1596 self.code_body_location = None 1597 1598 # Program-related details. 1599 1600 self.blocks = None 1601 self.body_block = None 1602 1603 self.temp_usage = 0 1604 self.local_usage = 0 1605 self.all_local_usage = 0 1606 1607 def _add_parameters(self, argnames): 1608 1609 "Add 'argnames' to the namespace." 1610 1611 for name in argnames: 1612 self.set(name, Instance()) 1613 1614 for name, top_level in self._flattened_parameters(argnames): 1615 if not top_level: 1616 self.set(name, Instance()) 1617 1618 def _flattened_parameters(self, argnames, top_level=1): 1619 l = [] 1620 for name in argnames: 1621 if isinstance(name, tuple): 1622 l += self._flattened_parameters(name, 0) 1623 else: 1624 l.append((name, top_level)) 1625 return l 1626 1627 def __repr__(self): 1628 if self.location is not None: 1629 return "Function(%r, %s, %r, location=%r, code_location=%r)" % ( 1630 self.name, shortrepr(self.parent), self.argnames, self.location, self.code_location 1631 ) 1632 else: 1633 return "Function(%r, %s, %r)" % ( 1634 self.name, shortrepr(self.parent), self.argnames 1635 ) 1636 1637 def __shortrepr__(self): 1638 return "Function(%r, %s)" % ( 1639 self.name, shortrepr(self.parent) 1640 ) 1641 1642 def get_body_block(self): 1643 return self.body_block 1644 1645 def is_lambda(self): 1646 return self._is_lambda 1647 1648 # Defaults-related methods. 1649 1650 def store_default(self, attr_or_value): 1651 1652 """ 1653 Reserve space for defaults, set outside the function, potentially on a 1654 dynamic basis, using the 'attr_or_value'. 1655 """ 1656 1657 attr = Attr(None, self, None) 1658 self._set_using_attr(attr, attr_or_value) 1659 self.default_attrs.append(attr) 1660 1661 def make_dynamic(self): 1662 1663 "Return whether this function must be handled using a dynamic object." 1664 1665 if self.dynamic is None: 1666 for attr in self.default_attrs: 1667 if not attr.is_strict_constant() and self.dynamic_def: 1668 self.dynamic = 1 1669 self._make_dynamic() 1670 break 1671 else: 1672 self.dynamic = 0 1673 1674 return self.dynamic 1675 1676 is_dynamic = make_dynamic 1677 1678 def _make_dynamic(self): 1679 1680 "Where functions have dynamic defaults, add a context argument." 1681 1682 name = "<context>" 1683 self.argnames.insert(0, name) 1684 self.positional_names.insert(0, name) 1685 self.set(name, Instance()) 1686 1687 # Namespace-related methods. 1688 1689 def make_global(self, name): 1690 1691 "Declare 'name' as a global in the current namespace." 1692 1693 if name not in self.argnames and not self.has_key(name): 1694 self.globals.add(name) 1695 return 1 1696 else: 1697 return 0 1698 1699 def parameters(self): 1700 1701 """ 1702 Return a dictionary mapping parameter names to their position in the 1703 parameter list. 1704 """ 1705 1706 parameters = {} 1707 for i, name in enumerate(self.argnames): 1708 parameters[name] = i 1709 return parameters 1710 1711 def tuple_parameters(self, argnames=None): 1712 1713 """ 1714 Return a list of (position, parameter) entries corresponding to tuple 1715 parameters, where each parameter may either be a string or another such 1716 list of entries. 1717 """ 1718 1719 names = argnames or self.argnames 1720 1721 l = [] 1722 for i, name in enumerate(names): 1723 if isinstance(name, tuple): 1724 l.append((i, self.tuple_parameters(name))) 1725 elif argnames: 1726 l.append((i, name)) 1727 return l 1728 1729 def all_locals(self): 1730 1731 "Return a dictionary mapping names to local and parameter details." 1732 1733 return dict(self) 1734 1735 def locals(self): 1736 1737 "Return a dictionary mapping names to local details." 1738 1739 if self.localnames is None: 1740 self.localnames = {} 1741 self.localnames.update(self.all_locals()) 1742 for name in self.argnames: 1743 del self.localnames[name] 1744 return self.localnames 1745 1746 def is_method(self): 1747 1748 """ 1749 Return whether this function is a method explicitly defined in a class. 1750 """ 1751 1752 return isinstance(self.parent, Class) 1753 1754 def is_relocated(self, name): 1755 1756 """ 1757 Determine whether the given attribute 'name' is relocated for instances 1758 having this function as a method. 1759 """ 1760 1761 for cls in self.parent.descendants: 1762 if name in cls.relocated: 1763 return 1 1764 return 0 1765 1766 # Administrative methods. 1767 1768 def items_for_vacuum(self): 1769 return self.lambdas.items() 1770 1771 def vacuum_item(self, name): 1772 del self.lambdas[name] 1773 return 1 1774 1775 def finalise_attributes(self): 1776 1777 """ 1778 Make sure all attributes (locals) are fully defined. Note that locals 1779 are not attributes in the sense of class, module or instance attributes. 1780 Defaults are also finalised by this method. 1781 """ 1782 1783 if self.finalised: 1784 return 1785 1786 # Defaults. 1787 1788 for i, default in enumerate(self.default_attrs): 1789 default.position = i 1790 1791 # Parameters. 1792 1793 i = self._finalise_parameters() 1794 1795 if i is not None: 1796 nparams = i + 1 1797 else: 1798 nparams = 0 1799 1800 # Locals (and tuple parameter names). 1801 1802 i = None 1803 for i, attr in enumerate(self.locals().values()): 1804 attr.position = i + nparams 1805 1806 if i is not None: 1807 nothers = i + 1 1808 else: 1809 nothers = 0 1810 1811 self.local_usage = nothers 1812 self.all_local_usage = nparams + nothers 1813 self.finalised = 1 1814 1815 def _finalise_parameters(self): 1816 if not self.argnames: 1817 return None 1818 1819 for i, name in enumerate(self.argnames): 1820 self[name].position = i 1821 1822 return i 1823 1824 def as_instantiator(self): 1825 1826 "Make an instantiator function from a method, keeping all arguments." 1827 1828 function = Function(self.parent.name, self.parent.parent, self.argnames, self.defaults, 1829 self.has_star, self.has_dstar, self.dynamic_def, self.module) 1830 function.default_attrs = self.default_attrs 1831 return function 1832 1833 class UnresolvedName(NamespaceDict, Constant): 1834 1835 "A module, class or function which was mentioned but could not be imported." 1836 1837 def __init__(self, name, parent_name, module=None): 1838 NamespaceDict.__init__(self, module) 1839 self.name = name 1840 self.parent_name = parent_name 1841 self.parent = None 1842 1843 self.descendants = set() 1844 1845 def add_descendant(self, cls): 1846 self.descendants.add(cls) 1847 1848 def all_attributes(self): 1849 return {} 1850 1851 def all_attribute_names(self): 1852 return [] 1853 1854 all_class_attributes = class_attributes = instance_attributes = all_attributes 1855 all_class_attribute_names = class_attribute_names = instance_attribute_names = all_attribute_names 1856 1857 def __repr__(self): 1858 return "UnresolvedName(%r, %r)" % (self.name, self.parent_name) 1859 1860 __shortrepr__ = __repr__ 1861 1862 def full_name(self): 1863 if self.name is not None: 1864 return self.parent_name + "." + self.name 1865 else: 1866 return self.parent_name 1867 1868 class Module(NamespaceDict, Constant): 1869 1870 "An inspected module's core details." 1871 1872 def __init__(self, name, importer): 1873 NamespaceDict.__init__(self, self) 1874 self.name = name 1875 self.importer = importer 1876 self.parent = None 1877 1878 # Original location details. 1879 1880 self.astnode = None 1881 1882 # Complete lists of classes and functions. 1883 1884 self.all_objects = set() 1885 1886 # Keyword records. 1887 1888 self.keyword_names = set() 1889 1890 # Image generation details. 1891 1892 self.location = None 1893 self.code_location = None 1894 1895 # Program-related details. 1896 1897 self.blocks = None 1898 self.temp_usage = 0 1899 self.local_usage = 0 1900 self.all_local_usage = 0 1901 1902 def full_name(self): 1903 return self.name 1904 1905 def __repr__(self): 1906 if self.location is not None: 1907 return "Module(%r, location=%r)" % (self.name, self.location) 1908 else: 1909 return "Module(%r)" % self.name 1910 1911 def __shortrepr__(self): 1912 return "Module(%r)" % self.name 1913 1914 # Attribute methods. 1915 1916 "Return the module attribute names provided by the module." 1917 1918 module_attribute_names = NamespaceDict.keys 1919 1920 def module_attributes(self): 1921 1922 "Return a dictionary mapping names to module attributes." 1923 1924 return dict(self) 1925 1926 # Pre-made instances. 1927 1928 type_class = TypeClass("type") # details to be filled in later 1929 1930 # Class construction. 1931 1932 def get_class(name, parent, module, node): 1933 1934 """ 1935 Return a Class instance for the class with the given 'name', 'parent', 1936 'module' and 'node'. 1937 """ 1938 1939 if name == "type" and module.full_name() == "__builtins__": 1940 type_class.set_context(parent, module, node) 1941 return type_class 1942 else: 1943 return CommonClass(name, parent, module, node) 1944 1945 # vim: tabstop=4 expandtab shiftwidth=4