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