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