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