1 #!/usr/bin/env python 2 3 """ 4 Data classes. 5 6 Copyright (C) 2007, 2008, 2009 Paul Boddie <paul@boddie.org.uk> 7 8 This program is free software; you can redistribute it and/or modify it under 9 the terms of the GNU General Public License as published by the Free Software 10 Foundation; either version 3 of the License, or (at your option) any later 11 version. 12 13 This program is distributed in the hope that it will be useful, but WITHOUT 14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 16 details. 17 18 You should have received a copy of the GNU General Public License along with 19 this program. If not, see <http://www.gnu.org/licenses/>. 20 21 -------- 22 23 The central data structure classes in this module are the following: 24 25 * Class 26 * Function 27 * Module 28 29 All of the above support the Naming interface either explicitly or through 30 general conformance, meaning that all can be asked to provide their 'full_name' 31 using the method of that name. 32 33 Additionally, all of the above also support a dictionary interface in order to 34 access names within their defined scopes. Specific methods also exist in order 35 to distinguish between certain kinds of attributes: 36 37 * Class: class_attributes, all_class_attributes, instance_attributes, all_attributes 38 * Function: parameters, locals, all_locals 39 * Module: module_attributes 40 41 These specific methods are useful in certain situations. 42 43 The above classes also provide an 'astnode' attribute, indicating the AST node 44 where each such object is defined. 45 """ 46 47 from micropython.program import DataObject, DataValue, ReplaceableContext, PlaceholderContext 48 49 def shortrepr(obj): 50 if obj is None: 51 return repr(None) 52 else: 53 return obj.__shortrepr__() 54 55 # Special representations. 56 57 class AtLeast: 58 59 "A special representation for numbers of a given value or greater." 60 61 def __init__(self, count): 62 self.count = count 63 64 def __eq__(self, other): 65 return 0 66 67 __lt__ = __le__ = __eq__ 68 69 def __ne__(self, other): 70 return 1 71 72 def __gt__(self, other): 73 if isinstance(other, AtLeast): 74 return 0 75 else: 76 return self.count > other 77 78 def __ge__(self, other): 79 if isinstance(other, AtLeast): 80 return 0 81 else: 82 return self.count >= other 83 84 def __iadd__(self, other): 85 if isinstance(other, AtLeast): 86 self.count += other.count 87 else: 88 self.count += other 89 return self 90 91 def __radd__(self, other): 92 if isinstance(other, AtLeast): 93 return AtLeast(self.count + other.count) 94 else: 95 return AtLeast(self.count + other) 96 97 def __repr__(self): 98 return "AtLeast(%r)" % self.count 99 100 # Mix-ins and abstract classes. 101 102 class Naming: 103 104 "A mix-in providing naming conveniences." 105 106 def full_name(self): 107 if self.name is not None: 108 return self.parent.full_name() + "." + self.name 109 else: 110 return self.parent.full_name() 111 112 class NamespaceDict: 113 114 "A mix-in providing dictionary methods." 115 116 def __init__(self, module=None): 117 self.namespace = {} 118 self.globals = set() 119 self.module = module 120 self.finalised = 0 121 122 # Attributes accessed on objects, potentially narrowing their types. 123 # Specific namespaces should define known names during initialisation. 124 # For example, functions can define names belonging to parameters. 125 126 self.attributes_used = [{}] # stack of usage 127 self.attribute_shelves = [] # stack of unmerged definitions 128 self.attribute_users = [{}] # stack of assignments 129 self.all_attributes_used = [] 130 131 # Attribute/name definition and access. 132 133 def __delitem__(self, name): 134 del self.namespace[name] 135 136 def has_key(self, name): 137 return self.namespace.has_key(name) 138 139 def keys(self): 140 return self.namespace.keys() 141 142 def values(self): 143 return self.namespace.values() 144 145 def items(self): 146 return self.namespace.items() 147 148 def __getitem__(self, name): 149 return self.namespace[name] 150 151 def get(self, name, default=None): 152 return self.namespace.get(name, default) 153 154 def __setitem__(self, name, value): 155 self.set(name, value) 156 157 def set(self, name, value, single_assignment=1): 158 159 """ 160 A more powerful set operation, making 'name' refer to 'value' whilst 161 indicating whether a 'single_assignment' (true by default) occurs in 162 this operation (or whether the operation covers potentially many 163 assignments in the lifetime of a program). 164 """ 165 166 if name in self.globals: 167 self.module.set(name, value, 0) 168 else: 169 self._set(name, value, single_assignment) 170 171 def set_module(self, name, value): 172 173 """ 174 A specialised set operation, making 'name' refer to 'value' in the 175 context of making a module reference available in association with 176 'name' as part of the import of that module or a submodule of that 177 module. 178 """ 179 180 self._set(name, value, 1) 181 182 def _set(self, name, attr_or_value, single_assignment=1): 183 184 """ 185 The underlying set operation associating 'name' with the given 186 'attr_or_value'. 187 See: docs/assignment.txt 188 """ 189 190 # Add and/or obtain the namespace entry. 191 192 if not self.namespace.has_key(name): 193 self.namespace[name] = Attr(None, self, name) 194 195 attr = self.namespace[name] 196 197 # Handle attribute assignment as well as assignment of basic objects. 198 # Attempt to fix the context if not explicitly defined. 199 200 if isinstance(attr_or_value, Attr): 201 context_values = self.get_updated_context_values(attr_or_value.context_values) 202 else: 203 context_values = self.get_updated_context_values([self.get_context_and_value(attr_or_value)]) 204 205 attr.update(context_values, single_assignment) 206 207 def get_context_and_value(self, value): 208 209 "Return a context, value tuple for the given 'value'." 210 211 # Functions have a replaceable context. 212 213 if isinstance(value, Function): 214 return (ReplaceableContext, value) 215 216 # Classes use placeholder contexts which cannot be replaced but which 217 # do not communicate useful contextual information. 218 219 elif isinstance(value, Class): 220 return (PlaceholderContext, value) 221 222 # Other values employ themselves as the context. 223 224 else: 225 return (value, value) 226 227 def get_updated_context_values(self, context_values): 228 229 """ 230 Adapt the contexts found in the given 'context_values', returning a new 231 set. 232 See: docs/assignment.txt 233 """ 234 235 results = set() 236 237 for context, value in context_values: 238 239 # Set the context of instances to themselves. 240 241 if isinstance(value, Instance): 242 results.add((value, value)) 243 else: 244 results.add((context, value)) 245 246 return results 247 248 def make_global(self, name): 249 if not self.namespace.has_key(name): 250 self.globals.add(name) 251 return 1 252 else: 253 return 0 254 255 # Attribute positioning. 256 257 def attributes_as_list(self): 258 259 "Return the attributes in a list." 260 261 self.finalise_attributes() 262 l = [None] * len(self.keys()) 263 for attr in self.values(): 264 l[attr.position] = attr 265 return l 266 267 def finalise_attributes(self): 268 269 "Make sure all attributes are fully defined." 270 271 if self.finalised: 272 return 273 274 # The default action is to assign attribute positions sequentially. 275 276 for i, attr in enumerate(self.values()): 277 attr.position = i 278 279 self.finalised = 1 280 281 def unfinalise_attributes(self): 282 283 "Open attribute definitions to editing and subsequent finalisation." 284 285 self.finalised = 0 286 287 # Attribute usage methods. 288 289 def get_all_attribute_usage(self): 290 291 """ 292 Return a set of all usage tuples for attributes used with the different 293 local names. 294 """ 295 296 usage = set() 297 for names in self.all_attributes_used: 298 usage.add(tuple(names)) 299 return usage 300 301 def use_attribute(self, name, attrname): 302 return self._use_attribute(name, attrname) 303 304 # These shadow various methods in the InspectedModule class, and provide 305 # implementations generally. 306 307 def _use_attribute(self, name, attrname): 308 309 """ 310 Indicate the use on the given 'name' in this namespace of an attribute 311 with the given 'attrname'. 312 """ 313 314 defs = self.attributes_used[-1] 315 users = self.attribute_users[-1] 316 317 # Permit the unforeseen definition of names since some names are likely 318 # to be defined by things (such as class definitions) which will not 319 # require access optimisations, but which still need to be monitored. 320 321 if not defs.has_key(name): 322 defs[name] = set() 323 324 defs[name].add(attrname) 325 return defs[name] 326 327 def _define_attribute_user(self, node): 328 329 """ 330 Define 'node' as the user of attributes, indicating the point where the 331 user is defined. 332 """ 333 334 name = node.name 335 self._define_attribute_user_for_name(node, name) 336 337 def _define_attribute_user_for_name(self, node, name): 338 339 "Define 'node' as the user of attributes for the given 'name'." 340 341 defs = self.attributes_used[-1] 342 users = self.attribute_users[-1] 343 users[name] = node 344 defs[name] = set() 345 346 # Record the attribute combinations for the name. 347 348 if not hasattr(node, "_attrnames"): 349 node._attrnames = {} 350 node._attrnames[name] = defs[name] 351 352 # Remember all attribute combinations. 353 354 self.all_attributes_used.append(defs[name]) 355 356 def _reset_all_attributes(self): 357 self.attributes_used[-1] = {} 358 self.attribute_users[-1] = {} 359 360 def _new_branchpoint(self): 361 self.attribute_shelves.append([]) 362 363 def _new_branch(self): 364 d = {} 365 for name, attrnames in self.attributes_used[-1].items(): 366 d[name] = set(attrnames) 367 self.attributes_used.append(d) 368 self.attribute_users.append({}) 369 370 def _shelve_branch(self): 371 self.attribute_shelves[-1].append(self.attributes_used.pop()) 372 self.attribute_users.pop() 373 374 def _merge_branches(self): 375 active = self.attributes_used[-1] 376 377 # Take each alternative branch, currently shelved, and find the 378 # intersection of their contributions for each name. 379 380 shelved_defs = self.attribute_shelves.pop() 381 defs = dict(shelved_defs[0]) 382 383 for next_defs in shelved_defs[1:]: 384 for name, attrnames in next_defs.items(): 385 if defs.has_key(name): 386 defs[name] = defs[name].intersection(attrnames) 387 388 # Intersect the contributions with the previous state for each name. 389 390 for name, attrnames in defs.items(): 391 if active.has_key(name): 392 active[name].intersection_update(attrnames) 393 else: 394 active[name] = attrnames 395 396 # Where each shelved set of definitions is a superset of the eventual 397 # definitions for a name, record these specialised sets of usage. 398 399 for defs in shelved_defs: 400 for name, attrnames in defs.items(): 401 if attrnames.issuperset(active[name]): 402 self.all_attributes_used.append(attrnames) 403 404 # Program data structures. There are two separate kinds of structures: those 405 # with context, which are the values manipulated by programs, and those without 406 # context, which are typically constant things which are stored alongside the 407 # program but which are wrapped in context-dependent structures in the running 408 # program. 409 410 class Attr: 411 412 "An attribute entry having a context." 413 414 def __init__(self, position, parent, name): 415 416 """ 417 Initialise the attribute with the given 'position' within the collection 418 of attributes of its 'parent', indicating its 'name'. 419 """ 420 421 self.position = position 422 self.parent = parent 423 self.name = name 424 425 # Possible values. 426 427 self.context_values = set() 428 429 # Number of assignments per name. 430 431 self.assignments = None 432 433 # Value-related methods. 434 435 def get_contexts(self): 436 return [c for (c, v) in self.context_values] 437 438 def get_values(self): 439 return [v for (c, v) in self.context_values] 440 441 def get_context(self): 442 if len(self.context_values) == 1: 443 return self.get_contexts()[0] 444 else: 445 return None 446 447 def get_value(self): 448 if len(self.context_values) == 1: 449 return self.get_values()[0] 450 else: 451 return None 452 453 def update(self, context_values, single_assignment): 454 455 """ 456 Update the attribute, adding the 'context_values' provided to the 457 known details associated with the attribute, changing the number of 458 assignments according to the 'single_assignment' status of the 459 operation, where a true value indicates that only one assignment is 460 associated with the update, and a false value indicates that potentially 461 many assignments may be involved. 462 """ 463 464 if self.assignments is None: 465 if single_assignment: 466 self.assignments = 1 467 else: 468 self.assignments = AtLeast(1) 469 else: 470 if single_assignment: 471 self.assignments += 1 472 else: 473 self.assignments += AtLeast(1) 474 475 self.context_values.update(context_values) 476 477 def is_static_attribute(self): 478 479 """ 480 Return whether this attribute is defined on a fixed/static object such 481 as a class or a module. 482 """ 483 484 return isinstance(self.parent, (Class, Module)) 485 486 def defines_ambiguous_class(self): 487 488 "Return whether this attribute defines more than one class." 489 490 if self.assignments > 1: 491 have_class = 0 492 for obj in self.get_values(): 493 if isinstance(obj, Class): 494 if have_class: 495 return 1 496 have_class = 1 497 498 return 0 499 500 def defined_within_hierarchy(self): 501 502 """ 503 Return whether the parent and context of the attribute belong to the 504 same class hierarchy. 505 """ 506 507 # Must be defined within a class. 508 509 if isinstance(self.parent, Class): 510 511 # To be sure, all contexts must be classes and be the same as the 512 # parent, or be a superclass of the parent, or be a subclass of the 513 # parent. 514 515 for context in self.get_contexts(): 516 if not ( 517 isinstance(context, Class) and ( 518 context is self.parent or 519 context.has_subclass(self.parent) or 520 self.parent.has_subclass(context)) 521 ): 522 return 0 523 524 return 1 525 526 # Instance attributes are not defined within a hierarchy. 527 528 else: 529 return 0 530 531 def defined_outside_hierarchy(self): 532 533 """ 534 Return whether the parent and context of the attribute never belong to 535 the same class hierarchy. 536 """ 537 538 # Must be defined within a class. 539 540 if isinstance(self.parent, Class): 541 542 # To be sure, all contexts must be classes and be the same as the 543 # parent, or be a superclass of the parent, or be a subclass of the 544 # parent. 545 546 for context in self.get_contexts(): 547 if not ( 548 isinstance(context, Class) and not ( 549 context is self.parent or 550 context.has_subclass(self.parent) or 551 self.parent.has_subclass(context)) 552 ): 553 return 0 554 555 return 1 556 557 # Instance attributes are not defined within a hierarchy. 558 559 else: 560 return 0 561 562 def __repr__(self): 563 return "Attr(%r, %s, %r) # [%s], %r" % ( 564 self.position, shortrepr(self.parent), self.name, 565 self._context_values_str(), self.assignments 566 ) 567 568 def _context_values_str(self): 569 l = [] 570 for (c, v) in self.context_values: 571 l.append("(c=%s, v=%s)" % (shortrepr(c), shortrepr(v))) 572 return ", ".join(l) 573 574 # Instances are special in that they need to be wrapped together with context in 575 # a running program, but they are not generally constant. 576 577 class Instance: 578 579 "A placeholder indicating the involvement of an instance." 580 581 def __init__(self): 582 self.parent = None 583 584 # Image generation details. 585 586 self.location = None 587 588 def __repr__(self): 589 return "Instance()" 590 591 __shortrepr__ = __repr__ 592 593 class Constant: 594 595 "A superclass for all constant or context-free structures." 596 597 pass 598 599 # Data objects appearing in programs before run-time. 600 601 class Const(Constant, Instance): 602 603 "A constant object with no context." 604 605 def __init__(self, value): 606 Instance.__init__(self) 607 self.value = value 608 609 def get_value(self): 610 return self.value 611 612 def __repr__(self): 613 if self.location is not None: 614 return "Const(%r, location=%r)" % (self.value, self.location) 615 else: 616 return "Const(%r)" % self.value 617 618 __shortrepr__ = __repr__ 619 620 # Support constants as dictionary keys in order to build constant tables. 621 622 def __eq__(self, other): 623 return other is not None and self.value == other.value and self.value.__class__ is other.value.__class__ 624 625 def __hash__(self): 626 return hash(self.value) 627 628 def value_type_name(self): 629 return "__builtins__." + self.value.__class__.__name__ 630 631 class Class(NamespaceDict, Naming, Constant): 632 633 "An inspected class." 634 635 def __init__(self, name, parent, module=None, node=None): 636 637 """ 638 Initialise the class with the given 'name', 'parent' object, optional 639 'module' and optional AST 'node'. 640 """ 641 642 NamespaceDict.__init__(self, module) 643 self.name = name 644 self.parent = parent 645 self.astnode = node 646 647 # Superclasses, descendants and attributes. 648 649 self.bases = [] 650 self.descendants = set() 651 self.instattr = set() # instance attributes 652 self.relocated = set() # attributes which do not have the same 653 # position as those of the same name in 654 # some superclasses 655 656 # Caches. 657 658 self.reset_caches() 659 660 # Image generation details. 661 662 self.location = None 663 self.code_location = None 664 self.code_body_location = None # corresponds to the instantiator 665 666 self.instantiator = None 667 self.instance_template_location = None # for creating instances at run-time 668 669 # Program-related details. 670 671 self.blocks = None 672 self.temp_usage = 0 673 self.local_usage = 0 674 self.all_local_usage = 0 675 676 # Add this class to its attributes. 677 678 self.set("__class__", self) 679 680 def reset_caches(self): 681 682 "Reset the caches." 683 684 self.all_instattr = None # cache for instance_attributes 685 self.all_instattr_names = None # from all_instattr 686 self.all_classattr = None # cache for all_class_attributes 687 self.all_classattr_names = None # from all_classattr 688 self.allattr = None # cache for all_attributes 689 self.allattr_names = None # from allattr 690 691 def __repr__(self): 692 if self.location is not None: 693 return "Class(%r, %s, location=%r)" % (self.name, shortrepr(self.parent), self.location) 694 else: 695 return "Class(%r, %s)" % (self.name, shortrepr(self.parent)) 696 697 def __shortrepr__(self): 698 return "Class(%r, %s)" % (self.name, shortrepr(self.parent)) 699 700 def get_body_block(self): 701 return self.get_instantiator().blocks[0] 702 703 # Namespace-related methods. 704 705 def get_updated_context_values(self, context_values): 706 707 """ 708 Adapt the contexts found in the given 'context_values', returning a new 709 set. 710 See: docs/assignment.txt 711 """ 712 713 results = set() 714 715 for context, value in context_values: 716 717 # Change the ownership of functions. 718 719 if context is ReplaceableContext and value is not None and isinstance(value, Function): 720 results.add((self, value)) 721 else: 722 results.add((context, value)) 723 724 return NamespaceDict.get_updated_context_values(self, results) 725 726 def finalise_attributes(self): 727 728 "Make sure that all attributes are fully defined." 729 730 if self.finalised: 731 return 732 733 self.finalise_class_attributes() 734 self.finalise_instance_attributes() 735 self.finalised = 1 736 737 def unfinalise_attributes(self): 738 739 "Open attribute definitions to editing and subsequent finalisation." 740 741 self.reset_caches() 742 self.finalised = 0 743 744 # Convenience methods for accessing functions and methods. 745 746 def get_instantiator(self): 747 748 "Return a function which can be used to instantiate the class." 749 750 if self.instantiator is None: 751 self.instantiator = self.get_init_method().as_instantiator() 752 return self.instantiator 753 754 def get_init_method(self): 755 return self.all_class_attributes()["__init__"].get_value() 756 757 # Class-specific methods. 758 759 def add_base(self, base): 760 self.bases.append(base) 761 base.add_descendant(self) 762 763 def add_instance_attribute(self, name): 764 self.instattr.add(name) 765 766 def add_descendant(self, cls): 767 self.descendants.add(cls) 768 for base in self.bases: 769 base.add_descendant(cls) 770 771 def has_subclass(self, other): 772 return other in self.descendants 773 774 def all_descendants(self): 775 d = {} 776 for cls in self.descendants: 777 d[cls.full_name()] = cls 778 return d 779 780 "Return the attribute names provided by this class only." 781 782 class_attribute_names = NamespaceDict.keys 783 784 def class_attributes(self): 785 786 "Return class attributes provided by this class only." 787 788 return dict(self) 789 790 def all_class_attribute_names(self): 791 792 "Return the attribute names provided by classes in this hierarchy." 793 794 if self.all_classattr_names is None: 795 self.all_class_attributes() 796 self.all_classattr_names = self.all_classattr.keys() 797 return self.all_classattr_names 798 799 def all_class_attributes(self): 800 801 "Return all class attributes, indicating the class which provides them." 802 803 self.finalise_class_attributes() 804 return self.all_classattr 805 806 def finalise_class_attributes(self): 807 808 "Make sure that the class attributes are fully defined." 809 810 if self.all_classattr is None: 811 self.all_classattr = {} 812 clsattr = {} 813 814 # Record provisional position information for attributes of this 815 # class. 816 817 for name in self.class_attributes().keys(): 818 clsattr[name] = set() # position not yet defined 819 820 reversed_bases = self.bases[:] 821 reversed_bases.reverse() 822 823 # For the bases in reverse order, acquire class attribute details. 824 825 for cls in reversed_bases: 826 for name, attr in cls.all_class_attributes().items(): 827 self.all_classattr[name] = attr 828 829 # Record previous attribute information. 830 831 if clsattr.has_key(name): 832 clsattr[name].add(attr.position) 833 834 # Record class attributes provided by this class and its bases, 835 # along with their positions. 836 837 self.all_classattr.update(self.class_attributes()) 838 839 if clsattr: 840 for i, name in enumerate(self._get_position_list(clsattr)): 841 self.all_classattr[name].position = i 842 843 return self.all_classattr 844 845 def instance_attribute_names(self): 846 847 "Return the instance attribute names provided by the class." 848 849 if self.all_instattr_names is None: 850 self.instance_attributes() 851 return self.all_instattr_names 852 853 def instance_attributes(self): 854 855 "Return instance-only attributes for instances of this class." 856 857 self.finalise_instance_attributes() 858 return self.all_instattr 859 860 def finalise_instance_attributes(self): 861 862 "Make sure that the instance attributes are fully defined." 863 864 # Cache the attributes by converting the positioned attributes into a 865 # dictionary. 866 867 if self.all_instattr is None: 868 self.all_instattr = self._get_attributes() 869 self.all_instattr_names = self.all_instattr.keys() 870 871 return self.all_instattr 872 873 def _get_attributes(self): 874 875 """ 876 Return a dictionary mapping names to Attr instances incorporating 877 information about their positions in the final instance structure. 878 """ 879 880 instattr = {} 881 882 # Record provisional position information for attributes of this 883 # instance. 884 885 for name in self.instattr: 886 instattr[name] = set() # position not yet defined 887 888 reversed_bases = self.bases[:] 889 reversed_bases.reverse() 890 891 # For the bases in reverse order, acquire instance attribute 892 # details. 893 894 for cls in reversed_bases: 895 for name, attr in cls.instance_attributes().items(): 896 897 # Record previous attribute information. 898 899 if instattr.has_key(name): 900 instattr[name].add(attr.position) 901 else: 902 instattr[name] = set([attr.position]) 903 904 # Build the dictionary of attributes using the existing positions known 905 # for each name. 906 907 d = {} 908 for i, name in enumerate(self._get_position_list(instattr)): 909 d[name] = Attr(i, Instance(), name) 910 return d 911 912 def _get_position_list(self, positions): 913 914 """ 915 Return a list of attribute names for the given 'positions' mapping from 916 names to positions, indicating the positions of the attributes in the 917 final instance structure. 918 """ 919 920 position_items = positions.items() 921 namearray = [None] * len(position_items) 922 923 # Get the positions in ascending order of list size, with lists 924 # of the same size ordered according to their smallest position 925 # value. 926 927 position_items.sort(self._cmp_positions) 928 929 # Get the names in position order. 930 931 held = [] 932 933 for name, pos in position_items: 934 pos = list(pos) 935 pos.sort() 936 if pos and pos[0] < len(namearray) and namearray[pos[0]] is None: 937 namearray[pos[0]] = name 938 else: 939 if pos: 940 self.relocated.add(name) 941 held.append((name, pos)) 942 943 for i, attr in enumerate(namearray): 944 if attr is None: 945 name, pos = held.pop() 946 namearray[i] = name 947 948 return namearray 949 950 def _cmp_positions(self, a, b): 951 952 "Compare name plus position list operands 'a' and 'b'." 953 954 name_a, list_a = a 955 name_b, list_b = b 956 if len(list_a) < len(list_b): 957 return -1 958 elif len(list_a) > len(list_b): 959 return 1 960 elif not list_a: 961 return 0 962 else: 963 return cmp(min(list_a), min(list_b)) 964 965 def all_attribute_names(self): 966 967 """ 968 Return the names of all attributes provided by instances of this class. 969 """ 970 971 self.allattr_names = self.allattr_names or self.all_attributes().keys() 972 return self.allattr_names 973 974 def all_attributes(self): 975 976 """ 977 Return all attributes for an instance, indicating either the class which 978 provides them or that the instance itself provides them. 979 """ 980 981 if self.allattr is None: 982 self.allattr = {} 983 self.allattr.update(self.all_class_attributes()) 984 for name, attr in self.instance_attributes().items(): 985 if self.allattr.has_key(name): 986 print "Instance attribute %r in %r overrides class attribute." % (name, self) 987 self.allattr[name] = attr 988 return self.allattr 989 990 class Function(NamespaceDict, Naming, Constant): 991 992 "An inspected function." 993 994 def __init__(self, name, parent, argnames, defaults, has_star, has_dstar, module=None, node=None): 995 996 """ 997 Initialise the function with the given 'name', 'parent', list of 998 'argnames', list of 'defaults', the 'has_star' flag (indicating the 999 presence of a * parameter), the 'has_dstar' flag (indicating the 1000 presence of a ** parameter), optional 'module', and optional AST 'node'. 1001 """ 1002 1003 NamespaceDict.__init__(self, module) 1004 self.name = name 1005 self.parent = parent 1006 self.argnames = argnames 1007 self.defaults = defaults 1008 self.has_star = has_star 1009 self.has_dstar = has_dstar 1010 self.astnode = node 1011 1012 # For lambda functions with defaults, add a context argument. 1013 1014 if name is None and defaults: 1015 self.argnames.insert(0, "<context>") 1016 1017 # Initialise the positional names. 1018 1019 self.positional_names = self.argnames[:] 1020 if has_dstar: 1021 self.dstar_name = self.positional_names[-1] 1022 del self.positional_names[-1] 1023 if has_star: 1024 self.star_name = self.positional_names[-1] 1025 del self.positional_names[-1] 1026 1027 # Initialise default storage. 1028 # NOTE: This must be initialised separately due to the reliance on node 1029 # NOTE: visiting. 1030 1031 self.default_attrs = [] 1032 1033 # Initialise attribute usage. 1034 1035 for arg in argnames: 1036 1037 # Define attribute users. 1038 1039 if node is not None: 1040 self._define_attribute_user_for_name(node, arg) 1041 1042 # Or just record the usage. 1043 1044 else: 1045 self.attributes_used[-1][arg] = set() 1046 1047 # Caches. 1048 1049 self.localnames = None # cache for locals 1050 1051 # Add parameters to the namespace. 1052 1053 self._add_parameters(argnames) 1054 1055 # Image generation details. 1056 1057 self.location = None 1058 self.code_location = None 1059 self.code_body_location = None 1060 1061 # Program-related details. 1062 1063 self.blocks = None 1064 self.body_block = None 1065 1066 self.temp_usage = 0 1067 self.local_usage = 0 1068 self.all_local_usage = 0 1069 1070 def _add_parameters(self, argnames): 1071 for name in argnames: 1072 if isinstance(name, tuple): 1073 self._add_parameters(name) 1074 else: 1075 self.set(name, None) 1076 1077 def __repr__(self): 1078 if self.location is not None: 1079 return "Function(%r, %s, %r, location=%r, code_location=%r)" % ( 1080 self.name, shortrepr(self.parent), self.argnames, self.location, self.code_location 1081 ) 1082 else: 1083 return "Function(%r, %s, %r)" % ( 1084 self.name, shortrepr(self.parent), self.argnames 1085 ) 1086 1087 def __shortrepr__(self): 1088 return "Function(%r, %s)" % ( 1089 self.name, shortrepr(self.parent) 1090 ) 1091 1092 def get_body_block(self): 1093 return self.body_block 1094 1095 # Namespace-related methods. 1096 1097 def store_default(self, value): 1098 attr = Attr(None, self, None) 1099 attr.update([self.get_context_and_value(value)], 1) 1100 self.default_attrs.append(attr) 1101 1102 def make_global(self, name): 1103 if name not in self.argnames and not self.has_key(name): 1104 self.globals.add(name) 1105 return 1 1106 else: 1107 return 0 1108 1109 def parameters(self): 1110 1111 """ 1112 Return a dictionary mapping parameter names to their position in the 1113 parameter list. 1114 """ 1115 1116 parameters = {} 1117 for i, name in enumerate(self.argnames): 1118 parameters[name] = i 1119 return parameters 1120 1121 def all_locals(self): 1122 1123 "Return a dictionary mapping names to local and parameter details." 1124 1125 return dict(self) 1126 1127 def locals(self): 1128 1129 "Return a dictionary mapping names to local details." 1130 1131 if self.localnames is None: 1132 self.localnames = {} 1133 self.localnames.update(self.all_locals()) 1134 for name in self.argnames: 1135 del self.localnames[name] 1136 return self.localnames 1137 1138 def is_method(self): 1139 1140 """ 1141 Return whether this function is a method explicitly defined in a class. 1142 """ 1143 1144 return isinstance(self.parent, Class) 1145 1146 def is_relocated(self, name): 1147 1148 """ 1149 Determine whether the given attribute 'name' is relocated for instances 1150 having this function as a method. 1151 """ 1152 1153 for cls in self.parent.descendants: 1154 if name in cls.relocated: 1155 return 1 1156 return 0 1157 1158 def finalise_attributes(self): 1159 1160 """ 1161 Make sure all attributes (locals) are fully defined. Note that locals 1162 are not attributes in the sense of class, module or instance attributes. 1163 Defaults are also finalised by this method. 1164 """ 1165 1166 if self.finalised: 1167 return 1168 1169 # Defaults. 1170 1171 for i, default in enumerate(self.default_attrs): 1172 default.position = i 1173 1174 # Locals. 1175 1176 i = None 1177 for i, name in enumerate(self.argnames): 1178 self[name].position = i 1179 1180 if i is not None: 1181 nparams = i + 1 1182 else: 1183 nparams = 0 1184 1185 i = None 1186 for i, attr in enumerate(self.locals().values()): 1187 attr.position = i + nparams 1188 1189 if i is not None: 1190 nothers = i + 1 1191 else: 1192 nothers = 0 1193 1194 self.local_usage = nothers 1195 self.all_local_usage = nparams + nothers 1196 self.finalised = 1 1197 1198 def as_instantiator(self): 1199 1200 "Make an instantiator function from a method, keeping all arguments." 1201 1202 function = Function(self.parent.name, self.parent.parent, self.argnames, self.defaults, 1203 self.has_star, self.has_dstar, self.module, self.astnode) 1204 function.default_attrs = self.default_attrs 1205 return function 1206 1207 class UnresolvedName(NamespaceDict, Constant): 1208 1209 "A module, class or function which was mentioned but could not be imported." 1210 1211 def __init__(self, name, parent_name, module=None): 1212 NamespaceDict.__init__(self, module) 1213 self.name = name 1214 self.parent_name = parent_name 1215 self.parent = None 1216 1217 self.descendants = set() 1218 1219 def add_descendant(self, cls): 1220 self.descendants.add(cls) 1221 1222 def all_class_attributes(self): 1223 return {} 1224 1225 def instance_attributes(self): 1226 return {} 1227 1228 def __repr__(self): 1229 return "UnresolvedName(%r, %r)" % (self.name, self.parent_name) 1230 1231 __shortrepr__ = __repr__ 1232 1233 def full_name(self): 1234 if self.name is not None: 1235 return self.parent_name + "." + self.name 1236 else: 1237 return self.parent_name 1238 1239 class Module(NamespaceDict, Constant): 1240 1241 "An inspected module's core details." 1242 1243 def __init__(self, name): 1244 NamespaceDict.__init__(self, self) 1245 self.name = name 1246 self.parent = None 1247 1248 # Original location details. 1249 1250 self.astnode = None 1251 1252 # Complete lists of classes and functions. 1253 1254 self.all_objects = set() 1255 1256 # Keyword records. 1257 1258 self.keyword_names = set() 1259 1260 # Image generation details. 1261 1262 self.location = None 1263 self.code_location = None 1264 1265 # Program-related details. 1266 1267 self.blocks = None 1268 self.temp_usage = 0 1269 self.local_usage = 0 1270 self.all_local_usage = 0 1271 1272 def full_name(self): 1273 return self.name 1274 1275 def __repr__(self): 1276 if self.location is not None: 1277 return "Module(%r, location=%r)" % (self.name, self.location) 1278 else: 1279 return "Module(%r)" % self.name 1280 1281 def __shortrepr__(self): 1282 return "Module(%r)" % self.name 1283 1284 # Attribute methods. 1285 1286 "Return the module attribute names provided by the module." 1287 1288 module_attribute_names = NamespaceDict.keys 1289 1290 def module_attributes(self): 1291 1292 "Return a dictionary mapping names to module attributes." 1293 1294 return dict(self) 1295 1296 # vim: tabstop=4 expandtab shiftwidth=4