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 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 DataObject, DataValue, ReplaceableContext, PlaceholderContext 56 from micropython.common import AtLeast, InspectError 57 58 def shortrepr(obj): 59 if obj is None: 60 return repr(None) 61 else: 62 return obj.__shortrepr__() 63 64 # Mix-ins and abstract classes. 65 66 class Naming: 67 68 "A mix-in providing naming conveniences." 69 70 def full_name(self): 71 if self.name is not None: 72 return self.parent.full_name() + "." + self.name 73 else: 74 return self.parent.full_name() 75 76 class NamespaceDict: 77 78 "A mix-in providing dictionary methods." 79 80 def __init__(self, module=None): 81 self.module = module 82 self.namespace = {} 83 self.globals = set() 84 self.finalised = 0 85 86 # Attributes accessed on objects, potentially narrowing their types. 87 # Specific namespaces should define known names during initialisation. 88 # For example, functions can define names belonging to parameters. 89 90 # Attribute users, defining names which use attributes. 91 92 self.attribute_users = [{}] # stack of assignments 93 self.user_shelves = [] 94 self.loop_users = [{}] # stack of loop nodes 95 96 # Scope usage, indicating the origin of names. 97 98 self.scope_usage = [{}] # stack of scope usage 99 self.scope_shelves = [] 100 101 # Define attribute usage to identify active program sections. 102 # Attribute users are AST nodes defining names. 103 104 self.all_attribute_users = set() 105 106 # Attribute/name definition and access. 107 108 def __delitem__(self, name): 109 del self.namespace[name] 110 111 def has_key(self, name): 112 return self.namespace.has_key(name) 113 114 def keys(self): 115 return self.namespace.keys() 116 117 def values(self): 118 return self.namespace.values() 119 120 def items(self): 121 return self.namespace.items() 122 123 def __getitem__(self, name): 124 return self.namespace[name] 125 126 def get_using_node(self, name, node): 127 128 """ 129 Access the given 'name' through this namespace, making use of the module 130 and builtins namespaces if necessary, annotating the given 'node' with 131 the scope involved. 132 """ 133 134 attr, scope, full_name = self._get_with_scope(name) 135 136 if scope is not None: 137 node._scope = scope 138 self.note_scope(name, scope) 139 140 if full_name is not None: 141 self.use_specific_attribute(full_name, name) 142 143 return attr 144 145 def _get_with_scope(self, name, external=0): 146 147 module = self.module 148 builtins = module and module.builtins or None 149 importer = module and module.importer or None 150 151 # Constants. 152 153 if importer is not None and importer.predefined_constants.has_key(name): 154 return importer.get_predefined_constant(name), "constant", None 155 156 # Locals. 157 158 elif not external and self.has_key(name): 159 return self[name], "local", self.full_name() 160 161 # Globals. 162 163 elif module is not None and module is not self and module.has_key(name): 164 return module[name], "global", module.full_name() 165 166 # Builtins. 167 168 elif builtins is not None and builtins.has_key(name): 169 return builtins[name], "builtins", builtins.full_name() 170 171 # Unknown. 172 173 else: 174 return None, None, None 175 176 def get(self, name, default=None): 177 return self.namespace.get(name, default) 178 179 def __setitem__(self, name, value): 180 self.set(name, value) 181 182 def set(self, name, value, single_assignment=1): 183 184 """ 185 A more powerful set operation, making 'name' refer to 'value' whilst 186 indicating whether a 'single_assignment' (true by default) occurs in 187 this operation (or whether the operation covers potentially many 188 assignments in the lifetime of a program). 189 """ 190 191 if name in self.globals: 192 self.module.set(name, value, 0) 193 else: 194 self._set(name, value, single_assignment) 195 self.note_scope(name, "local") 196 197 def set_module(self, name, value): 198 199 """ 200 A specialised set operation, making 'name' refer to 'value' in the 201 context of making a module reference available in association with 202 'name' as part of the import of that module or a submodule of that 203 module. 204 """ 205 206 self._set(name, value, 1) 207 208 def _set(self, name, attr_or_value, single_assignment=1): 209 210 """ 211 The underlying set operation associating 'name' with the given 212 'attr_or_value'. 213 See: docs/assignment.txt 214 """ 215 216 # Add and/or obtain the namespace entry. 217 218 if not self.namespace.has_key(name): 219 self.namespace[name] = Attr(None, self, name) 220 221 attr = self.namespace[name] 222 self._set_using_attr(attr, attr_or_value, single_assignment) 223 224 def _set_using_attr(self, attr, attr_or_value, single_assignment=1): 225 226 # Handle attribute assignment as well as assignment of basic objects. 227 # Attempt to fix the context if not explicitly defined. 228 229 if isinstance(attr_or_value, Attr): 230 context_values = self.get_updated_context_values(attr_or_value.context_values) 231 else: 232 context_values = self.get_updated_context_values([self.get_context_and_value(attr_or_value)]) 233 234 attr.update(context_values, single_assignment) 235 236 def get_context_and_value(self, value): 237 238 "Return a context, value tuple for the given 'value'." 239 240 # Functions have a replaceable context. 241 242 if isinstance(value, Function): 243 return (ReplaceableContext, value) 244 245 # Classes use placeholder contexts which cannot be replaced but which 246 # do not communicate useful contextual information. 247 248 elif isinstance(value, Class): 249 return (PlaceholderContext, value) 250 251 # Other values employ themselves as the context. 252 253 else: 254 return (value, value) 255 256 def get_updated_context_values(self, context_values): 257 258 """ 259 Adapt the contexts found in the given 'context_values', returning a new 260 set. 261 See: docs/assignment.txt 262 """ 263 264 results = set() 265 266 for context, value in context_values: 267 268 # Set the context of instances to themselves. 269 270 if isinstance(value, Instance): 271 results.add((value, value)) 272 else: 273 results.add((context, value)) 274 275 return results 276 277 def make_global(self, name): 278 279 "Declare 'name' as a global in the current namespace." 280 281 if not self.namespace.has_key(name): 282 self.globals.add(name) 283 self.note_scope(name, "global") 284 return 1 285 else: 286 return 0 287 288 # Attribute positioning. 289 290 def attributes_as_list(self): 291 292 "Return the attributes in a list." 293 294 self.finalise_attributes() 295 l = [None] * len(self.keys()) 296 for attr in self.values(): 297 l[attr.position] = attr 298 return l 299 300 def finalise_attributes(self): 301 302 "Make sure all attributes are fully defined." 303 304 if self.finalised: 305 return 306 307 # The default action is to assign attribute positions sequentially. 308 309 for i, attr in enumerate(self.values()): 310 attr.position = i 311 312 self.finalised = 1 313 314 def unfinalise_attributes(self): 315 316 "Open attribute definitions to editing and subsequent finalisation." 317 318 self.finalised = 0 319 320 # Attribute usage methods. 321 322 def finalise_attribute_usage(self): 323 324 "Propagate attribute usage for the namespace to the importer." 325 326 module = self.module 327 importer = module and module.importer 328 329 if importer is not None: 330 for names in self.get_all_attribute_usage(): 331 importer.use_names(names, self.full_name()) 332 333 def get_all_attribute_usage(self): 334 335 """ 336 Return a set of all usage tuples for attributes used with the different 337 local names. 338 """ 339 340 usage = set() 341 for user in self.all_attribute_users: 342 for name, attrnames in user._attrnames.items(): 343 usage.add(tuple(attrnames)) 344 return usage 345 346 def use_attribute(self, name, attrname): 347 348 "Declare the usage on 'name' of the given 'attrname'." 349 350 return self._use_attribute(name, attrname) 351 352 def use_specific_attribute(self, objname, attrname): 353 354 "Declare the usage on 'objname' of the given 'attrname'." 355 356 self._use_specific_attribute(objname, attrname) 357 358 # These shadow various methods in the InspectedModule class, and provide 359 # implementations generally. 360 361 def _use_specific_attribute(self, objname, attrname): 362 363 """ 364 Note attribute usage specifically on 'objname' - an object which is 365 known at inspection time - or in the current unit if 'objname' is None, 366 nominating a specific attribute 'attrname'. 367 368 This bypasses attribute user mechanisms. 369 """ 370 371 from_name = self.full_name() 372 objname = objname or from_name 373 module = self.module 374 importer = module and module.importer 375 376 if importer is not None: 377 importer.use_specific_name(objname, attrname, from_name) 378 379 def _use_attribute(self, name, attrname): 380 381 """ 382 Indicate the use of the given 'name' in this namespace of an attribute 383 with the given 'attrname'. 384 """ 385 386 for users in (self.attribute_users[-1], self.loop_users[-1]): 387 388 # Add the usage to all current users. 389 390 if users.has_key(name): 391 for user in users[name]: 392 user._attrnames[name].add(attrname) 393 394 users = self.attribute_users[-1] 395 396 if users.has_key(name): 397 return users[name] 398 else: 399 return [] 400 401 def _define_attribute_user(self, node): 402 403 """ 404 Define 'node' as the user of attributes, indicating the point where the 405 user is defined. 406 """ 407 408 name = node.name 409 self._define_attribute_user_for_name(node, name) 410 411 def _define_attribute_user_for_name(self, node, name): 412 413 "Define 'node' as the user of attributes for the given 'name'." 414 415 users = self.attribute_users[-1] 416 417 # This node overrides previous definitions. 418 419 users[name] = set([node]) 420 421 # Record the attribute combinations for the name. 422 423 self._init_attribute_user_for_name(node, name) 424 425 # Propagate any loop usage forward to any redefinition of a name. 426 427 loop_users = self.loop_users[-1] 428 429 if loop_users.has_key(name): 430 for loop_user in loop_users[name]: 431 node._attrnames[name].update(loop_user._attrnames[name]) 432 del loop_users[name] 433 434 # Remember this user. 435 436 self.all_attribute_users.add(node) 437 438 def _init_attribute_user_for_name(self, node, name): 439 440 "Make sure that 'node' is initialised for 'name'." 441 442 if not hasattr(node, "_attrnames"): 443 node._attrnames = {} 444 445 node._attrnames[name] = set() 446 447 # Branch management methods. 448 449 def _new_branchpoint(self): 450 451 """ 452 Establish a new branchpoint where several control-flow branches diverge 453 and subsequently converge. 454 """ 455 456 self.user_shelves.append([]) 457 self.scope_shelves.append([]) 458 459 def _new_branch(self, loop_node=None): 460 461 """ 462 Establish a new control-flow branch, transferring attribute usage to 463 the new branch so that it may be augmented for each name locally. 464 465 If the optional 'loop_node' is given, add it as an active user to be 466 informed of attribute usage. 467 """ 468 469 # Retain a record of active users. 470 471 new_users = {} 472 new_users.update(self.attribute_users[-1]) 473 self.attribute_users.append(new_users) 474 475 # Where a loop is the cause of the branch, register the loop node as a 476 # user of each name so that attribute usage is also recorded for the 477 # loop. 478 479 loop_users = {} 480 loop_users.update(self.loop_users[-1]) 481 self.loop_users.append(loop_users) 482 483 if loop_node is not None: 484 for name in new_users.keys(): 485 if not loop_users.has_key(name): 486 loop_users[name] = set([loop_node]) 487 else: 488 loop_users[name] = loop_users[name].union([loop_node]) 489 self._init_attribute_user_for_name(loop_node, name) 490 491 # Retain a record of scope usage. 492 493 scope_usage = {} 494 scope_usage.update(self.scope_usage[-1]) 495 self.scope_usage.append(scope_usage) 496 497 def _abandon_branch(self): 498 pass 499 500 def _shelve_branch(self): 501 502 """ 503 Shelve the current control-flow branch, recording the attribute usage 504 for subsequent merging. If this branch should be abandoned, the usage 505 observations are still recorded but will not contribute to subsequent 506 observations after a merge. 507 """ 508 509 users = self.attribute_users.pop() 510 self.user_shelves[-1].append(users) 511 512 scope_usage = self.scope_usage.pop() 513 self.scope_shelves[-1].append(scope_usage) 514 515 def _merge_branches(self): 516 517 """ 518 Merge control-flow branches. This should find the users active within 519 each branch, which have been "shelved", and update the active users 520 dictionary with these contributions. 521 """ 522 523 # Combine the attribute users. This ensures that a list of users 524 # affected by attribute usage is maintained for the current branch. 525 526 users = self.attribute_users[-1] 527 new_users = {} 528 529 all_shelved_users = self.user_shelves.pop() 530 all_user_names = set() 531 532 # Find all the names defined by the branches. 533 534 for shelved_users in all_shelved_users: 535 all_user_names.update(shelved_users.keys()) 536 537 # Copy all definitions from the branches for the names, maintaining 538 # the existing users where a branch does not redefine a name. 539 540 for shelved_users in all_shelved_users: 541 for name in all_user_names: 542 543 if shelved_users.has_key(name): 544 nodes = shelved_users[name] 545 else: 546 nodes = users.get(name, set()) 547 548 if nodes: 549 if not new_users.has_key(name): 550 new_users[name] = set(nodes) 551 else: 552 new_users[name].update(nodes) 553 554 self.attribute_users[-1] = new_users 555 556 # Combine the scope usage. 557 558 scope_usage = self.scope_usage[-1] 559 new_scope_usage = {} 560 561 all_scope_usage = self.scope_shelves.pop() 562 all_scope_names = set() 563 564 # Find all the names for whom scope information has been defined. 565 566 for shelved_usage in all_scope_usage: 567 all_scope_names.update(shelved_usage.keys()) 568 569 for shelved_usage in all_scope_usage: 570 for name in all_scope_names: 571 572 # Find the recorded scope for the name. 573 574 if shelved_usage.has_key(name): 575 scope = shelved_usage[name] 576 elif scope_usage.has_key(name): 577 scope = scope_usage[name] 578 579 # If no scope is recorded, find a suitable external source. 580 581 else: 582 attr, scope, full_name = self._get_with_scope(name, external=1) 583 584 # Attempt to record the scope, testing for conflicts. 585 586 if scope: 587 if not new_scope_usage.has_key(name): 588 new_scope_usage[name] = scope 589 elif new_scope_usage[name] != scope: 590 raise InspectError("Scope conflict for %r: defined as both %s and %s." % (name, new_scope_usage[name], scope)) 591 592 # Scope usage methods. 593 594 def note_scope(self, name, scope): 595 596 "Note usage of 'name' from the given 'scope' in the current namespace." 597 598 self.scope_usage[-1][name] = scope 599 600 def used_in_scope(self, name, scope): 601 602 """ 603 Return whether 'name' is used from the given 'scope' in the current 604 namespace. 605 """ 606 607 scope_usage = self.scope_usage[-1] 608 return scope_usage.get(name) == scope 609 610 # Program data structures. 611 612 class Attr: 613 614 "An attribute entry having a context." 615 616 def __init__(self, position, parent, name): 617 618 """ 619 Initialise the attribute with the given 'position' within the collection 620 of attributes of its 'parent', indicating its 'name'. 621 """ 622 623 self.position = position 624 self.parent = parent 625 self.name = name 626 627 # Possible values. 628 629 self.context_values = set() 630 631 # Number of assignments per name. 632 633 self.assignments = None 634 635 # Value-related methods. 636 637 def get_contexts(self): 638 return [c for (c, v) in self.context_values] 639 640 def get_values(self): 641 return [v for (c, v) in self.context_values] 642 643 def get_context(self): 644 if len(self.context_values) == 1: 645 return self.get_contexts()[0] 646 else: 647 return None 648 649 def get_value(self): 650 if len(self.context_values) == 1: 651 return self.get_values()[0] 652 else: 653 return None 654 655 def update(self, context_values, single_assignment): 656 657 """ 658 Update the attribute, adding the 'context_values' provided to the 659 known details associated with the attribute, changing the number of 660 assignments according to the 'single_assignment' status of the 661 operation, where a true value indicates that only one assignment is 662 associated with the update, and a false value indicates that potentially 663 many assignments may be involved. 664 """ 665 666 if self.assignments is None: 667 if single_assignment: 668 self.assignments = 1 669 else: 670 self.assignments = AtLeast(1) 671 else: 672 if single_assignment: 673 self.assignments += 1 674 else: 675 self.assignments += AtLeast(1) 676 677 self.context_values.update(context_values) 678 679 def is_constant(self): 680 681 """ 682 Return whether this attribute references something that can be regarded 683 as being constant within a particular scope. 684 """ 685 686 return self.assignments == 1 687 688 def is_strict_constant(self): 689 690 """ 691 Return whether this attribute references something that can be regarded 692 as being constant. 693 """ 694 695 value = self.get_value() 696 return not (value is None or isinstance(value, Instance)) 697 698 def is_static_attribute(self): 699 700 """ 701 Return whether this attribute is defined on a fixed/static object such 702 as a class or a module. 703 """ 704 705 return isinstance(self.parent, (Class, Module)) 706 707 def defines_ambiguous_class(self): 708 709 "Return whether this attribute defines more than one class." 710 711 if self.assignments > 1: 712 have_class = 0 713 for obj in self.get_values(): 714 if isinstance(obj, Class): 715 if have_class: 716 return 1 717 have_class = 1 718 719 return 0 720 721 def defined_within_hierarchy(self): 722 723 """ 724 Return whether the parent and context of the attribute belong to the 725 same class hierarchy. 726 """ 727 728 # Must be defined within a class. 729 730 if isinstance(self.parent, Class): 731 732 # To be sure, all contexts must be classes and be the same as the 733 # parent, or be a superclass of the parent, or be a subclass of the 734 # parent. 735 736 for context in self.get_contexts(): 737 if not ( 738 isinstance(context, Class) and ( 739 context is self.parent or 740 context.has_subclass(self.parent) or 741 self.parent.has_subclass(context)) 742 ): 743 return 0 744 745 return 1 746 747 # Instance attributes are not defined within a hierarchy. 748 749 else: 750 return 0 751 752 def defined_outside_hierarchy(self): 753 754 """ 755 Return whether the parent and context of the attribute never belong to 756 the same class hierarchy. 757 """ 758 759 # Must be defined within a class. 760 761 if isinstance(self.parent, Class): 762 763 # To be sure, all contexts must be classes and be the same as the 764 # parent, or be a superclass of the parent, or be a subclass of the 765 # parent. 766 767 for context in self.get_contexts(): 768 if not ( 769 isinstance(context, Class) and not ( 770 context is self.parent or 771 context.has_subclass(self.parent) or 772 self.parent.has_subclass(context)) 773 ): 774 return 0 775 776 return 1 777 778 # Instance attributes are not defined within a hierarchy. 779 780 else: 781 return 0 782 783 def __repr__(self): 784 return "Attr(%r, %s, %r) # {[%s] (%r)}" % ( 785 self.position, shortrepr(self.parent), self.name, 786 self._context_values_str(), self.assignments 787 ) 788 789 def __shortrepr__(self): 790 return "Attr(%r, %s, %r)" % ( 791 self.position, shortrepr(self.parent), self.name 792 ) 793 794 def _context_values_str(self): 795 l = [] 796 for (c, v) in self.context_values: 797 l.append("(c=%s, v=%s)" % (shortrepr(c), shortrepr(v))) 798 return ", ".join(l) 799 800 # Instances are special in that they need to be wrapped together with context in 801 # a running program, but they are not generally constant. 802 803 class Instance: 804 805 "A placeholder indicating the involvement of an instance." 806 807 def __init__(self): 808 self.parent = None 809 810 # Image generation details. 811 812 self.location = None 813 814 def __repr__(self): 815 return "Instance()" 816 817 __shortrepr__ = __repr__ 818 819 class Constant: 820 821 "A superclass for all constant or context-free structures." 822 823 pass 824 825 # Data objects appearing in programs before run-time. 826 827 class Const(Constant, Instance): 828 829 "A constant object with no context." 830 831 def __init__(self, value): 832 Instance.__init__(self) 833 self.value = value 834 835 def get_value(self): 836 return self.value 837 838 def __repr__(self): 839 if self.location is not None: 840 return "Const(%r, location=%r)" % (self.value, self.location) 841 else: 842 return "Const(%r)" % self.value 843 844 __shortrepr__ = __repr__ 845 846 # Support constants as dictionary keys in order to build constant tables. 847 848 def __eq__(self, other): 849 return other is not None and self.value == other.value and self.value.__class__ is other.value.__class__ 850 851 def __hash__(self): 852 return hash(self.value) 853 854 def value_type_name(self): 855 return "__builtins__." + self.value.__class__.__name__ 856 857 class Class(NamespaceDict, Naming, Constant): 858 859 "An inspected class." 860 861 def __init__(self, name, parent, module=None, node=None): 862 863 """ 864 Initialise the class with the given 'name', 'parent' object, optional 865 'module' and optional AST 'node'. 866 """ 867 868 NamespaceDict.__init__(self, module) 869 self.name = name 870 self.parent = parent 871 self.astnode = node 872 node._def = self 873 874 # Superclasses, descendants and attributes. 875 876 self.bases = [] 877 self.descendants = set() 878 self.instattr = set() # instance attributes 879 self.relocated = set() # attributes which do not have the same 880 # position as those of the same name in 881 # some superclasses 882 883 # Caches. 884 885 self.reset_caches() 886 887 # Image generation details. 888 889 self.location = None 890 self.code_location = None 891 self.code_body_location = None # corresponds to the instantiator 892 893 self.instantiator = None 894 self.instance_template_location = None # for creating instances at run-time 895 896 # Program-related details. 897 898 self.blocks = None 899 self.temp_usage = 0 900 self.local_usage = 0 901 self.all_local_usage = 0 902 903 # Add this class to its attributes. 904 905 self.set("__class__", self) 906 907 def reset_caches(self): 908 909 "Reset the caches." 910 911 self.all_instattr = None # cache for instance_attributes 912 self.all_instattr_names = None # from all_instattr 913 self.all_classattr = None # cache for all_class_attributes 914 self.all_classattr_names = None # from all_classattr 915 self.allattr = None # cache for all_attributes 916 self.allattr_names = None # from allattr 917 918 def __repr__(self): 919 if self.location is not None: 920 return "Class(%r, %s, location=%r)" % (self.name, shortrepr(self.parent), self.location) 921 else: 922 return "Class(%r, %s)" % (self.name, shortrepr(self.parent)) 923 924 def __shortrepr__(self): 925 return "Class(%r, %s)" % (self.name, shortrepr(self.parent)) 926 927 def get_body_block(self): 928 return self.get_instantiator().blocks[0] 929 930 # Namespace-related methods. 931 932 def get_updated_context_values(self, context_values): 933 934 """ 935 Adapt the contexts found in the given 'context_values', returning a new 936 set. 937 See: docs/assignment.txt 938 """ 939 940 results = set() 941 942 for context, value in context_values: 943 944 # Change the ownership of functions. 945 946 if context is ReplaceableContext and value is not None and isinstance(value, Function): 947 results.add((self, value)) 948 else: 949 results.add((context, value)) 950 951 return NamespaceDict.get_updated_context_values(self, results) 952 953 def finalise_attributes(self): 954 955 "Make sure that all attributes are fully defined." 956 957 if self.finalised: 958 return 959 960 self.finalise_class_attributes() 961 self.finalise_instance_attributes() 962 self.finalised = 1 963 964 def unfinalise_attributes(self): 965 966 "Open attribute definitions to editing and subsequent finalisation." 967 968 self.reset_caches() 969 self.finalised = 0 970 971 # Convenience methods for accessing functions and methods. 972 973 def get_instantiator(self): 974 975 "Return a function which can be used to instantiate the class." 976 977 if self.instantiator is None: 978 self.instantiator = self.get_init_method().as_instantiator() 979 return self.instantiator 980 981 def get_init_method(self): 982 return self.all_class_attributes()["__init__"].get_value() 983 984 # Class-specific methods. 985 986 def add_base(self, base): 987 self.bases.append(base) 988 base.add_descendant(self) 989 990 def add_instance_attribute(self, name): 991 self.instattr.add(name) 992 993 def add_descendant(self, cls): 994 self.descendants.add(cls) 995 for base in self.bases: 996 base.add_descendant(cls) 997 998 def has_subclass(self, other): 999 return other in self.descendants 1000 1001 def all_descendants(self): 1002 d = {} 1003 for cls in self.descendants: 1004 d[cls.full_name()] = cls 1005 return d 1006 1007 "Return the attribute names provided by this class only." 1008 1009 class_attribute_names = NamespaceDict.keys 1010 1011 def class_attributes(self): 1012 1013 "Return class attributes provided by this class only." 1014 1015 return dict(self) 1016 1017 def all_class_attribute_names(self): 1018 1019 "Return the attribute names provided by classes in this hierarchy." 1020 1021 if self.all_classattr_names is None: 1022 self.all_class_attributes() 1023 self.all_classattr_names = self.all_classattr.keys() 1024 return self.all_classattr_names 1025 1026 def all_class_attributes(self): 1027 1028 "Return all class attributes, indicating the class which provides them." 1029 1030 self.finalise_class_attributes() 1031 return self.all_classattr 1032 1033 def finalise_class_attributes(self): 1034 1035 "Make sure that the class attributes are fully defined." 1036 1037 if self.all_classattr is None: 1038 self.all_classattr = {} 1039 clsattr = {} 1040 1041 # Record provisional position information for attributes of this 1042 # class. 1043 1044 for name in self.class_attributes().keys(): 1045 clsattr[name] = set() # position not yet defined 1046 1047 reversed_bases = self.bases[:] 1048 reversed_bases.reverse() 1049 1050 # For the bases in reverse order, acquire class attribute details. 1051 1052 for cls in reversed_bases: 1053 for name, attr in cls.all_class_attributes().items(): 1054 self.all_classattr[name] = attr 1055 1056 # Record previous attribute information. 1057 1058 if clsattr.has_key(name): 1059 clsattr[name].add(attr.position) 1060 1061 # Record class attributes provided by this class and its bases, 1062 # along with their positions. 1063 1064 self.all_classattr.update(self.class_attributes()) 1065 1066 if clsattr: 1067 for i, name in enumerate(self._get_position_list(clsattr)): 1068 self.all_classattr[name].position = i 1069 1070 return self.all_classattr 1071 1072 def instance_attribute_names(self): 1073 1074 "Return the instance attribute names provided by the class." 1075 1076 if self.all_instattr_names is None: 1077 self.instance_attributes() 1078 return self.all_instattr_names 1079 1080 def instance_attributes(self): 1081 1082 "Return instance-only attributes for instances of this class." 1083 1084 self.finalise_instance_attributes() 1085 return self.all_instattr 1086 1087 def finalise_instance_attributes(self): 1088 1089 "Make sure that the instance attributes are fully defined." 1090 1091 # Cache the attributes by converting the positioned attributes into a 1092 # dictionary. 1093 1094 if self.all_instattr is None: 1095 self.all_instattr = self._get_attributes() 1096 self.all_instattr_names = self.all_instattr.keys() 1097 1098 return self.all_instattr 1099 1100 def _get_attributes(self): 1101 1102 """ 1103 Return a dictionary mapping names to Attr instances incorporating 1104 information about their positions in the final instance structure. 1105 """ 1106 1107 instattr = {} 1108 1109 # Record provisional position information for attributes of this 1110 # instance. 1111 1112 for name in self.instattr: 1113 instattr[name] = set() # position not yet defined 1114 1115 reversed_bases = self.bases[:] 1116 reversed_bases.reverse() 1117 1118 # For the bases in reverse order, acquire instance attribute 1119 # details. 1120 1121 for cls in reversed_bases: 1122 for name, attr in cls.instance_attributes().items(): 1123 1124 # Record previous attribute information. 1125 1126 if instattr.has_key(name): 1127 instattr[name].add(attr.position) 1128 else: 1129 instattr[name] = set([attr.position]) 1130 1131 # Build the dictionary of attributes using the existing positions known 1132 # for each name. 1133 1134 d = {} 1135 for i, name in enumerate(self._get_position_list(instattr)): 1136 d[name] = Attr(i, Instance(), name) 1137 return d 1138 1139 def _get_position_list(self, positions): 1140 1141 """ 1142 Return a list of attribute names for the given 'positions' mapping from 1143 names to positions, indicating the positions of the attributes in the 1144 final instance structure. 1145 """ 1146 1147 position_items = positions.items() 1148 namearray = [None] * len(position_items) 1149 1150 # Get the positions in ascending order of list size, with lists 1151 # of the same size ordered according to their smallest position 1152 # value. 1153 1154 position_items.sort(self._cmp_positions) 1155 1156 # Get the names in position order. 1157 1158 held = [] 1159 1160 for name, pos in position_items: 1161 pos = list(pos) 1162 pos.sort() 1163 if pos and pos[0] < len(namearray) and namearray[pos[0]] is None: 1164 namearray[pos[0]] = name 1165 else: 1166 if pos: 1167 self.relocated.add(name) 1168 held.append((name, pos)) 1169 1170 for i, attr in enumerate(namearray): 1171 if attr is None: 1172 name, pos = held.pop() 1173 namearray[i] = name 1174 1175 return namearray 1176 1177 def _cmp_positions(self, a, b): 1178 1179 "Compare name plus position list operands 'a' and 'b'." 1180 1181 name_a, list_a = a 1182 name_b, list_b = b 1183 if len(list_a) < len(list_b): 1184 return -1 1185 elif len(list_a) > len(list_b): 1186 return 1 1187 elif not list_a: 1188 return 0 1189 else: 1190 return cmp(min(list_a), min(list_b)) 1191 1192 def all_attribute_names(self): 1193 1194 """ 1195 Return the names of all attributes provided by instances of this class. 1196 """ 1197 1198 self.allattr_names = self.allattr_names or self.all_attributes().keys() 1199 return self.allattr_names 1200 1201 def all_attributes(self): 1202 1203 """ 1204 Return all attributes for an instance, indicating either the class which 1205 provides them or that the instance itself provides them. 1206 """ 1207 1208 if self.allattr is None: 1209 self.allattr = {} 1210 self.allattr.update(self.all_class_attributes()) 1211 for name, attr in self.instance_attributes().items(): 1212 if self.allattr.has_key(name): 1213 print "Instance attribute %r in %r overrides class attribute." % (name, self) 1214 self.allattr[name] = attr 1215 return self.allattr 1216 1217 class Function(NamespaceDict, Naming, Constant): 1218 1219 "An inspected function." 1220 1221 def __init__(self, name, parent, argnames, defaults, has_star, has_dstar, 1222 dynamic_def=0, module=None, node=None): 1223 1224 """ 1225 Initialise the function with the given 'name', 'parent', list of 1226 'argnames', list of 'defaults', the 'has_star' flag (indicating the 1227 presence of a * parameter), the 'has_dstar' flag (indicating the 1228 presence of a ** parameter), optional 'module', and optional AST 'node'. 1229 """ 1230 1231 NamespaceDict.__init__(self, module) 1232 self.name = name 1233 self.parent = parent 1234 self.argnames = argnames 1235 self.defaults = defaults 1236 self.has_star = has_star 1237 self.has_dstar = has_dstar 1238 self.dynamic_def = dynamic_def 1239 self.astnode = node 1240 node._def = self 1241 1242 # Initialise the positional names. 1243 1244 self.positional_names = self.argnames[:] 1245 if has_dstar: 1246 self.dstar_name = self.positional_names[-1] 1247 del self.positional_names[-1] 1248 if has_star: 1249 self.star_name = self.positional_names[-1] 1250 del self.positional_names[-1] 1251 1252 # Initialise default storage. 1253 # NOTE: This must be initialised separately due to the reliance on node 1254 # NOTE: visiting. 1255 1256 self.default_attrs = [] 1257 1258 # Initialise attribute usage. 1259 1260 for arg in argnames: 1261 1262 # Define attribute users. 1263 1264 if node is not None: 1265 self._define_attribute_user_for_name(node, arg) 1266 1267 # Or just record the usage. 1268 1269 else: 1270 self.attributes_used[-1][arg] = set() 1271 1272 # Caches. 1273 1274 self.localnames = None # cache for locals 1275 1276 # Add parameters to the namespace. 1277 1278 self._add_parameters(argnames) 1279 1280 # Image generation details. 1281 1282 self.dynamic = None 1283 self.location = None 1284 self.code_location = None 1285 self.code_body_location = None 1286 1287 # Program-related details. 1288 1289 self.blocks = None 1290 self.body_block = None 1291 1292 self.temp_usage = 0 1293 self.local_usage = 0 1294 self.all_local_usage = 0 1295 1296 def _add_parameters(self, argnames): 1297 for name in argnames: 1298 if isinstance(name, tuple): 1299 self._add_parameters(name) 1300 else: 1301 self.set(name, Instance()) 1302 1303 def __repr__(self): 1304 if self.location is not None: 1305 return "Function(%r, %s, %r, location=%r, code_location=%r)" % ( 1306 self.name, shortrepr(self.parent), self.argnames, self.location, self.code_location 1307 ) 1308 else: 1309 return "Function(%r, %s, %r)" % ( 1310 self.name, shortrepr(self.parent), self.argnames 1311 ) 1312 1313 def __shortrepr__(self): 1314 return "Function(%r, %s)" % ( 1315 self.name, shortrepr(self.parent) 1316 ) 1317 1318 def get_body_block(self): 1319 return self.body_block 1320 1321 # Defaults-related methods. 1322 1323 def store_default(self, attr_or_value): 1324 1325 """ 1326 Reserve space for defaults, set outside the function, potentially on a 1327 dynamic basis, using the 'attr_or_value'. 1328 """ 1329 1330 attr = Attr(None, self, None) 1331 self._set_using_attr(attr, attr_or_value) 1332 self.default_attrs.append(attr) 1333 1334 def make_dynamic(self): 1335 1336 "Return whether this function must be handled using a dynamic object." 1337 1338 if self.dynamic is None: 1339 for attr in self.default_attrs: 1340 if not attr.is_strict_constant() and self.dynamic_def: 1341 self.dynamic = 1 1342 self._make_dynamic() 1343 break 1344 else: 1345 self.dynamic = 0 1346 1347 return self.dynamic 1348 1349 is_dynamic = make_dynamic 1350 1351 def _make_dynamic(self): 1352 1353 "Where functions have dynamic defaults, add a context argument." 1354 1355 name = "<context>" 1356 self.argnames.insert(0, name) 1357 self.positional_names.insert(0, name) 1358 self.set(name, Instance()) 1359 1360 # Namespace-related methods. 1361 1362 def make_global(self, name): 1363 1364 "Declare 'name' as a global in the current namespace." 1365 1366 if name not in self.argnames and not self.has_key(name): 1367 self.globals.add(name) 1368 return 1 1369 else: 1370 return 0 1371 1372 def parameters(self): 1373 1374 """ 1375 Return a dictionary mapping parameter names to their position in the 1376 parameter list. 1377 """ 1378 1379 parameters = {} 1380 for i, name in enumerate(self.argnames): 1381 parameters[name] = i 1382 return parameters 1383 1384 def all_locals(self): 1385 1386 "Return a dictionary mapping names to local and parameter details." 1387 1388 return dict(self) 1389 1390 def locals(self): 1391 1392 "Return a dictionary mapping names to local details." 1393 1394 if self.localnames is None: 1395 self.localnames = {} 1396 self.localnames.update(self.all_locals()) 1397 for name in self.argnames: 1398 del self.localnames[name] 1399 return self.localnames 1400 1401 def is_method(self): 1402 1403 """ 1404 Return whether this function is a method explicitly defined in a class. 1405 """ 1406 1407 return isinstance(self.parent, Class) 1408 1409 def is_relocated(self, name): 1410 1411 """ 1412 Determine whether the given attribute 'name' is relocated for instances 1413 having this function as a method. 1414 """ 1415 1416 for cls in self.parent.descendants: 1417 if name in cls.relocated: 1418 return 1 1419 return 0 1420 1421 def finalise_attributes(self): 1422 1423 """ 1424 Make sure all attributes (locals) are fully defined. Note that locals 1425 are not attributes in the sense of class, module or instance attributes. 1426 Defaults are also finalised by this method. 1427 """ 1428 1429 if self.finalised: 1430 return 1431 1432 # Defaults. 1433 1434 for i, default in enumerate(self.default_attrs): 1435 default.position = i 1436 1437 # Locals. 1438 1439 i = None 1440 for i, name in enumerate(self.argnames): 1441 self[name].position = i 1442 1443 if i is not None: 1444 nparams = i + 1 1445 else: 1446 nparams = 0 1447 1448 i = None 1449 for i, attr in enumerate(self.locals().values()): 1450 attr.position = i + nparams 1451 1452 if i is not None: 1453 nothers = i + 1 1454 else: 1455 nothers = 0 1456 1457 self.local_usage = nothers 1458 self.all_local_usage = nparams + nothers 1459 self.finalised = 1 1460 1461 def as_instantiator(self): 1462 1463 "Make an instantiator function from a method, keeping all arguments." 1464 1465 function = Function(self.parent.name, self.parent.parent, self.argnames, self.defaults, 1466 self.has_star, self.has_dstar, self.dynamic_def, self.module, self.astnode) 1467 function.default_attrs = self.default_attrs 1468 return function 1469 1470 class UnresolvedName(NamespaceDict, Constant): 1471 1472 "A module, class or function which was mentioned but could not be imported." 1473 1474 def __init__(self, name, parent_name, module=None): 1475 NamespaceDict.__init__(self, module) 1476 self.name = name 1477 self.parent_name = parent_name 1478 self.parent = None 1479 1480 self.descendants = set() 1481 1482 def add_descendant(self, cls): 1483 self.descendants.add(cls) 1484 1485 def all_class_attributes(self): 1486 return {} 1487 1488 def instance_attributes(self): 1489 return {} 1490 1491 def __repr__(self): 1492 return "UnresolvedName(%r, %r)" % (self.name, self.parent_name) 1493 1494 __shortrepr__ = __repr__ 1495 1496 def full_name(self): 1497 if self.name is not None: 1498 return self.parent_name + "." + self.name 1499 else: 1500 return self.parent_name 1501 1502 class Module(NamespaceDict, Constant): 1503 1504 "An inspected module's core details." 1505 1506 def __init__(self, name, importer): 1507 NamespaceDict.__init__(self, self) 1508 self.name = name 1509 self.importer = importer 1510 self.parent = None 1511 1512 # Original location details. 1513 1514 self.astnode = None 1515 1516 # Complete lists of classes and functions. 1517 1518 self.all_objects = set() 1519 1520 # Keyword records. 1521 1522 self.keyword_names = set() 1523 1524 # Image generation details. 1525 1526 self.location = None 1527 self.code_location = None 1528 1529 # Program-related details. 1530 1531 self.blocks = None 1532 self.temp_usage = 0 1533 self.local_usage = 0 1534 self.all_local_usage = 0 1535 1536 def full_name(self): 1537 return self.name 1538 1539 def __repr__(self): 1540 if self.location is not None: 1541 return "Module(%r, location=%r)" % (self.name, self.location) 1542 else: 1543 return "Module(%r)" % self.name 1544 1545 def __shortrepr__(self): 1546 return "Module(%r)" % self.name 1547 1548 # Attribute methods. 1549 1550 "Return the module attribute names provided by the module." 1551 1552 module_attribute_names = NamespaceDict.keys 1553 1554 def module_attributes(self): 1555 1556 "Return a dictionary mapping names to module attributes." 1557 1558 return dict(self) 1559 1560 # vim: tabstop=4 expandtab shiftwidth=4