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