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 = 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 (Instance(), 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 class Constant: 1102 1103 "A superclass for all constant or context-free structures." 1104 1105 pass 1106 1107 # Data objects appearing in programs before run-time. 1108 1109 class Const(Constant, Instance): 1110 1111 "A constant object with no context." 1112 1113 def __init__(self, value): 1114 Instance.__init__(self) 1115 self.value = value 1116 1117 def get_value(self): 1118 return self.value 1119 1120 def __repr__(self): 1121 if self.location is not None: 1122 return "Const(%r, location=%r)" % (self.value, self.location) 1123 else: 1124 return "Const(%r)" % self.value 1125 1126 __shortrepr__ = __repr__ 1127 1128 # Support constants as dictionary keys in order to build constant tables. 1129 1130 def __eq__(self, other): 1131 return other is not None and isinstance(other, Const) and \ 1132 self.value == other.value and self.value.__class__ is other.value.__class__ 1133 1134 def __ne__(self, other): 1135 return not self.__eq__(other) 1136 1137 def __hash__(self): 1138 return hash(self.value) 1139 1140 # Constants are instances of various built-in types. 1141 1142 def value_type_name(self): 1143 return ".".join(self.value_type_name_parts()) 1144 1145 def value_type_name_parts(self): 1146 return "__builtins__", self.value.__class__.__name__ 1147 1148 class Class(NamespaceDict, Naming, Constant): 1149 1150 "A base class for common/normal classes and the type class." 1151 1152 def __init__(self, name, parent=None, module=None, node=None): 1153 1154 """ 1155 Initialise the class with the given 'name', optional 'parent' object, 1156 'module' and AST 'node'. The optional information must be set at a later 1157 point using the 'set_context' method if omitted. 1158 """ 1159 1160 NamespaceDict.__init__(self, module) 1161 self.name = name 1162 self.parent = parent 1163 self.astnode = node 1164 1165 # Superclasses, descendants and attributes. 1166 1167 self.bases = [] 1168 self.descendants = set() 1169 self.instattr = set() # instance attributes 1170 self.relocated = set() # attributes which do not have the same 1171 # position as those of the same name in 1172 # some superclasses 1173 1174 # Caches. 1175 1176 self.reset_caches() 1177 1178 # Image generation details. 1179 1180 self.location = None 1181 self.code_location = None 1182 self.code_body_location = None # corresponds to the instantiator 1183 1184 self.instantiator = None 1185 self.instance_template_location = None # for creating instances at run-time 1186 1187 # Program-related details. 1188 1189 self.blocks = None 1190 self.temp_usage = 0 1191 self.local_usage = 0 1192 self.all_local_usage = 0 1193 1194 # Add an attribute to this class for use by instances. 1195 1196 self.set("__class__", self) 1197 1198 def set_context(self, parent, module, node): 1199 1200 "Set the 'parent', 'module' and 'node' of a class created in advance." 1201 1202 self.parent = parent 1203 self.module = module 1204 self.astnode = node 1205 1206 def reset_caches(self): 1207 1208 "Reset the caches." 1209 1210 self.all_instattr = None # cache for instance_attributes 1211 self.all_instattr_names = None # from all_instattr 1212 self.all_classattr = None # cache for all_class_attributes 1213 self.all_classattr_names = None # from all_classattr 1214 self.allattr = None # cache for all_attributes 1215 self.allattr_names = None # from allattr 1216 1217 def __repr__(self): 1218 if self.location is not None: 1219 return "Class(%r, %s, location=%r)" % (self.name, shortrepr(self.parent), self.location) 1220 else: 1221 return "Class(%r, %s)" % (self.name, shortrepr(self.parent)) 1222 1223 def __shortrepr__(self): 1224 return "Class(%r, %s)" % (self.name, shortrepr(self.parent)) 1225 1226 def get_body_block(self): 1227 return self.get_instantiator().blocks[0] 1228 1229 # Namespace-related methods. 1230 1231 def get_updated_context_values(self, context_values): 1232 1233 """ 1234 Adapt the contexts found in the given 'context_values', returning a new 1235 set. 1236 See: docs/assignment.txt 1237 """ 1238 1239 results = set() 1240 1241 for context, value in context_values: 1242 1243 # Change the ownership of functions. 1244 1245 if context is ReplaceableContext and value is not None and isinstance(value, Function): 1246 results.add((self, value)) 1247 else: 1248 results.add((context, value)) 1249 1250 return NamespaceDict.get_updated_context_values(self, results) 1251 1252 # Administrative methods. 1253 1254 def items_for_vacuum(self): 1255 1256 "Consider both class and instance attributes for vacuuming." 1257 1258 items = [] 1259 for name in self.instattr: 1260 items.append((name, None)) 1261 return NamespaceDict.items_for_vacuum(self) + items 1262 1263 def vacuum_item(self, name): 1264 1265 "Vacuum 'name' from the class or instance attribute collections." 1266 1267 # NOTE: Hack to prevent damage to exceptions. 1268 1269 if name == "_pc": 1270 return 0 1271 1272 if not NamespaceDict.vacuum_item(self, name): 1273 self.instattr.remove(name) 1274 return 1 1275 1276 def finalise_attributes(self): 1277 1278 "Make sure that all attributes are fully defined." 1279 1280 if self.finalised: 1281 return 1282 1283 self.finalise_class_attributes() 1284 self.finalise_instance_attributes() 1285 self.finalised = 1 1286 1287 def unfinalise_attributes(self): 1288 1289 "Open attribute definitions to editing and subsequent finalisation." 1290 1291 self.reset_caches() 1292 self.finalised = 0 1293 1294 # Convenience methods for accessing functions and methods. 1295 1296 def get_instantiator(self): 1297 1298 "Return a function which can be used to instantiate the class." 1299 1300 if self.instantiator is None: 1301 self.instantiator = self.get_init_method().as_instantiator() 1302 return self.instantiator 1303 1304 def get_init_method(self): 1305 return self.all_class_attributes()["__init__"].get_value() 1306 1307 # Class-specific methods. 1308 1309 def add_base(self, base): 1310 self.bases.append(base) 1311 base.add_descendant(self) 1312 1313 def add_instance_attribute(self, name): 1314 self.instattr.add(name) 1315 1316 def add_descendant(self, cls): 1317 self.descendants.add(cls) 1318 for base in self.bases: 1319 base.add_descendant(cls) 1320 1321 def has_subclass(self, other): 1322 return other in self.descendants 1323 1324 def all_descendants(self): 1325 d = {} 1326 for cls in self.descendants: 1327 d[cls.full_name()] = cls 1328 return d 1329 1330 "Return the attribute names provided by this class only." 1331 1332 class_attribute_names = NamespaceDict.keys 1333 1334 def class_attributes(self): 1335 1336 "Return class attributes provided by this class only." 1337 1338 return dict(self) 1339 1340 def all_class_attribute_names(self): 1341 1342 "Return the attribute names provided by classes in this hierarchy." 1343 1344 if self.all_classattr_names is None: 1345 self.all_class_attributes() 1346 self.all_classattr_names = self.all_classattr.keys() 1347 return self.all_classattr_names 1348 1349 def all_class_attributes(self): 1350 1351 "Return all class attributes, indicating the class which provides them." 1352 1353 self.finalise_class_attributes() 1354 return self.all_classattr 1355 1356 def finalise_class_attributes(self): 1357 1358 "Make sure that the class attributes are fully defined." 1359 1360 if self.all_classattr is None: 1361 self.all_classattr = {} 1362 clsattr = {} 1363 1364 # Record provisional position information for attributes of this 1365 # class. 1366 1367 for name in self.class_attributes().keys(): 1368 1369 # Special case: __class__ has to be at position 0. 1370 1371 if name == "__class__": 1372 clsattr[name] = set([0]) 1373 else: 1374 clsattr[name] = set() # position not yet defined 1375 1376 reversed_bases = self.bases[:] 1377 reversed_bases.reverse() 1378 1379 # For the bases in reverse order, acquire class attribute details. 1380 1381 for cls in reversed_bases: 1382 for name, attr in cls.all_class_attributes().items(): 1383 self.all_classattr[name] = attr 1384 1385 # Record previous attribute information. 1386 1387 if clsattr.has_key(name): 1388 clsattr[name].add(attr.position) 1389 1390 # Record class attributes provided by this class and its bases, 1391 # along with their positions. 1392 1393 self.all_classattr.update(self.class_attributes()) 1394 1395 if clsattr: 1396 for i, name in enumerate(self._get_position_list(clsattr)): 1397 self.all_classattr[name].position = i 1398 1399 return self.all_classattr 1400 1401 def instance_attribute_names(self): 1402 1403 "Return the instance attribute names provided by the class." 1404 1405 if self.all_instattr_names is None: 1406 self.instance_attributes() 1407 return self.all_instattr_names 1408 1409 def instance_attributes(self): 1410 1411 "Return instance-only attributes for instances of this class." 1412 1413 self.finalise_instance_attributes() 1414 return self.all_instattr 1415 1416 def finalise_instance_attributes(self): 1417 1418 "Make sure that the instance attributes are fully defined." 1419 1420 # Cache the attributes by converting the positioned attributes into a 1421 # dictionary. 1422 1423 if self.all_instattr is None: 1424 self.all_instattr = self._get_attributes() 1425 self.all_instattr_names = self.all_instattr.keys() 1426 1427 return self.all_instattr 1428 1429 def _get_attributes(self): 1430 1431 """ 1432 Return a dictionary mapping names to Attr instances incorporating 1433 information about their positions in the final instance structure. 1434 """ 1435 1436 instattr = {} 1437 1438 # Record provisional position information for attributes of this 1439 # instance. 1440 1441 for name in self.instattr: 1442 instattr[name] = set() # position not yet defined 1443 1444 reversed_bases = self.bases[:] 1445 reversed_bases.reverse() 1446 1447 # For the bases in reverse order, acquire instance attribute 1448 # details. 1449 1450 for cls in reversed_bases: 1451 for name, attr in cls.instance_attributes().items(): 1452 1453 # Record previous attribute information. 1454 1455 if instattr.has_key(name): 1456 instattr[name].add(attr.position) 1457 else: 1458 instattr[name] = set([attr.position]) 1459 1460 # Build the dictionary of attributes using the existing positions known 1461 # for each name. 1462 1463 d = {} 1464 for i, name in enumerate(self._get_position_list(instattr)): 1465 d[name] = Attr(i, Instance(), name) 1466 return d 1467 1468 def _get_position_list(self, positions): 1469 1470 """ 1471 Return a list of attribute names for the given 'positions' mapping from 1472 names to positions, indicating the positions of the attributes in the 1473 final instance structure. 1474 """ 1475 1476 position_items = positions.items() 1477 namearray = [None] * len(position_items) 1478 1479 # Get the positions in ascending order of list size, with lists 1480 # of the same size ordered according to their smallest position 1481 # value. 1482 1483 position_items.sort(self._cmp_positions) 1484 1485 # Get the names in position order. 1486 1487 held = [] 1488 1489 for name, pos in position_items: 1490 pos = list(pos) 1491 pos.sort() 1492 if pos and pos[0] < len(namearray) and namearray[pos[0]] is None: 1493 namearray[pos[0]] = name 1494 else: 1495 if pos: 1496 self.relocated.add(name) 1497 held.append((name, pos)) 1498 1499 for i, attr in enumerate(namearray): 1500 if attr is None: 1501 name, pos = held.pop() 1502 namearray[i] = name 1503 1504 return namearray 1505 1506 def _cmp_positions(self, a, b): 1507 1508 "Compare name plus position list operands 'a' and 'b'." 1509 1510 name_a, list_a = a 1511 name_b, list_b = b 1512 if len(list_a) < len(list_b): 1513 return -1 1514 elif len(list_a) > len(list_b): 1515 return 1 1516 elif not list_a: 1517 return 0 1518 else: 1519 return cmp(min(list_a), min(list_b)) 1520 1521 def all_attribute_names(self): 1522 1523 """ 1524 Return the names of all attributes provided by instances of this class. 1525 """ 1526 1527 self.allattr_names = self.allattr_names or self.all_attributes().keys() 1528 return self.allattr_names 1529 1530 def all_attributes(self): 1531 1532 """ 1533 Return all attributes for an instance, indicating either the class which 1534 provides them or that the instance itself provides them. 1535 1536 Note that __class__ acts like a class attribute for both instances and 1537 classes, and must be able to convey distinct values. 1538 """ 1539 1540 if self.allattr is None: 1541 self.allattr = {} 1542 self.allattr.update(self.all_class_attributes()) 1543 for name, attr in self.instance_attributes().items(): 1544 if self.allattr.has_key(name) and name != "__class__": 1545 print "Warning: instance attribute %r in %r overrides class attribute." % (name, self) 1546 self.allattr[name] = attr 1547 return self.allattr 1548 1549 class TypeClass(Class): 1550 1551 "A special class for the type class." 1552 1553 pass 1554 1555 class CommonClass(Class): 1556 1557 "An inspected class." 1558 1559 pass 1560 1561 class Function(NamespaceDict, Naming, Constant): 1562 1563 "An inspected function." 1564 1565 def __init__(self, name, parent, argnames, defaults, has_star, has_dstar, 1566 dynamic_def=0, module=None, node=None): 1567 1568 """ 1569 Initialise the function with the given 'name', 'parent', list of 1570 'argnames', list of 'defaults', the 'has_star' flag (indicating the 1571 presence of a * parameter), the 'has_dstar' flag (indicating the 1572 presence of a ** parameter), optional 'dynamic_def' (indicating that the 1573 function must be handled dynamically), optional 'module', and optional 1574 AST 'node'. 1575 """ 1576 1577 NamespaceDict.__init__(self, module) 1578 1579 if name is None: 1580 self.name = "lambda#%d" % new_lambda() 1581 self._is_lambda = 1 1582 else: 1583 self.name = name 1584 self._is_lambda = 0 1585 1586 self.parent = parent 1587 self.argnames = argnames 1588 self.defaults = defaults 1589 self.has_star = has_star 1590 self.has_dstar = has_dstar 1591 self.dynamic_def = dynamic_def 1592 self.astnode = node 1593 1594 # Initialise the positional names. 1595 1596 self.positional_names = self.argnames[:] 1597 if has_dstar: 1598 self.dstar_name = self.positional_names[-1] 1599 del self.positional_names[-1] 1600 if has_star: 1601 self.star_name = self.positional_names[-1] 1602 del self.positional_names[-1] 1603 1604 # Initialise default storage. 1605 # NOTE: This must be initialised separately due to the reliance on node 1606 # NOTE: visiting. 1607 1608 self.default_attrs = [] 1609 1610 # Initialise attribute usage. 1611 1612 if node is not None: 1613 for arg in argnames: 1614 1615 # Define attribute users. 1616 1617 self._define_attribute_user_for_name(node, arg) 1618 1619 # Caches. 1620 1621 self.localnames = None # cache for locals 1622 1623 # Add parameters to the namespace. 1624 1625 self._add_parameters(argnames) 1626 1627 # Image generation details. 1628 1629 self.dynamic = None 1630 self.location = None 1631 self.code_location = None 1632 self.code_body_location = None 1633 1634 # Program-related details. 1635 1636 self.blocks = None 1637 self.body_block = None 1638 1639 self.temp_usage = 0 1640 self.local_usage = 0 1641 self.all_local_usage = 0 1642 1643 def _add_parameters(self, argnames): 1644 1645 "Add 'argnames' to the namespace." 1646 1647 for name in argnames: 1648 self.set(name, Instance()) 1649 1650 for name, top_level in self._flattened_parameters(argnames): 1651 if not top_level: 1652 self.set(name, Instance()) 1653 1654 def _flattened_parameters(self, argnames, top_level=1): 1655 l = [] 1656 for name in argnames: 1657 if isinstance(name, tuple): 1658 l += self._flattened_parameters(name, 0) 1659 else: 1660 l.append((name, top_level)) 1661 return l 1662 1663 def __repr__(self): 1664 if self.location is not None: 1665 return "Function(%r, %s, %r, location=%r, code_location=%r)" % ( 1666 self.name, shortrepr(self.parent), self.argnames, self.location, self.code_location 1667 ) 1668 else: 1669 return "Function(%r, %s, %r)" % ( 1670 self.name, shortrepr(self.parent), self.argnames 1671 ) 1672 1673 def __shortrepr__(self): 1674 return "Function(%r, %s)" % ( 1675 self.name, shortrepr(self.parent) 1676 ) 1677 1678 def get_body_block(self): 1679 return self.body_block 1680 1681 def is_lambda(self): 1682 return self._is_lambda 1683 1684 # Defaults-related methods. 1685 1686 def store_default(self, attr_or_value): 1687 1688 """ 1689 Reserve space for defaults, set outside the function, potentially on a 1690 dynamic basis, using the 'attr_or_value'. 1691 """ 1692 1693 attr = Attr(None, self, None) 1694 self._set_using_attr(attr, attr_or_value) 1695 self.default_attrs.append(attr) 1696 1697 def make_dynamic(self): 1698 1699 "Return whether this function must be handled using a dynamic object." 1700 1701 if self.dynamic is None: 1702 for attr in self.default_attrs: 1703 if not attr.is_strict_constant() and self.dynamic_def: 1704 self.dynamic = 1 1705 self._make_dynamic() 1706 break 1707 else: 1708 self.dynamic = 0 1709 1710 return self.dynamic 1711 1712 is_dynamic = make_dynamic 1713 1714 def _make_dynamic(self): 1715 1716 "Where functions have dynamic defaults, add a context argument." 1717 1718 name = "<context>" 1719 self.argnames.insert(0, name) 1720 self.positional_names.insert(0, name) 1721 self.set(name, Instance()) 1722 1723 # Namespace-related methods. 1724 1725 def make_global(self, name): 1726 1727 "Declare 'name' as a global in the current namespace." 1728 1729 if name not in self.argnames and not self.has_key(name): 1730 self.globals.add(name) 1731 return 1 1732 else: 1733 return 0 1734 1735 def parameters(self): 1736 1737 """ 1738 Return a dictionary mapping parameter names to their position in the 1739 parameter list. 1740 """ 1741 1742 parameters = {} 1743 for i, name in enumerate(self.argnames): 1744 parameters[name] = i 1745 return parameters 1746 1747 def tuple_parameters(self, argnames=None): 1748 1749 """ 1750 Return a list of (position, parameter) entries corresponding to tuple 1751 parameters, where each parameter may either be a string or another such 1752 list of entries. 1753 """ 1754 1755 names = argnames or self.argnames 1756 1757 l = [] 1758 for i, name in enumerate(names): 1759 if isinstance(name, tuple): 1760 l.append((i, self.tuple_parameters(name))) 1761 elif argnames: 1762 l.append((i, name)) 1763 return l 1764 1765 def all_locals(self): 1766 1767 "Return a dictionary mapping names to local and parameter details." 1768 1769 return dict(self) 1770 1771 def locals(self): 1772 1773 "Return a dictionary mapping names to local details." 1774 1775 if self.localnames is None: 1776 self.localnames = {} 1777 self.localnames.update(self.all_locals()) 1778 for name in self.argnames: 1779 del self.localnames[name] 1780 return self.localnames 1781 1782 def is_method(self): 1783 1784 """ 1785 Return whether this function is a method explicitly defined in a class. 1786 """ 1787 1788 return isinstance(self.parent, Class) 1789 1790 def is_relocated(self, name): 1791 1792 """ 1793 Determine whether the given attribute 'name' is relocated for instances 1794 having this function as a method. 1795 """ 1796 1797 for cls in self.parent.descendants: 1798 if name in cls.relocated: 1799 return 1 1800 return 0 1801 1802 # Administrative methods. 1803 1804 def finalise(self, objtable): 1805 self.finalise_attributes() 1806 self.finalise_users(objtable) 1807 1808 def items_for_vacuum(self): 1809 return self.lambdas.items() 1810 1811 def vacuum_item(self, name): 1812 del self.lambdas[name] 1813 return 1 1814 1815 def finalise_attributes(self): 1816 1817 """ 1818 Make sure all attributes (locals) are fully defined. Note that locals 1819 are not attributes in the sense of class, module or instance attributes. 1820 Defaults are also finalised by this method. 1821 """ 1822 1823 if self.finalised: 1824 return 1825 1826 # Defaults. 1827 1828 for i, default in enumerate(self.default_attrs): 1829 default.position = i 1830 1831 # Parameters. 1832 1833 i = self._finalise_parameters() 1834 1835 if i is not None: 1836 nparams = i + 1 1837 else: 1838 nparams = 0 1839 1840 # Locals (and tuple parameter names). 1841 1842 i = None 1843 for i, attr in enumerate(self.locals().values()): 1844 attr.position = i + nparams 1845 1846 if i is not None: 1847 nothers = i + 1 1848 else: 1849 nothers = 0 1850 1851 self.local_usage = nothers 1852 self.all_local_usage = nparams + nothers 1853 self.finalised = 1 1854 1855 def _finalise_parameters(self): 1856 if not self.argnames: 1857 return None 1858 1859 for i, name in enumerate(self.argnames): 1860 self[name].position = i 1861 1862 return i 1863 1864 def finalise_users(self, objtable): 1865 1866 "Record the object types for generating guards." 1867 1868 # Visit each user and examine the attribute usage for each name. 1869 1870 for user in self.all_attribute_users: 1871 user._attrtypes = {} 1872 for name, usage in user._attrcombined.items(): 1873 user._attrtypes[name] = get_object_types_for_usage(usage, objtable, name, self.full_name()) 1874 1875 def as_instantiator(self): 1876 1877 "Make an instantiator function from a method, keeping all arguments." 1878 1879 function = Function(self.parent.name, self.parent.parent, self.argnames, self.defaults, 1880 self.has_star, self.has_dstar, self.dynamic_def, self.module) 1881 function.default_attrs = self.default_attrs 1882 return function 1883 1884 class UnresolvedName(NamespaceDict, Constant): 1885 1886 "A module, class or function which was mentioned but could not be imported." 1887 1888 def __init__(self, name, parent_name, module=None): 1889 NamespaceDict.__init__(self, module) 1890 self.name = name 1891 self.parent_name = parent_name 1892 self.parent = None 1893 1894 self.descendants = set() 1895 1896 def add_descendant(self, cls): 1897 self.descendants.add(cls) 1898 1899 def all_attributes(self): 1900 return {} 1901 1902 def all_attribute_names(self): 1903 return [] 1904 1905 all_class_attributes = class_attributes = instance_attributes = all_attributes 1906 all_class_attribute_names = class_attribute_names = instance_attribute_names = all_attribute_names 1907 1908 def __repr__(self): 1909 return "UnresolvedName(%r, %r)" % (self.name, self.parent_name) 1910 1911 __shortrepr__ = __repr__ 1912 1913 def full_name(self): 1914 if self.name is not None: 1915 return self.parent_name + "." + self.name 1916 else: 1917 return self.parent_name 1918 1919 class Module(NamespaceDict, Constant): 1920 1921 "An inspected module's core details." 1922 1923 def __init__(self, name, importer): 1924 NamespaceDict.__init__(self, self) 1925 self.name = name 1926 self.importer = importer 1927 self.parent = None 1928 1929 # Original location details. 1930 1931 self.astnode = None 1932 1933 # Complete lists of classes and functions. 1934 1935 self.all_objects = set() 1936 1937 # Keyword records. 1938 1939 self.keyword_names = set() 1940 1941 # Image generation details. 1942 1943 self.location = None 1944 self.code_location = None 1945 1946 # Program-related details. 1947 1948 self.blocks = None 1949 self.temp_usage = 0 1950 self.local_usage = 0 1951 self.all_local_usage = 0 1952 1953 def full_name(self): 1954 return self.name 1955 1956 def __repr__(self): 1957 if self.location is not None: 1958 return "Module(%r, location=%r)" % (self.name, self.location) 1959 else: 1960 return "Module(%r)" % self.name 1961 1962 def __shortrepr__(self): 1963 return "Module(%r)" % self.name 1964 1965 # Attribute methods. 1966 1967 "Return the module attribute names provided by the module." 1968 1969 module_attribute_names = NamespaceDict.keys 1970 1971 def module_attributes(self): 1972 1973 "Return a dictionary mapping names to module attributes." 1974 1975 return dict(self) 1976 1977 # Pre-made instances. 1978 1979 type_class = TypeClass("type") # details to be filled in later 1980 1981 # Class construction. 1982 1983 def get_class(name, parent, module, node): 1984 1985 """ 1986 Return a Class instance for the class with the given 'name', 'parent', 1987 'module' and 'node'. 1988 """ 1989 1990 if name == "type" and module.full_name() == "__builtins__": 1991 type_class.set_context(parent, module, node) 1992 return type_class 1993 else: 1994 return CommonClass(name, parent, module, node) 1995 1996 # vim: tabstop=4 expandtab shiftwidth=4