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