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