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 clsattr[name] = set() # position not yet defined 1325 1326 reversed_bases = self.bases[:] 1327 reversed_bases.reverse() 1328 1329 # For the bases in reverse order, acquire class attribute details. 1330 1331 for cls in reversed_bases: 1332 for name, attr in cls.all_class_attributes().items(): 1333 self.all_classattr[name] = attr 1334 1335 # Record previous attribute information. 1336 1337 if clsattr.has_key(name): 1338 clsattr[name].add(attr.position) 1339 1340 # Record class attributes provided by this class and its bases, 1341 # along with their positions. 1342 1343 self.all_classattr.update(self.class_attributes()) 1344 1345 if clsattr: 1346 for i, name in enumerate(self._get_position_list(clsattr)): 1347 self.all_classattr[name].position = i 1348 1349 return self.all_classattr 1350 1351 def instance_attribute_names(self): 1352 1353 "Return the instance attribute names provided by the class." 1354 1355 if self.all_instattr_names is None: 1356 self.instance_attributes() 1357 return self.all_instattr_names 1358 1359 def instance_attributes(self): 1360 1361 "Return instance-only attributes for instances of this class." 1362 1363 self.finalise_instance_attributes() 1364 return self.all_instattr 1365 1366 def finalise_instance_attributes(self): 1367 1368 "Make sure that the instance attributes are fully defined." 1369 1370 # Cache the attributes by converting the positioned attributes into a 1371 # dictionary. 1372 1373 if self.all_instattr is None: 1374 self.all_instattr = self._get_attributes() 1375 self.all_instattr_names = self.all_instattr.keys() 1376 1377 return self.all_instattr 1378 1379 def _get_attributes(self): 1380 1381 """ 1382 Return a dictionary mapping names to Attr instances incorporating 1383 information about their positions in the final instance structure. 1384 """ 1385 1386 instattr = {} 1387 1388 # Record provisional position information for attributes of this 1389 # instance. 1390 1391 for name in self.instattr: 1392 instattr[name] = set() # position not yet defined 1393 1394 reversed_bases = self.bases[:] 1395 reversed_bases.reverse() 1396 1397 # For the bases in reverse order, acquire instance attribute 1398 # details. 1399 1400 for cls in reversed_bases: 1401 for name, attr in cls.instance_attributes().items(): 1402 1403 # Record previous attribute information. 1404 1405 if instattr.has_key(name): 1406 instattr[name].add(attr.position) 1407 else: 1408 instattr[name] = set([attr.position]) 1409 1410 # Build the dictionary of attributes using the existing positions known 1411 # for each name. 1412 1413 d = {} 1414 for i, name in enumerate(self._get_position_list(instattr)): 1415 d[name] = Attr(i, Instance(), name) 1416 return d 1417 1418 def _get_position_list(self, positions): 1419 1420 """ 1421 Return a list of attribute names for the given 'positions' mapping from 1422 names to positions, indicating the positions of the attributes in the 1423 final instance structure. 1424 """ 1425 1426 position_items = positions.items() 1427 namearray = [None] * len(position_items) 1428 1429 # Get the positions in ascending order of list size, with lists 1430 # of the same size ordered according to their smallest position 1431 # value. 1432 1433 position_items.sort(self._cmp_positions) 1434 1435 # Get the names in position order. 1436 1437 held = [] 1438 1439 for name, pos in position_items: 1440 pos = list(pos) 1441 pos.sort() 1442 if pos and pos[0] < len(namearray) and namearray[pos[0]] is None: 1443 namearray[pos[0]] = name 1444 else: 1445 if pos: 1446 self.relocated.add(name) 1447 held.append((name, pos)) 1448 1449 for i, attr in enumerate(namearray): 1450 if attr is None: 1451 name, pos = held.pop() 1452 namearray[i] = name 1453 1454 return namearray 1455 1456 def _cmp_positions(self, a, b): 1457 1458 "Compare name plus position list operands 'a' and 'b'." 1459 1460 name_a, list_a = a 1461 name_b, list_b = b 1462 if len(list_a) < len(list_b): 1463 return -1 1464 elif len(list_a) > len(list_b): 1465 return 1 1466 elif not list_a: 1467 return 0 1468 else: 1469 return cmp(min(list_a), min(list_b)) 1470 1471 def all_attribute_names(self): 1472 1473 """ 1474 Return the names of all attributes provided by instances of this class. 1475 """ 1476 1477 self.allattr_names = self.allattr_names or self.all_attributes().keys() 1478 return self.allattr_names 1479 1480 def all_attributes(self): 1481 1482 """ 1483 Return all attributes for an instance, indicating either the class which 1484 provides them or that the instance itself provides them. 1485 1486 Note that __class__ acts like an instance attribute for both instances 1487 and classes. 1488 """ 1489 1490 if self.allattr is None: 1491 self.allattr = {} 1492 self.allattr.update(self.all_class_attributes()) 1493 for name, attr in self.instance_attributes().items(): 1494 if self.allattr.has_key(name) and name != "__class__": 1495 print "Warning: instance attribute %r in %r overrides class attribute." % (name, self) 1496 self.allattr[name] = attr 1497 return self.allattr 1498 1499 class TypeClass(Class): 1500 1501 "A special class for the type class." 1502 1503 def initialise_class_attribute(self): 1504 self.set("__class__", self) 1505 1506 class CommonClass(Class): 1507 1508 "An inspected class." 1509 1510 def initialise_class_attribute(self): 1511 self.set("__class__", type_class) 1512 1513 class Function(NamespaceDict, Naming, Constant): 1514 1515 "An inspected function." 1516 1517 def __init__(self, name, parent, argnames, defaults, has_star, has_dstar, 1518 dynamic_def=0, module=None, node=None): 1519 1520 """ 1521 Initialise the function with the given 'name', 'parent', list of 1522 'argnames', list of 'defaults', the 'has_star' flag (indicating the 1523 presence of a * parameter), the 'has_dstar' flag (indicating the 1524 presence of a ** parameter), optional 'dynamic_def' (indicating that the 1525 function must be handled dynamically), optional 'module', and optional 1526 AST 'node'. 1527 """ 1528 1529 NamespaceDict.__init__(self, module) 1530 1531 if name is None: 1532 self.name = "lambda#%d" % new_lambda() 1533 self._is_lambda = 1 1534 else: 1535 self.name = name 1536 self._is_lambda = 0 1537 1538 self.parent = parent 1539 self.argnames = argnames 1540 self.defaults = defaults 1541 self.has_star = has_star 1542 self.has_dstar = has_dstar 1543 self.dynamic_def = dynamic_def 1544 self.astnode = node 1545 1546 # Initialise the positional names. 1547 1548 self.positional_names = self.argnames[:] 1549 if has_dstar: 1550 self.dstar_name = self.positional_names[-1] 1551 del self.positional_names[-1] 1552 if has_star: 1553 self.star_name = self.positional_names[-1] 1554 del self.positional_names[-1] 1555 1556 # Initialise default storage. 1557 # NOTE: This must be initialised separately due to the reliance on node 1558 # NOTE: visiting. 1559 1560 self.default_attrs = [] 1561 1562 # Initialise attribute usage. 1563 1564 if node is not None: 1565 for arg in argnames: 1566 1567 # Define attribute users. 1568 1569 self._define_attribute_user_for_name(node, arg) 1570 1571 # Caches. 1572 1573 self.localnames = None # cache for locals 1574 1575 # Add parameters to the namespace. 1576 1577 self._add_parameters(argnames) 1578 1579 # Image generation details. 1580 1581 self.dynamic = None 1582 self.location = None 1583 self.code_location = None 1584 self.code_body_location = None 1585 1586 # Program-related details. 1587 1588 self.blocks = None 1589 self.body_block = None 1590 1591 self.temp_usage = 0 1592 self.local_usage = 0 1593 self.all_local_usage = 0 1594 1595 def _add_parameters(self, argnames): 1596 1597 "Add 'argnames' to the namespace." 1598 1599 for name in argnames: 1600 self.set(name, Instance()) 1601 1602 for name, top_level in self._flattened_parameters(argnames): 1603 if not top_level: 1604 self.set(name, Instance()) 1605 1606 def _flattened_parameters(self, argnames, top_level=1): 1607 l = [] 1608 for name in argnames: 1609 if isinstance(name, tuple): 1610 l += self._flattened_parameters(name, 0) 1611 else: 1612 l.append((name, top_level)) 1613 return l 1614 1615 def __repr__(self): 1616 if self.location is not None: 1617 return "Function(%r, %s, %r, location=%r, code_location=%r)" % ( 1618 self.name, shortrepr(self.parent), self.argnames, self.location, self.code_location 1619 ) 1620 else: 1621 return "Function(%r, %s, %r)" % ( 1622 self.name, shortrepr(self.parent), self.argnames 1623 ) 1624 1625 def __shortrepr__(self): 1626 return "Function(%r, %s)" % ( 1627 self.name, shortrepr(self.parent) 1628 ) 1629 1630 def get_body_block(self): 1631 return self.body_block 1632 1633 def is_lambda(self): 1634 return self._is_lambda 1635 1636 # Defaults-related methods. 1637 1638 def store_default(self, attr_or_value): 1639 1640 """ 1641 Reserve space for defaults, set outside the function, potentially on a 1642 dynamic basis, using the 'attr_or_value'. 1643 """ 1644 1645 attr = Attr(None, self, None) 1646 self._set_using_attr(attr, attr_or_value) 1647 self.default_attrs.append(attr) 1648 1649 def make_dynamic(self): 1650 1651 "Return whether this function must be handled using a dynamic object." 1652 1653 if self.dynamic is None: 1654 for attr in self.default_attrs: 1655 if not attr.is_strict_constant() and self.dynamic_def: 1656 self.dynamic = 1 1657 self._make_dynamic() 1658 break 1659 else: 1660 self.dynamic = 0 1661 1662 return self.dynamic 1663 1664 is_dynamic = make_dynamic 1665 1666 def _make_dynamic(self): 1667 1668 "Where functions have dynamic defaults, add a context argument." 1669 1670 name = "<context>" 1671 self.argnames.insert(0, name) 1672 self.positional_names.insert(0, name) 1673 self.set(name, Instance()) 1674 1675 # Namespace-related methods. 1676 1677 def make_global(self, name): 1678 1679 "Declare 'name' as a global in the current namespace." 1680 1681 if name not in self.argnames and not self.has_key(name): 1682 self.globals.add(name) 1683 return 1 1684 else: 1685 return 0 1686 1687 def parameters(self): 1688 1689 """ 1690 Return a dictionary mapping parameter names to their position in the 1691 parameter list. 1692 """ 1693 1694 parameters = {} 1695 for i, name in enumerate(self.argnames): 1696 parameters[name] = i 1697 return parameters 1698 1699 def tuple_parameters(self, argnames=None): 1700 1701 """ 1702 Return a list of (position, parameter) entries corresponding to tuple 1703 parameters, where each parameter may either be a string or another such 1704 list of entries. 1705 """ 1706 1707 names = argnames or self.argnames 1708 1709 l = [] 1710 for i, name in enumerate(names): 1711 if isinstance(name, tuple): 1712 l.append((i, self.tuple_parameters(name))) 1713 elif argnames: 1714 l.append((i, name)) 1715 return l 1716 1717 def all_locals(self): 1718 1719 "Return a dictionary mapping names to local and parameter details." 1720 1721 return dict(self) 1722 1723 def locals(self): 1724 1725 "Return a dictionary mapping names to local details." 1726 1727 if self.localnames is None: 1728 self.localnames = {} 1729 self.localnames.update(self.all_locals()) 1730 for name in self.argnames: 1731 del self.localnames[name] 1732 return self.localnames 1733 1734 def is_method(self): 1735 1736 """ 1737 Return whether this function is a method explicitly defined in a class. 1738 """ 1739 1740 return isinstance(self.parent, Class) 1741 1742 def is_relocated(self, name): 1743 1744 """ 1745 Determine whether the given attribute 'name' is relocated for instances 1746 having this function as a method. 1747 """ 1748 1749 for cls in self.parent.descendants: 1750 if name in cls.relocated: 1751 return 1 1752 return 0 1753 1754 # Administrative methods. 1755 1756 def items_for_vacuum(self): 1757 return self.lambdas.items() 1758 1759 def vacuum_item(self, name): 1760 del self.lambdas[name] 1761 return 1 1762 1763 def finalise_attributes(self): 1764 1765 """ 1766 Make sure all attributes (locals) are fully defined. Note that locals 1767 are not attributes in the sense of class, module or instance attributes. 1768 Defaults are also finalised by this method. 1769 """ 1770 1771 if self.finalised: 1772 return 1773 1774 # Defaults. 1775 1776 for i, default in enumerate(self.default_attrs): 1777 default.position = i 1778 1779 # Parameters. 1780 1781 i = self._finalise_parameters() 1782 1783 if i is not None: 1784 nparams = i + 1 1785 else: 1786 nparams = 0 1787 1788 # Locals (and tuple parameter names). 1789 1790 i = None 1791 for i, attr in enumerate(self.locals().values()): 1792 attr.position = i + nparams 1793 1794 if i is not None: 1795 nothers = i + 1 1796 else: 1797 nothers = 0 1798 1799 self.local_usage = nothers 1800 self.all_local_usage = nparams + nothers 1801 self.finalised = 1 1802 1803 def _finalise_parameters(self): 1804 if not self.argnames: 1805 return None 1806 1807 for i, name in enumerate(self.argnames): 1808 self[name].position = i 1809 1810 return i 1811 1812 def as_instantiator(self): 1813 1814 "Make an instantiator function from a method, keeping all arguments." 1815 1816 function = Function(self.parent.name, self.parent.parent, self.argnames, self.defaults, 1817 self.has_star, self.has_dstar, self.dynamic_def, self.module) 1818 function.default_attrs = self.default_attrs 1819 return function 1820 1821 class UnresolvedName(NamespaceDict, Constant): 1822 1823 "A module, class or function which was mentioned but could not be imported." 1824 1825 def __init__(self, name, parent_name, module=None): 1826 NamespaceDict.__init__(self, module) 1827 self.name = name 1828 self.parent_name = parent_name 1829 self.parent = None 1830 1831 self.descendants = set() 1832 1833 def add_descendant(self, cls): 1834 self.descendants.add(cls) 1835 1836 def all_attributes(self): 1837 return {} 1838 1839 def all_attribute_names(self): 1840 return [] 1841 1842 all_class_attributes = class_attributes = instance_attributes = all_attributes 1843 all_class_attribute_names = class_attribute_names = instance_attribute_names = all_attribute_names 1844 1845 def __repr__(self): 1846 return "UnresolvedName(%r, %r)" % (self.name, self.parent_name) 1847 1848 __shortrepr__ = __repr__ 1849 1850 def full_name(self): 1851 if self.name is not None: 1852 return self.parent_name + "." + self.name 1853 else: 1854 return self.parent_name 1855 1856 class Module(NamespaceDict, Constant): 1857 1858 "An inspected module's core details." 1859 1860 def __init__(self, name, importer): 1861 NamespaceDict.__init__(self, self) 1862 self.name = name 1863 self.importer = importer 1864 self.parent = None 1865 1866 # Original location details. 1867 1868 self.astnode = None 1869 1870 # Complete lists of classes and functions. 1871 1872 self.all_objects = set() 1873 1874 # Keyword records. 1875 1876 self.keyword_names = set() 1877 1878 # Image generation details. 1879 1880 self.location = None 1881 self.code_location = None 1882 1883 # Program-related details. 1884 1885 self.blocks = None 1886 self.temp_usage = 0 1887 self.local_usage = 0 1888 self.all_local_usage = 0 1889 1890 def full_name(self): 1891 return self.name 1892 1893 def __repr__(self): 1894 if self.location is not None: 1895 return "Module(%r, location=%r)" % (self.name, self.location) 1896 else: 1897 return "Module(%r)" % self.name 1898 1899 def __shortrepr__(self): 1900 return "Module(%r)" % self.name 1901 1902 # Attribute methods. 1903 1904 "Return the module attribute names provided by the module." 1905 1906 module_attribute_names = NamespaceDict.keys 1907 1908 def module_attributes(self): 1909 1910 "Return a dictionary mapping names to module attributes." 1911 1912 return dict(self) 1913 1914 # Pre-made instances. 1915 1916 type_class = TypeClass("type") # details to be filled in later 1917 1918 # Class construction. 1919 1920 def get_class(name, parent, module, node): 1921 1922 """ 1923 Return a Class instance for the class with the given 'name', 'parent', 1924 'module' and 'node'. 1925 """ 1926 1927 if name == "type" and module.full_name() == "__builtins__": 1928 type_class.set_context(parent, module, node) 1929 return type_class 1930 else: 1931 return CommonClass(name, parent, module, node) 1932 1933 # vim: tabstop=4 expandtab shiftwidth=4