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 def __delitem__(self, name): 123 del self.namespace[name] 124 125 def has_key(self, name): 126 return self.namespace.has_key(name) 127 128 def keys(self): 129 return self.namespace.keys() 130 131 def values(self): 132 return self.namespace.values() 133 134 def items(self): 135 return self.namespace.items() 136 137 def __getitem__(self, name): 138 return self.namespace[name] 139 140 def get(self, name, default=None): 141 return self.namespace.get(name, default) 142 143 def __setitem__(self, name, value): 144 self.set(name, value) 145 146 def set(self, name, value, single_assignment=1): 147 148 """ 149 A more powerful set operation, making 'name' refer to 'value' whilst 150 indicating whether a 'single_assignment' (true by default) occurs in 151 this operation (or whether the operation covers potentially many 152 assignments in the lifetime of a program). 153 """ 154 155 if name in self.globals: 156 self.module.set(name, value, 0) 157 else: 158 self._set(name, value, single_assignment) 159 160 def set_module(self, name, value): 161 162 """ 163 A specialised set operation, making 'name' refer to 'value' in the 164 context of making a module reference available in association with 165 'name' as part of the import of that module or a submodule of that 166 module. 167 """ 168 169 self._set(name, value, 1) 170 171 def _set(self, name, attr_or_value, single_assignment=1): 172 173 """ 174 The underlying set operation associating 'name' with the given 175 'attr_or_value'. 176 See: docs/assignment.txt 177 """ 178 179 # Add and/or obtain the namespace entry. 180 181 if not self.namespace.has_key(name): 182 self.namespace[name] = Attr(None, self, name) 183 184 attr = self.namespace[name] 185 186 # Handle attribute assignment as well as assignment of basic objects. 187 # Attempt to fix the context if not explicitly defined. 188 189 if isinstance(attr_or_value, Attr): 190 context_values = self.get_updated_context_values(attr_or_value.context_values) 191 else: 192 context_values = self.get_updated_context_values([self.get_context_and_value(attr_or_value)]) 193 194 attr.update(context_values, single_assignment) 195 196 def get_context_and_value(self, value): 197 198 "Return a context, value tuple for the given 'value'." 199 200 # Functions have a replaceable context. 201 202 if isinstance(value, Function): 203 return (ReplaceableContext, value) 204 205 # Classes use placeholder contexts which cannot be replaced but which 206 # do not communicate useful contextual information. 207 208 elif isinstance(value, Class): 209 return (PlaceholderContext, value) 210 211 # Other values employ themselves as the context. 212 213 else: 214 return (value, value) 215 216 def get_updated_context_values(self, context_values): 217 218 """ 219 Adapt the contexts found in the given 'context_values', returning a new 220 set. 221 See: docs/assignment.txt 222 """ 223 224 results = set() 225 226 for context, value in context_values: 227 228 # Set the context of instances to themselves. 229 230 if isinstance(value, Instance): 231 results.add((value, value)) 232 else: 233 results.add((context, value)) 234 235 return results 236 237 def make_global(self, name): 238 if not self.namespace.has_key(name): 239 self.globals.add(name) 240 return 1 241 else: 242 return 0 243 244 def attributes_as_list(self): 245 246 "Return the attributes in a list." 247 248 self.finalise_attributes() 249 l = [None] * len(self.keys()) 250 for attr in self.values(): 251 l[attr.position] = attr 252 return l 253 254 def finalise_attributes(self): 255 256 "Make sure all attributes are fully defined." 257 258 if self.finalised: 259 return 260 261 # The default action is to assign attribute positions sequentially. 262 263 for i, attr in enumerate(self.values()): 264 attr.position = i 265 266 self.finalised = 1 267 268 # Program data structures. There are two separate kinds of structures: those 269 # with context, which are the values manipulated by programs, and those without 270 # context, which are typically constant things which are stored alongside the 271 # program but which are wrapped in context-dependent structures in the running 272 # program. 273 274 class Attr: 275 276 "An attribute entry having a context." 277 278 def __init__(self, position, parent, name): 279 280 """ 281 Initialise the attribute with the given 'position' within the collection 282 of attributes of its 'parent', indicating its 'name'. 283 """ 284 285 self.position = position 286 self.parent = parent 287 self.name = name 288 289 # Attribute usage. 290 291 self.attributes_used = set() 292 293 # Possible values. 294 295 self.context_values = set() 296 297 # Number of assignments per name. 298 299 self.assignments = None 300 301 # Attribute usage methods. 302 303 def use_attribute(self, attrname): 304 self.attributes_used.add(attrname) 305 return self.attributes_used 306 307 def exposes_name(self, attrname): 308 return attrname in self.attributes_used 309 310 # Value-related methods. 311 312 def get_contexts(self): 313 return [c for (c, v) in self.context_values] 314 315 def get_values(self): 316 return [v for (c, v) in self.context_values] 317 318 def get_context(self): 319 if len(self.context_values) == 1: 320 return self.get_contexts()[0] 321 else: 322 return None 323 324 def get_value(self): 325 if len(self.context_values) == 1: 326 return self.get_values()[0] 327 else: 328 return None 329 330 def update(self, context_values, single_assignment): 331 332 """ 333 Update the attribute, adding the 'context_values' provided to the 334 known details associated with the attribute, changing the number of 335 assignments according to the 'single_assignment' status of the 336 operation, where a true value indicates that only one assignment is 337 associated with the update, and a false value indicates that potentially 338 many assignments may be involved. 339 """ 340 341 if self.assignments is None: 342 if single_assignment: 343 self.assignments = 1 344 else: 345 self.assignments = AtLeast(1) 346 else: 347 if single_assignment: 348 self.assignments += 1 349 else: 350 self.assignments += AtLeast(1) 351 352 self.context_values.update(context_values) 353 354 def is_static_attribute(self): 355 356 """ 357 Return whether this attribute is defined on a fixed/static object such 358 as a class or a module. 359 """ 360 361 return isinstance(self.parent, (Class, Module)) 362 363 def defines_ambiguous_class(self): 364 365 "Return whether this attribute defines more than one class." 366 367 if self.assignments > 1: 368 have_class = 0 369 for obj in self.get_values(): 370 if isinstance(obj, Class): 371 if have_class: 372 return 1 373 have_class = 1 374 375 return 0 376 377 def defined_within_hierarchy(self): 378 379 """ 380 Return whether the parent and context of the attribute belong to the 381 same class hierarchy. 382 """ 383 384 # Must be defined within a class. 385 386 if isinstance(self.parent, Class): 387 388 # To be sure, all contexts must be classes and be the same as the 389 # parent, or be a superclass of the parent, or be a subclass of the 390 # parent. 391 392 for context in self.get_contexts(): 393 if not ( 394 isinstance(context, Class) and ( 395 context is self.parent or 396 context.has_subclass(self.parent) or 397 self.parent.has_subclass(context)) 398 ): 399 return 0 400 401 return 1 402 403 # Instance attributes are not defined within a hierarchy. 404 405 else: 406 return 0 407 408 def defined_outside_hierarchy(self): 409 410 """ 411 Return whether the parent and context of the attribute never belong to 412 the same class hierarchy. 413 """ 414 415 # Must be defined within a class. 416 417 if isinstance(self.parent, Class): 418 419 # To be sure, all contexts must be classes and be the same as the 420 # parent, or be a superclass of the parent, or be a subclass of the 421 # parent. 422 423 for context in self.get_contexts(): 424 if not ( 425 isinstance(context, Class) and not ( 426 context is self.parent or 427 context.has_subclass(self.parent) or 428 self.parent.has_subclass(context)) 429 ): 430 return 0 431 432 return 1 433 434 # Instance attributes are not defined within a hierarchy. 435 436 else: 437 return 0 438 439 def __repr__(self): 440 return "Attr(%r, %s, %r) # [%s], %r" % ( 441 self.position, shortrepr(self.parent), self.name, 442 self._context_values_str(), self.assignments 443 ) 444 445 def _context_values_str(self): 446 l = [] 447 for (c, v) in self.context_values: 448 l.append("(c=%s, v=%s)" % (shortrepr(c), shortrepr(v))) 449 return ", ".join(l) 450 451 # Instances are special in that they need to be wrapped together with context in 452 # a running program, but they are not generally constant. 453 454 class Instance: 455 456 "A placeholder indicating the involvement of an instance." 457 458 def __init__(self): 459 self.parent = None 460 461 # Image generation details. 462 463 self.location = None 464 465 def __repr__(self): 466 return "Instance()" 467 468 __shortrepr__ = __repr__ 469 470 class Constant: 471 472 "A superclass for all constant or context-free structures." 473 474 pass 475 476 # Data objects appearing in programs before run-time. 477 478 class Const(Constant, Instance): 479 480 "A constant object with no context." 481 482 def __init__(self, value): 483 Instance.__init__(self) 484 self.value = value 485 486 def get_value(self): 487 return self.value 488 489 def __repr__(self): 490 if self.location is not None: 491 return "Const(%r, location=%r)" % (self.value, self.location) 492 else: 493 return "Const(%r)" % self.value 494 495 __shortrepr__ = __repr__ 496 497 # Support constants as dictionary keys in order to build constant tables. 498 499 def __eq__(self, other): 500 return other is not None and self.value == other.value and self.value.__class__ is other.value.__class__ 501 502 def __hash__(self): 503 return hash(self.value) 504 505 def value_type_name(self): 506 return "__builtins__." + self.value.__class__.__name__ 507 508 class Class(NamespaceDict, Naming, Constant): 509 510 "An inspected class." 511 512 def __init__(self, name, parent, module=None, node=None): 513 514 """ 515 Initialise the class with the given 'name', 'parent' object, optional 516 'module' and optional AST 'node'. 517 """ 518 519 NamespaceDict.__init__(self, module) 520 self.name = name 521 self.parent = parent 522 self.astnode = node 523 524 # Superclasses, descendants and attributes. 525 526 self.bases = [] 527 self.descendants = set() 528 self.instattr = set() # instance attributes 529 self.relocated = set() # attributes which do not have the same 530 # position as those of the same name in 531 # some superclasses 532 533 # Caches. 534 535 self.all_instattr = None # cache for instance_attributes 536 self.all_instattr_names = None # from all_instattr 537 self.all_classattr = None # cache for all_class_attributes 538 self.all_classattr_names = None # from all_classattr 539 self.allattr = None # cache for all_attributes 540 self.allattr_names = None # from allattr 541 542 # Image generation details. 543 544 self.location = None 545 self.code_location = None 546 self.code_body_location = None # corresponds to the instantiator 547 548 self.instantiator = None 549 self.instance_template_location = None # for creating instances at run-time 550 551 # Program-related details. 552 553 self.blocks = None 554 self.temp_usage = 0 555 self.local_usage = 0 556 self.all_local_usage = 0 557 558 # Add this class to its attributes. 559 560 self.set("__class__", self) 561 562 def __repr__(self): 563 if self.location is not None: 564 return "Class(%r, %s, location=%r)" % (self.name, shortrepr(self.parent), self.location) 565 else: 566 return "Class(%r, %s)" % (self.name, shortrepr(self.parent)) 567 568 def __shortrepr__(self): 569 return "Class(%r, %s)" % (self.name, shortrepr(self.parent)) 570 571 def get_body_block(self): 572 return self.get_instantiator().blocks[0] 573 574 # Namespace-related methods. 575 576 def get_updated_context_values(self, context_values): 577 578 """ 579 Adapt the contexts found in the given 'context_values', returning a new 580 set. 581 See: docs/assignment.txt 582 """ 583 584 results = set() 585 586 for context, value in context_values: 587 588 # Change the ownership of functions. 589 590 if context is ReplaceableContext and value is not None and isinstance(value, Function): 591 results.add((self, value)) 592 else: 593 results.add((context, value)) 594 595 return NamespaceDict.get_updated_context_values(self, results) 596 597 def finalise_attributes(self): 598 599 "Make sure that all attributes are fully defined." 600 601 if self.finalised: 602 return 603 604 self.finalise_class_attributes() 605 self.finalise_instance_attributes() 606 self.finalised = 1 607 608 # Convenience methods for accessing functions and methods. 609 610 def get_instantiator(self): 611 612 "Return a function which can be used to instantiate the class." 613 614 if self.instantiator is None: 615 self.instantiator = self.get_init_method().as_instantiator() 616 return self.instantiator 617 618 def get_init_method(self): 619 return self.all_class_attributes()["__init__"].get_value() 620 621 # Class-specific methods. 622 623 def add_base(self, base): 624 self.bases.append(base) 625 base.add_descendant(self) 626 627 def add_instance_attribute(self, name): 628 self.instattr.add(name) 629 630 def add_descendant(self, cls): 631 self.descendants.add(cls) 632 for base in self.bases: 633 base.add_descendant(cls) 634 635 def has_subclass(self, other): 636 return other in self.descendants 637 638 def all_descendants(self): 639 d = {} 640 for cls in self.descendants: 641 d[cls.full_name()] = cls 642 return d 643 644 "Return the attribute names provided by this class only." 645 646 class_attribute_names = NamespaceDict.keys 647 648 def class_attributes(self): 649 650 "Return class attributes provided by this class only." 651 652 return dict(self) 653 654 def all_class_attribute_names(self): 655 656 "Return the attribute names provided by classes in this hierarchy." 657 658 if self.all_classattr_names is None: 659 self.all_class_attributes() 660 return self.all_classattr_names 661 662 def all_class_attributes(self): 663 664 "Return all class attributes, indicating the class which provides them." 665 666 self.finalise_class_attributes() 667 return self.all_classattr 668 669 def finalise_class_attributes(self): 670 671 "Make sure that the class attributes are fully defined." 672 673 if self.all_classattr is None: 674 self.all_classattr = {} 675 clsattr = {} 676 677 # Record provisional position information for attributes of this 678 # class. 679 680 for name in self.class_attributes().keys(): 681 clsattr[name] = set() # position not yet defined 682 683 reversed_bases = self.bases[:] 684 reversed_bases.reverse() 685 686 # For the bases in reverse order, acquire class attribute details. 687 688 for cls in reversed_bases: 689 for name, attr in cls.all_class_attributes().items(): 690 self.all_classattr[name] = attr 691 692 # Record previous attribute information. 693 694 if clsattr.has_key(name): 695 clsattr[name].add(attr.position) 696 697 # Record class attributes provided by this class and its bases, 698 # along with their positions. 699 700 self.all_classattr.update(self.class_attributes()) 701 702 if clsattr: 703 for i, name in enumerate(self._get_position_list(clsattr)): 704 self.all_classattr[name].position = i 705 706 return self.all_classattr 707 708 def instance_attribute_names(self): 709 710 "Return the instance attribute names provided by the class." 711 712 if self.all_instattr_names is None: 713 self.instance_attributes() 714 return self.all_instattr_names 715 716 def instance_attributes(self): 717 718 "Return instance-only attributes for instances of this class." 719 720 self.finalise_instance_attributes() 721 return self.all_instattr 722 723 def finalise_instance_attributes(self): 724 725 "Make sure that the instance attributes are fully defined." 726 727 # Cache the attributes by converting the positioned attributes into a 728 # dictionary. 729 730 if self.all_instattr is None: 731 self.all_instattr = self._get_attributes() 732 self.all_instattr_names = self.all_instattr.keys() 733 734 return self.all_instattr 735 736 def _get_attributes(self): 737 738 """ 739 Return a dictionary mapping names to Attr instances incorporating 740 information about their positions in the final instance structure. 741 """ 742 743 instattr = {} 744 745 # Record provisional position information for attributes of this 746 # instance. 747 748 for name in self.instattr: 749 instattr[name] = set() # position not yet defined 750 751 reversed_bases = self.bases[:] 752 reversed_bases.reverse() 753 754 # For the bases in reverse order, acquire instance attribute 755 # details. 756 757 for cls in reversed_bases: 758 for name, attr in cls.instance_attributes().items(): 759 760 # Record previous attribute information. 761 762 if instattr.has_key(name): 763 instattr[name].add(attr.position) 764 else: 765 instattr[name] = set([attr.position]) 766 767 # Build the dictionary of attributes using the existing positions known 768 # for each name. 769 770 d = {} 771 for i, name in enumerate(self._get_position_list(instattr)): 772 d[name] = Attr(i, Instance(), name) 773 return d 774 775 def _get_position_list(self, positions): 776 777 """ 778 Return a list of attribute names for the given 'positions' mapping from 779 names to positions, indicating the positions of the attributes in the 780 final instance structure. 781 """ 782 783 position_items = positions.items() 784 namearray = [None] * len(position_items) 785 786 # Get the positions in ascending order of list size, with lists 787 # of the same size ordered according to their smallest position 788 # value. 789 790 position_items.sort(self._cmp_positions) 791 792 # Get the names in position order. 793 794 held = [] 795 796 for name, pos in position_items: 797 pos = list(pos) 798 pos.sort() 799 if pos and pos[0] < len(namearray) and namearray[pos[0]] is None: 800 namearray[pos[0]] = name 801 else: 802 if pos: 803 self.relocated.add(name) 804 held.append((name, pos)) 805 806 for i, attr in enumerate(namearray): 807 if attr is None: 808 name, pos = held.pop() 809 namearray[i] = name 810 811 #print self.name, positions 812 #print "->", namearray 813 return namearray 814 815 def _cmp_positions(self, a, b): 816 817 "Compare name plus position list operands 'a' and 'b'." 818 819 name_a, list_a = a 820 name_b, list_b = b 821 if len(list_a) < len(list_b): 822 return -1 823 elif len(list_a) > len(list_b): 824 return 1 825 elif not list_a: 826 return 0 827 else: 828 return cmp(min(list_a), min(list_b)) 829 830 def all_attribute_names(self): 831 832 """ 833 Return the names of all attributes provided by instances of this class. 834 """ 835 836 self.allattr_names = self.allattr_names or self.all_attributes().keys() 837 return self.allattr_names 838 839 def all_attributes(self): 840 841 """ 842 Return all attributes for an instance, indicating either the class which 843 provides them or that the instance itself provides them. 844 """ 845 846 if self.allattr is None: 847 self.allattr = {} 848 self.allattr.update(self.all_class_attributes()) 849 for name, attr in self.instance_attributes().items(): 850 if self.allattr.has_key(name): 851 print "Instance attribute %r in %r overrides class attribute." % (name, self) 852 self.allattr[name] = attr 853 return self.allattr 854 855 class Function(NamespaceDict, Naming, Constant): 856 857 "An inspected function." 858 859 def __init__(self, name, parent, argnames, defaults, has_star, has_dstar, module=None, node=None): 860 861 """ 862 Initialise the function with the given 'name', 'parent', list of 863 'argnames', list of 'defaults', the 'has_star' flag (indicating the 864 presence of a * parameter), the 'has_dstar' flag (indicating the 865 presence of a ** parameter), optional 'module', and optional AST 'node'. 866 """ 867 868 NamespaceDict.__init__(self, module) 869 self.name = name 870 self.parent = parent 871 self.argnames = argnames 872 self.defaults = defaults 873 self.has_star = has_star 874 self.has_dstar = has_dstar 875 self.astnode = node 876 877 # For lambda functions with defaults, add a context argument. 878 879 if name is None and defaults: 880 self.argnames.insert(0, "<context>") 881 882 # Initialise the positional names. 883 884 self.positional_names = self.argnames[:] 885 if has_dstar: 886 self.dstar_name = self.positional_names[-1] 887 del self.positional_names[-1] 888 if has_star: 889 self.star_name = self.positional_names[-1] 890 del self.positional_names[-1] 891 892 # Initialise default storage. 893 # NOTE: This must be initialised separately due to the reliance on node 894 # NOTE: visiting. 895 896 self.default_attrs = [] 897 898 # Caches. 899 900 self.localnames = None # cache for locals 901 902 # Add parameters to the namespace. 903 904 self._add_parameters(argnames) 905 906 # Image generation details. 907 908 self.location = None 909 self.code_location = None 910 self.code_body_location = None 911 912 # Program-related details. 913 914 self.blocks = None 915 self.body_block = None 916 917 self.temp_usage = 0 918 self.local_usage = 0 919 self.all_local_usage = 0 920 921 def _add_parameters(self, argnames): 922 for name in argnames: 923 if isinstance(name, tuple): 924 self._add_parameters(name) 925 else: 926 self.set(name, None) 927 928 def __repr__(self): 929 if self.location is not None: 930 return "Function(%r, %s, %r, location=%r, code_location=%r)" % ( 931 self.name, shortrepr(self.parent), self.argnames, self.location, self.code_location 932 ) 933 else: 934 return "Function(%r, %s, %r)" % ( 935 self.name, shortrepr(self.parent), self.argnames 936 ) 937 938 def __shortrepr__(self): 939 return "Function(%r, %s)" % ( 940 self.name, shortrepr(self.parent) 941 ) 942 943 def get_body_block(self): 944 return self.body_block 945 946 # Namespace-related methods. 947 948 def store_default(self, value): 949 attr = Attr(None, self, None) 950 attr.update([self.get_context_and_value(value)], 1) 951 self.default_attrs.append(attr) 952 953 def make_global(self, name): 954 if name not in self.argnames and not self.has_key(name): 955 self.globals.add(name) 956 return 1 957 else: 958 return 0 959 960 def parameters(self): 961 962 """ 963 Return a dictionary mapping parameter names to their position in the 964 parameter list. 965 """ 966 967 parameters = {} 968 for i, name in enumerate(self.argnames): 969 parameters[name] = i 970 return parameters 971 972 def all_locals(self): 973 974 "Return a dictionary mapping names to local and parameter details." 975 976 return dict(self) 977 978 def locals(self): 979 980 "Return a dictionary mapping names to local details." 981 982 if self.localnames is None: 983 self.localnames = {} 984 self.localnames.update(self.all_locals()) 985 for name in self.argnames: 986 del self.localnames[name] 987 return self.localnames 988 989 def is_method(self): 990 991 """ 992 Return whether this function is a method explicitly defined in a class. 993 """ 994 995 return isinstance(self.parent, Class) 996 997 def is_relocated(self, name): 998 999 """ 1000 Determine whether the given attribute 'name' is relocated for instances 1001 having this function as a method. 1002 """ 1003 1004 for cls in self.parent.descendants: 1005 if name in cls.relocated: 1006 return 1 1007 return 0 1008 1009 def finalise_attributes(self): 1010 1011 """ 1012 Make sure all attributes (locals) are fully defined. Note that locals 1013 are not attributes in the sense of class, module or instance attributes. 1014 Defaults are also finalised by this method. 1015 """ 1016 1017 if self.finalised: 1018 return 1019 1020 # Defaults. 1021 1022 for i, default in enumerate(self.default_attrs): 1023 default.position = i 1024 1025 # Locals. 1026 1027 i = None 1028 for i, name in enumerate(self.argnames): 1029 self[name].position = i 1030 1031 if i is not None: 1032 nparams = i + 1 1033 else: 1034 nparams = 0 1035 1036 i = None 1037 for i, attr in enumerate(self.locals().values()): 1038 attr.position = i + nparams 1039 1040 if i is not None: 1041 nothers = i + 1 1042 else: 1043 nothers = 0 1044 1045 self.local_usage = nothers 1046 self.all_local_usage = nparams + nothers 1047 self.finalised = 1 1048 1049 def as_instantiator(self): 1050 1051 "Make an instantiator function from a method, keeping all arguments." 1052 1053 function = Function(self.parent.name, self.parent.parent, self.argnames, self.defaults, 1054 self.has_star, self.has_dstar, self.module, self.astnode) 1055 function.default_attrs = self.default_attrs 1056 return function 1057 1058 class UnresolvedName(NamespaceDict, Constant): 1059 1060 "A module, class or function which was mentioned but could not be imported." 1061 1062 def __init__(self, name, parent_name, module=None): 1063 NamespaceDict.__init__(self, module) 1064 self.name = name 1065 self.parent_name = parent_name 1066 self.parent = None 1067 1068 self.descendants = set() 1069 1070 def add_descendant(self, cls): 1071 self.descendants.add(cls) 1072 1073 def all_class_attributes(self): 1074 return {} 1075 1076 def instance_attributes(self): 1077 return {} 1078 1079 def __repr__(self): 1080 return "UnresolvedName(%r, %r)" % (self.name, self.parent_name) 1081 1082 __shortrepr__ = __repr__ 1083 1084 def full_name(self): 1085 if self.name is not None: 1086 return self.parent_name + "." + self.name 1087 else: 1088 return self.parent_name 1089 1090 class Module(NamespaceDict, Constant): 1091 1092 "An inspected module's core details." 1093 1094 def __init__(self, name): 1095 NamespaceDict.__init__(self, self) 1096 self.name = name 1097 self.parent = None 1098 1099 # Original location details. 1100 1101 self.astnode = None 1102 1103 # Complete lists of classes and functions. 1104 1105 self.all_objects = set() 1106 1107 # Keyword records. 1108 1109 self.keyword_names = set() 1110 1111 # Image generation details. 1112 1113 self.location = None 1114 self.code_location = None 1115 1116 # Program-related details. 1117 1118 self.blocks = None 1119 self.temp_usage = 0 1120 self.local_usage = 0 1121 self.all_local_usage = 0 1122 1123 def full_name(self): 1124 return self.name 1125 1126 def __repr__(self): 1127 if self.location is not None: 1128 return "Module(%r, location=%r)" % (self.name, self.location) 1129 else: 1130 return "Module(%r)" % self.name 1131 1132 def __shortrepr__(self): 1133 return "Module(%r)" % self.name 1134 1135 # Attribute methods. 1136 1137 "Return the module attribute names provided by the module." 1138 1139 module_attribute_names = NamespaceDict.keys 1140 1141 def module_attributes(self): 1142 1143 "Return a dictionary mapping names to module attributes." 1144 1145 return dict(self) 1146 1147 # vim: tabstop=4 expandtab shiftwidth=4