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