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