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