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