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