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