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