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