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