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