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