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