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