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(Namespace): 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 def get_static_attribute(self, name): 1660 1661 """ 1662 Return a static attribute for the given 'name' or None if no such 1663 attribute exists. 1664 """ 1665 1666 return self.all_class_attributes().get(name) 1667 1668 class TypeClass(Class): 1669 1670 "A special class for the type class." 1671 1672 pass 1673 1674 class CommonClass(Class): 1675 1676 "An inspected class." 1677 1678 pass 1679 1680 class Function(NamespaceDict, Naming, Constant): 1681 1682 "An inspected function." 1683 1684 def __init__(self, name, parent, argnames, defaults, has_star, has_dstar, 1685 dynamic_def=0, module=None, node=None): 1686 1687 """ 1688 Initialise the function with the given 'name', 'parent', list of 1689 'argnames', list of 'defaults', the 'has_star' flag (indicating the 1690 presence of a * parameter), the 'has_dstar' flag (indicating the 1691 presence of a ** parameter), optional 'dynamic_def' (indicating that the 1692 function must be handled dynamically), optional 'module', and optional 1693 AST 'node'. 1694 """ 1695 1696 NamespaceDict.__init__(self, module) 1697 1698 if name is None: 1699 self.name = "lambda#%d" % new_lambda() 1700 self._is_lambda = True 1701 else: 1702 self.name = name 1703 self._is_lambda = False 1704 1705 self.parent = parent 1706 self.argnames = argnames 1707 self.defaults = defaults 1708 self.has_star = has_star 1709 self.has_dstar = has_dstar 1710 self.dynamic_def = dynamic_def 1711 self.astnode = node 1712 1713 # Initialise the positional names. 1714 1715 self.positional_names = self.argnames[:] 1716 if has_dstar: 1717 self.dstar_name = self.positional_names[-1] 1718 del self.positional_names[-1] 1719 if has_star: 1720 self.star_name = self.positional_names[-1] 1721 del self.positional_names[-1] 1722 1723 # Initialise default storage. 1724 # NOTE: This must be initialised separately due to the reliance on node 1725 # NOTE: visiting. 1726 1727 self.default_attrs = [] 1728 1729 # Initialise attribute usage. 1730 1731 if node is not None: 1732 for arg in argnames: 1733 1734 # Define attribute users. 1735 1736 self._define_attribute_user_for_name(node, arg) 1737 1738 # Caches. 1739 1740 self.localnames = None # cache for locals 1741 1742 # Add parameters to the namespace. 1743 1744 self._add_parameters(argnames) 1745 1746 # Image generation details. 1747 1748 self.dynamic = None 1749 self.location = None 1750 self.code_location = None 1751 self.code_body_location = None 1752 1753 # Program-related details. 1754 1755 self.blocks = None 1756 self.body_block = None 1757 1758 self.temp_usage = 0 1759 self.local_usage = 0 1760 self.all_local_usage = 0 1761 1762 def _add_parameters(self, argnames): 1763 1764 "Add 'argnames' to the namespace." 1765 1766 for name in argnames: 1767 self.set(name, make_instance()) 1768 1769 for name, top_level in self._flattened_parameters(argnames): 1770 if not top_level: 1771 self.set(name, make_instance()) 1772 1773 def _flattened_parameters(self, argnames, top_level=1): 1774 l = [] 1775 for name in argnames: 1776 if isinstance(name, tuple): 1777 l += self._flattened_parameters(name, 0) 1778 else: 1779 l.append((name, top_level)) 1780 return l 1781 1782 def __repr__(self): 1783 if self.location is not None: 1784 return "<function %s (at %r, code at %r)>" % ( 1785 shortrepr(self), self.location, self.code_location 1786 ) 1787 else: 1788 return "<function %s>" % shortrepr(self) 1789 1790 def __shortrepr__(self): 1791 return "%s.%s(%s)" % (shortrepr(self.parent), self.name, ", ".join(self.argnames)) 1792 1793 def get_body_block(self): 1794 return self.body_block 1795 1796 def is_lambda(self): 1797 return self._is_lambda 1798 1799 # Defaults-related methods. 1800 1801 def store_default(self, attr_or_value): 1802 1803 """ 1804 Reserve space for defaults, set outside the function, potentially on a 1805 dynamic basis, using the 'attr_or_value'. 1806 """ 1807 1808 attr = Attr(None, self, None) 1809 self._set_using_attr(attr, attr_or_value) 1810 self.default_attrs.append(attr) 1811 1812 def make_dynamic(self): 1813 1814 "Return whether this function must be handled using a dynamic object." 1815 1816 if self.dynamic is None: 1817 for attr in self.default_attrs: 1818 if not attr.is_strict_constant() and self.dynamic_def: 1819 self.dynamic = True 1820 self._make_dynamic() 1821 break 1822 else: 1823 self.dynamic = False 1824 1825 return self.dynamic 1826 1827 is_dynamic = make_dynamic 1828 1829 def _make_dynamic(self): 1830 1831 "Where functions have dynamic defaults, add a context argument." 1832 1833 name = "<context>" 1834 self.argnames.insert(0, name) 1835 self.positional_names.insert(0, name) 1836 self.set(name, make_instance()) 1837 1838 # Namespace-related methods. 1839 1840 def make_global(self, name): 1841 1842 "Declare 'name' as a global in the current namespace." 1843 1844 if name not in self.argnames and not self.has_key(name): 1845 self.globals.add(name) 1846 return True 1847 else: 1848 return False 1849 1850 def parameters(self): 1851 1852 """ 1853 Return a dictionary mapping parameter names to their position in the 1854 parameter list. 1855 """ 1856 1857 parameters = {} 1858 for i, name in enumerate(self.argnames): 1859 parameters[name] = i 1860 return parameters 1861 1862 def tuple_parameters(self, argnames=None): 1863 1864 """ 1865 Return a list of (position, parameter) entries corresponding to tuple 1866 parameters, where each parameter may either be a string or another such 1867 list of entries. 1868 """ 1869 1870 names = argnames or self.argnames 1871 1872 l = [] 1873 for i, name in enumerate(names): 1874 if isinstance(name, tuple): 1875 l.append((i, self.tuple_parameters(name))) 1876 elif argnames: 1877 l.append((i, name)) 1878 return l 1879 1880 def all_locals(self): 1881 1882 "Return a dictionary mapping names to local and parameter details." 1883 1884 return dict(self) 1885 1886 def locals(self): 1887 1888 "Return a dictionary mapping names to local details." 1889 1890 if self.localnames is None: 1891 self.localnames = {} 1892 self.localnames.update(self.all_locals()) 1893 for name in self.argnames: 1894 del self.localnames[name] 1895 return self.localnames 1896 1897 def is_method(self): 1898 1899 """ 1900 Return whether this function is a method explicitly defined in a class. 1901 """ 1902 1903 return isinstance(self.parent, Class) 1904 1905 def is_relocated(self, name): 1906 1907 """ 1908 Determine whether the given attribute 'name' is relocated for instances 1909 having this function as a method. 1910 """ 1911 1912 for cls in self.parent.descendants: 1913 if name in cls.relocated: 1914 return True 1915 return False 1916 1917 # Administrative methods. 1918 1919 def items_for_vacuum(self): 1920 return self.lambdas.items() 1921 1922 def vacuum_item(self, name): 1923 del self.lambdas[name] 1924 return True 1925 1926 def finalise_attributes(self): 1927 1928 """ 1929 Make sure all attributes (locals) are fully defined. Note that locals 1930 are not attributes in the sense of class, module or instance attributes. 1931 Defaults are also finalised by this method. 1932 """ 1933 1934 if self.finalised: 1935 return 1936 1937 # Defaults. 1938 1939 for i, default in enumerate(self.default_attrs): 1940 default.position = i 1941 1942 # Parameters. 1943 1944 i = self._finalise_parameters() 1945 1946 if i is not None: 1947 nparams = i + 1 1948 else: 1949 nparams = 0 1950 1951 # Locals (and tuple parameter names). 1952 1953 i = None 1954 for i, attr in enumerate(self.locals().values()): 1955 attr.position = i + nparams 1956 1957 if i is not None: 1958 nothers = i + 1 1959 else: 1960 nothers = 0 1961 1962 self.local_usage = nothers 1963 self.all_local_usage = nparams + nothers 1964 self.finalised = True 1965 1966 def _finalise_parameters(self): 1967 if not self.argnames: 1968 return None 1969 1970 for i, name in enumerate(self.argnames): 1971 self[name].position = i 1972 1973 return i 1974 1975 def as_instantiator(self): 1976 1977 "Make an instantiator function from a method, keeping all arguments." 1978 1979 function = Function(self.parent.name, self.parent.parent, self.argnames, self.defaults, 1980 self.has_star, self.has_dstar, self.dynamic_def, self.module) 1981 function.default_attrs = self.default_attrs 1982 return function 1983 1984 class UnresolvedName(NamespaceDict, Constant): 1985 1986 "A module, class or function which was mentioned but could not be imported." 1987 1988 def __init__(self, name, parent_name, module=None): 1989 NamespaceDict.__init__(self, module) 1990 self.name = name 1991 self.parent_name = parent_name 1992 self.parent = None 1993 1994 self.descendants = set() 1995 1996 def add_descendant(self, cls): 1997 self.descendants.add(cls) 1998 1999 def all_attributes(self): 2000 return {} 2001 2002 def all_attribute_names(self): 2003 return [] 2004 2005 all_class_attributes = class_attributes = instance_attributes = all_attributes 2006 all_class_attribute_names = class_attribute_names = instance_attribute_names = all_attribute_names 2007 2008 def __repr__(self): 2009 return "<unknown %s>" % shortrepr(self) 2010 2011 def __shortrepr__(self): 2012 if self.name is not None: 2013 return "%s.%s" % (self.parent_name, self.name) 2014 else: 2015 return self.parent_name 2016 2017 def full_name(self): 2018 if self.name is not None: 2019 return self.parent_name + "." + self.name 2020 else: 2021 return self.parent_name 2022 2023 class Module(NamespaceDict, Constant): 2024 2025 "An inspected module's core details." 2026 2027 def __init__(self, name, importer): 2028 NamespaceDict.__init__(self, self) 2029 self.name = name 2030 self.importer = importer 2031 self.parent = None 2032 2033 # Original location details. 2034 2035 self.astnode = None 2036 2037 # Complete lists of classes and functions. 2038 2039 self.all_objects = set() 2040 2041 # Whether the module is imported in a circular fashion, exposing the 2042 # unfinished namespace to external modification. 2043 2044 self.circular_import = self in importer.circular_imports 2045 2046 # A set of global names that cannot support combined attribute usage 2047 # observations because they may be modified within functions during 2048 # initialisation. 2049 2050 self.modified_names = set() 2051 2052 # Keyword records. 2053 2054 self.keyword_names = set() 2055 2056 # Image generation details. 2057 2058 self.location = None 2059 self.code_location = None 2060 2061 # Program-related details. 2062 2063 self.blocks = None 2064 self.temp_usage = 0 2065 self.local_usage = 0 2066 self.all_local_usage = 0 2067 2068 def full_name(self): 2069 return self.name 2070 2071 def __repr__(self): 2072 if self.location is not None: 2073 return "<module %s (at %r)>" % (self.name, self.location) 2074 else: 2075 return "<module %s>" % shortrepr(self) 2076 2077 def __shortrepr__(self): 2078 return self.name 2079 2080 # Attribute methods. 2081 2082 "Return the module attribute names provided by the module." 2083 2084 module_attribute_names = NamespaceDict.keys 2085 2086 def module_attributes(self): 2087 2088 "Return a dictionary mapping names to module attributes." 2089 2090 return dict(self) 2091 2092 def get_static_attribute(self, name): 2093 2094 """ 2095 Return a static attribute for the given 'name' or None if no such 2096 attribute exists. 2097 """ 2098 2099 return self.get(name) 2100 2101 def modify_name(self, name): 2102 2103 """ 2104 Modify a global 'name' invalidating various assumptions about its 2105 behaviour based on the module namespace being "safe" and suitable for 2106 attribute usage and constant value observations. 2107 """ 2108 2109 self.modified_names.add(name) 2110 2111 # Establish an attribute directly in the namespace if not present. 2112 2113 if not self.namespace.has_key(name): 2114 self.namespace[name] = Attr(None, self, name) 2115 2116 # Indicate that there is at least one assignment to the name, although 2117 # no actual values are recorded. 2118 2119 attr = self.namespace[name] 2120 attr.update_assignments(1, False) 2121 2122 def set(self, name, value, single_assignment=1): 2123 2124 """ 2125 Set the module attribute with the given 'name', having the given 'value' 2126 that is assigned once if 'single_assignment' is omitted to given as a 2127 true value. 2128 2129 Where the module is imported before it is completely initialised, all 2130 assignments will be regarded as multiple assignments since it is 2131 possible that an external assignment to the name may occur. 2132 """ 2133 2134 NamespaceDict.set(self, name, value, not self.circular_import and single_assignment) 2135 2136 # Attribute usage methods that apply to module globals in certain 2137 # circumstances. 2138 2139 def _use_attribute(self, name, attrname, value=None): 2140 if name not in self.modified_names and not self.circular_import: 2141 return NamespaceDict._use_attribute(self, name, attrname, value) 2142 else: 2143 self.importer.use_name(attrname, self.full_name(), value) 2144 return [] 2145 2146 def _define_attribute_user_for_name(self, node, name): 2147 if name not in self.modified_names and not self.circular_import: 2148 NamespaceDict._define_attribute_user_for_name(self, node, name) 2149 2150 def _init_attribute_user_for_name(self, node, name): 2151 if name not in self.modified_names and not self.circular_import: 2152 NamespaceDict._init_attribute_user_for_name(self, node, name) 2153 2154 def _define_attribute_accessor(self, name, attrname, node, value): 2155 if name not in self.modified_names and not self.circular_import: 2156 NamespaceDict._define_attribute_accessor(self, name, attrname, node, value) 2157 else: 2158 self.importer.use_name(attrname, self.full_name(), value) 2159 2160 # Pre-made instances. 2161 2162 type_class = TypeClass("type") # details to be filled in later 2163 2164 # Class construction. 2165 2166 def get_class(name, parent, module, node): 2167 2168 """ 2169 Return a Class instance for the class with the given 'name', 'parent', 2170 'module' and 'node'. 2171 """ 2172 2173 if name == "type" and module.full_name() == "__builtins__": 2174 type_class.set_context(parent, module, node) 2175 return type_class 2176 else: 2177 return CommonClass(name, parent, module, node) 2178 2179 # Lambda sequence numbering. 2180 2181 lambda_index = 0 2182 2183 def new_lambda(): 2184 2185 "Return a new sequence number for a lambda definition." 2186 2187 global lambda_index 2188 lambda_index += 1 2189 return lambda_index 2190 2191 # Special representations. 2192 2193 class AtLeast: 2194 2195 "A special representation for numbers of a given value or greater." 2196 2197 def __init__(self, count): 2198 self.count = count 2199 2200 def __eq__(self, other): 2201 return False 2202 2203 __lt__ = __le__ = __eq__ 2204 2205 def __ne__(self, other): 2206 return True 2207 2208 def __gt__(self, other): 2209 if isinstance(other, AtLeast): 2210 return False 2211 else: 2212 return self.count > other 2213 2214 def __ge__(self, other): 2215 if isinstance(other, AtLeast): 2216 return False 2217 else: 2218 return self.count >= other 2219 2220 def __iadd__(self, other): 2221 if isinstance(other, AtLeast): 2222 self.count += other.count 2223 else: 2224 self.count += other 2225 return self 2226 2227 def __radd__(self, other): 2228 if isinstance(other, AtLeast): 2229 return AtLeast(self.count + other.count) 2230 else: 2231 return AtLeast(self.count + other) 2232 2233 def __repr__(self): 2234 return "AtLeast(%r)" % self.count 2235 2236 class UnsetType: 2237 2238 "A None-like value." 2239 2240 def __nonzero__(self): 2241 return False 2242 2243 Unset = UnsetType() 2244 2245 # vim: tabstop=4 expandtab shiftwidth=4