1 #!/usr/bin/env python 2 3 """ 4 Inspect source files, obtaining details of classes and attributes. 5 6 Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013 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 results of inspecting a module are as follows: 24 25 Constants 26 --------- 27 28 All constants identified within the code shall be registered. 29 30 Classes 31 ------- 32 33 All global classes shall be registered; local classes (within functions) or 34 nested classes (within classes) are not currently registered. 35 36 Base classes must be detected and constant. 37 38 All classes without bases are made to inherit from __builtins__.object in order 39 to support some standard methods. 40 41 Functions 42 --------- 43 44 All functions and lambda definitions shall be registered. 45 46 Namespaces 47 ---------- 48 49 Modules define their own "global" namespace, within which classes, functions 50 and lambda definitions establish a hierarchy of namespaces. 51 52 Only local, global and built-in namespaces are recognised; closures are not 53 supported. 54 55 Assignments 56 ----------- 57 58 Name assignment and attribute assignment involving modules and classes cause 59 names to be associated with values within namespaces. 60 61 Any assignments within loops are considered to cause the targets of such 62 assignments to provide non-constant values. 63 64 Assignments to names are only really considered to cause the targets of such 65 assignments to provide constant values if the targets reside in class 66 namespaces, subject to the above conditions. 67 68 Assignments to names within functions are not generally considered to cause the 69 targets of such assignments to provide constant values since functions can be 70 invoked many times with different inputs. This affects particularly the 71 definition of functions or lambdas within functions. However, there may be 72 benefits in considering a local to be constant within a single invocation. 73 """ 74 75 from micropython.common import ASTVisitor, operator_functions 76 from micropython.data import * 77 from micropython.errors import * 78 import compiler.ast 79 import sys 80 81 class NullBranch(compiler.ast.AttributeUser): 82 83 "A class representing an attribute user for a non-existent branch." 84 85 pass 86 87 # Program visitors. 88 89 class InspectedModule(ASTVisitor, Module): 90 91 """ 92 An inspected module, providing core details via the Module superclass, but 93 capable of being used as an AST visitor. 94 95 A module can be inspected through the invocation of the following methods in 96 order: 97 98 1. parse 99 2. process 100 3. vacuum 101 4. finalise 102 103 A module importer can be expected to perform these invocations. 104 """ 105 106 def __init__(self, name, importer): 107 108 """ 109 Initialise this visitor with a module 'name' and an 'importer' which is 110 used to provide access to other modules when required. 111 """ 112 113 Module.__init__(self, name, importer) 114 self.visitor = self 115 116 # Import machinery links. 117 118 self.builtins = self.importer.modules.get("__builtins__") 119 self.loaded = False 120 self.completed = False 121 122 # Current expression state. 123 124 self.expr = None 125 self.in_assignment = False # For slice and subscript handling. 126 127 # Namespace state. 128 129 self.in_method = False # Find instance attributes in all methods. 130 self.in_function = False # Note function presence, affecting definitions. 131 self.in_loop = False # Note loop "membership", affecting assignments. 132 self.namespaces = [] 133 self.functions = [] 134 135 def parse(self, filename): 136 137 "Parse the file having the given 'filename'." 138 139 self.astnode = module = compiler.parseFile(filename) 140 141 # Detect and record imports and globals declared in the module. 142 143 self.process_structure(module) 144 145 def complete(self): 146 if not self.completed: 147 self.completed = True 148 self.process() 149 if self.importer.verbose: 150 print >>sys.stderr, "Completed import of", self.full_name() 151 152 def process(self): 153 return self.process_module(self.astnode) 154 155 def process_module(self, module): 156 157 """ 158 Process the given 'module', visiting module-level code and function 159 code. 160 """ 161 162 # Add __name__ to the namespace. 163 164 self.store("__name__", self._visitConst(self.full_name())) 165 166 # Visit module-level code, also recording global names. 167 168 processed = self.dispatch(module) 169 170 self.finalise_attribute_usage() 171 172 # Visit functions. 173 174 self.process_functions() 175 176 # Add references to other modules declared using the __all__ global. 177 178 if self.has_key("__all__"): 179 all = self["__all__"] 180 if isinstance(all, compiler.ast.List): 181 for n in all.nodes: 182 self.store(n.value, self.importer.add_module(self.name + "." + n.value)) 183 184 return processed 185 186 def process_functions(self): 187 188 """ 189 Process all function bodies. Deferred imports may occur during this 190 process. 191 """ 192 193 # Then, visit each function, recording other names. This happens to 194 # work for lambda definitions inside functions since they are added to 195 # the end of self.functions and are thus visited as the iteration 196 # reaches the end of the original list. 197 198 for node, namespaces in self.functions: 199 self._visitFunctionBody(node, namespaces) 200 namespaces[-1].finalise_attribute_usage() 201 202 def process_structure(self, node): 203 204 """ 205 Within the given 'node', process global declarations, adjusting the 206 module namespace, and import statements, building a module dependency 207 hierarchy. 208 """ 209 210 for n in node.getChildNodes(): 211 212 # Module global detection. 213 214 if isinstance(n, compiler.ast.Global): 215 for name in n.names: 216 217 # Each name may potentially be assigned many times. 218 # We don't try and find out the specifics at this point and 219 # just indicate that the name cannot be relied upon for 220 # various observations. 221 222 self.modify_name(name) 223 224 # Module import declarations. 225 226 elif isinstance(n, compiler.ast.From): 227 modname, names = self.get_module_name(n) 228 229 # Perform whole module relative imports. 230 231 if not modname: 232 for name, alias in names: 233 self.record_import(name, n) 234 235 # Otherwise, perform normal "from" imports. 236 237 else: 238 # Load the mentioned module. 239 240 self.record_import(modname, n) 241 242 # Speculatively load modules for names beneath the module. 243 244 for name, alias in n.names: 245 subname = modname + "." + name 246 self.record_import(subname, n) 247 248 elif isinstance(n, compiler.ast.Import): 249 250 # Load the mentioned module. 251 252 for name, alias in n.names: 253 self.record_import(name, n) 254 255 # Nodes using operator module functions. 256 257 elif operator_functions.has_key(n.__class__.__name__) or \ 258 isinstance(n, (compiler.ast.AugAssign, compiler.ast.Compare)): 259 260 n._module = self.importer.load("operator") 261 262 else: 263 self.process_structure(n) 264 265 def get_module_name(self, node): 266 267 """ 268 Using the given From 'node', calculate any relative import information, 269 returning a tuple containing a module to import along with any names to 270 import based on the node's name information. 271 272 Where the returned module is given as None, whole module imports should 273 be performed for the returned modules using the returned names. 274 """ 275 276 # Absolute import. 277 278 if node.level == 0: 279 return node.modname, node.names 280 281 # Relative to this module. 282 283 elif node.level == 1: 284 basename = self.full_name() 285 286 # Relative to an ancestor of this module. 287 288 else: 289 path = self.full_name().split(".") 290 if node.level > len(path): 291 raise InspectError("Relative import %r involves too many levels up from module %r" % (("." * node.level + node.modname), self.full_name())) 292 basename = ".".join(path[:-node.level+1]) 293 294 # Name imports from a module. 295 296 if node.modname: 297 return "%s.%s" % (basename, node.modname), node.names 298 299 # Relative whole module imports. 300 301 else: 302 return None, [("%s.%s" % (basename, name), alias) for name, alias in node.names] 303 304 def get_module_paths(self, name): 305 306 """ 307 Return the paths of modules leading to the module having the given 308 'name'. 309 """ 310 311 names = [] 312 parts = [] 313 for part in name.split("."): 314 parts.append(part) 315 names.append(".".join(parts)) 316 return names 317 318 def record_import(self, name, node): 319 320 """ 321 Record an import of a module with the given 'name' occurring at the 322 given 'node'. 323 """ 324 325 module = self.importer.load(name, 1, importer=node) 326 if module and not module.loaded: 327 self.importer.circular_imports.add(module) 328 329 def complete_import(self, name, return_leaf): 330 331 """ 332 Complete the import of the module with the given 'name', returning the 333 module itself if 'return_leaf' is a true value, or returning the root of 334 the module hierarchy if 'return_leaf' is a false value. 335 """ 336 337 top = module = None 338 339 for modname in self.get_module_paths(name): 340 341 # Attempt to get the module, returning None for non-existent 342 # modules. 343 344 try: 345 module = self.importer.get_module(modname) 346 except KeyError: 347 return None 348 349 if module: 350 module.complete() 351 352 if top is None: 353 top = module 354 355 if return_leaf: 356 return module 357 else: 358 return top 359 360 def vacuum(self): 361 362 """ 363 Vacuum the module namespace, removing unreferenced objects and unused 364 names. 365 """ 366 367 self.vacuum_object(self) 368 369 all_objects = list(self.all_objects) 370 371 for obj in all_objects: 372 self.vacuum_object(obj) 373 374 def vacuum_object(self, obj, delete_all=0): 375 376 "Vacuum the given object 'obj'." 377 378 # Get all constant objects in apparent use. 379 380 if delete_all: 381 obj_objects = set() 382 else: 383 obj_objects = [] 384 for name, attr in obj.items_for_vacuum(): 385 386 # Get constant objects for attributes in use. 387 388 if self.importer.uses_attribute(obj.full_name(), name) and \ 389 attr is not None and attr.is_constant(): 390 391 value = attr.get_value() 392 obj_objects.append(value) 393 394 # Now vacuum unused attributes and objects not in use. 395 396 for name, attr in obj.items_for_vacuum(): 397 398 # Only consider deleting entire unused objects or things accessible 399 # via names which are never used. 400 401 if delete_all or not self.importer.uses_attribute(obj.full_name(), name): 402 obj.vacuum_item(name) 403 404 # Delete any unambiguous attribute value. Such values can only 405 # have been defined within the object and therefore are not 406 # redefined by other code regions. 407 408 if attr is not None and attr.is_constant(): 409 value = attr.get_value() 410 411 # The value must have this object as a parent. 412 # However, it must not be shared by several names. 413 414 if value is not obj and value.parent is obj and \ 415 value in self.all_objects and value not in obj_objects: 416 417 self.all_objects.remove(value) 418 419 # Delete class contents and lambdas from functions. 420 421 self.vacuum_object(value, 1) 422 423 def unfinalise(self): 424 425 "Reset finalised information for the module." 426 427 for obj in self.all_objects: 428 obj.unfinalise_attributes() 429 430 def finalise(self, objtable): 431 432 "Finalise the module." 433 434 for obj in self.all_objects: 435 obj.finalise(objtable) 436 437 self.finalise_users(objtable) 438 439 def add_object(self, obj, any_scope=0): 440 441 """ 442 Record 'obj' if non-local or if the optional 'any_scope' is set to a 443 true value. 444 """ 445 446 if any_scope or not (self.namespaces and isinstance(self.namespaces[-1], Function)): 447 self.all_objects.add(obj) 448 449 # Namespace methods. 450 451 def in_class(self, namespaces=None): 452 namespaces = namespaces or self.namespaces 453 return len(namespaces) > 1 and isinstance(namespaces[-2], Class) 454 455 def store(self, name, obj): 456 457 "Record attribute or local 'name', storing 'obj'." 458 459 # Store in the module. 460 461 if not self.namespaces: 462 if self.in_loop and self.used_in_scope(name, "builtins"): 463 raise InspectError("Name %r already used as a built-in." % name) 464 else: 465 self.set(name, obj, not self.in_loop) 466 467 # Or store locally. 468 469 else: 470 locals = self.namespaces[-1] 471 472 if self.in_loop and locals.used_in_scope(name, "global") and not name in locals.globals: 473 raise InspectError("Name %r already used as global." % name) 474 elif self.in_loop and locals.used_in_scope(name, "builtins"): 475 raise InspectError("Name %r already used as a built-in." % name) 476 else: 477 locals.set(name, obj, not self.in_loop) 478 479 def store_lambda(self, obj): 480 481 "Store a lambda function 'obj'." 482 483 self.add_object(obj) 484 self.get_namespace().add_lambda(obj) 485 486 def store_module_attr(self, name, module): 487 488 """ 489 Record module attribute 'name' in the given 'module' using the current 490 expression. 491 """ 492 493 module.set(name, self.expr, 0) 494 self.use_specific_attribute(module.full_name(), name) 495 496 def store_class_attr(self, name, cls): 497 498 """ 499 Record class attribute 'name' in the given class 'cls' using the current 500 expression. 501 """ 502 503 cls.set(name, self.expr, 0) 504 self.use_specific_attribute(cls.full_name(), name) 505 506 def store_instance_attr(self, name, tentative=False): 507 508 """ 509 Record instance attribute 'name' in the current class. If 'tentative' is 510 set to a true value, the instance attribute will be discarded if a class 511 attribute is observed. 512 """ 513 514 if self.in_method: 515 516 # Current namespace is the function. 517 # Previous namespace is the class. 518 519 cls = self.namespaces[-2] 520 cls.add_instance_attribute(name, tentative) 521 522 # NOTE: The instance attribute, although defined in a specific 523 # NOTE: class, obviously appears in all descendant classes. 524 525 self.use_specific_attribute(cls.full_name(), name) 526 527 def get_namespace(self): 528 529 "Return the parent (or most recent) namespace currently exposed." 530 531 return (self.namespaces[-1:] or [self])[0] 532 533 get_unit = get_namespace # compatibility method for error handling 534 535 def use_name(self, name, node=None, value=None, ns=None): 536 537 """ 538 Use the given 'name' within the current namespace/unit, either in 539 conjunction with a particular object (if 'node' is specified and not 540 None) or unconditionally. 541 """ 542 543 unit = self.get_namespace() 544 545 # Handle attribute usage situations within the current unit. 546 547 if node is not None and isinstance(node, compiler.ast.Name) and ns is unit: 548 self.use_attribute(node.name, name, value) 549 550 # For general name usage, declare usage of the given name from this 551 # particular unit. 552 553 else: 554 self.importer.use_name(name, unit.full_name(), value) 555 556 def use_constant(self, const): 557 558 "Use the given 'const' within the current namespace/unit." 559 560 unit = self.get_namespace() 561 self.importer.use_constant(const, unit.full_name()) 562 563 # Attribute usage methods. 564 # These are convenience methods which refer to the specific namespace's 565 # implementation of these operations. 566 567 def new_branchpoint(self, loop_node=None): 568 self.get_namespace()._new_branchpoint(loop_node) 569 570 def new_branch(self, node): 571 self.get_namespace()._new_branch(node) 572 573 def abandon_branch(self): 574 self.get_namespace()._abandon_branch() 575 576 def suspend_broken_branch(self): 577 self.get_namespace()._suspend_broken_branch() 578 579 def suspend_continuing_branch(self): 580 self.get_namespace()._suspend_continuing_branch() 581 582 def shelve_branch(self): 583 self.get_namespace()._shelve_branch() 584 585 def merge_branches(self): 586 self.get_namespace()._merge_branches() 587 588 def resume_broken_branches(self): 589 self.get_namespace()._resume_broken_branches() 590 591 def resume_continuing_branches(self): 592 self.get_namespace()._resume_continuing_branches() 593 594 def resume_abandoned_branches(self): 595 self.get_namespace()._resume_abandoned_branches() 596 597 def define_attribute_user(self, node): 598 599 """ 600 Define 'node' as the user of attributes, indicating the point where the 601 user is defined. 602 """ 603 604 self.get_namespace()._define_attribute_user(node) 605 606 def use_attribute(self, name, attrname, value=None): 607 608 """ 609 Note usage on the attribute user 'name' of the attribute 'attrname', 610 noting an assignment if 'value' is specified. 611 """ 612 613 return self.get_namespace()._use_attribute(name, attrname, value) 614 615 def use_specific_attribute(self, objname, attrname, from_name=None): 616 617 """ 618 Note usage on the object having the given 'objname' of the attribute 619 'attrname'. If 'objname' is None, the current namespace is chosen as the 620 object providing the attribute. 621 """ 622 623 return self.get_namespace()._use_specific_attribute(objname, attrname, from_name) 624 625 def define_attribute_accessor(self, name, attrname, node, value=None): 626 627 """ 628 Note applicable attribute users providing the given 'name' when 629 accessing the given 'attrname' on the specified 'node', with the 630 optional 'value' indicating an assignment. 631 """ 632 633 self.get_namespace()._define_attribute_accessor(name, attrname, node, value) 634 635 # Visitor methods. 636 637 def default(self, node, *args): 638 raise InspectError("Node class %r is not supported." % node.__class__) 639 640 def NOP(self, node): 641 for n in node.getChildNodes(): 642 self.dispatch(n) 643 644 def NOP_ABANDON(self, node): 645 self.NOP(node) 646 self.abandon_branch() 647 648 def TEST_NOP(self, node): 649 self.use_name("__bool__", node) 650 self.NOP(node) 651 652 def OP(self, node): 653 for n in node.getChildNodes(): 654 self.dispatch(n) 655 return make_instance() 656 657 def TEST_OP(self, node): 658 self.use_name("__bool__", node) 659 self.new_branchpoint() 660 661 # Propagate attribute usage to branches. 662 # Each node starts a new conditional region, effectively making a deeply 663 # nested collection of if-like statements. 664 665 for n in node.nodes: 666 self.new_branch(n) 667 self.dispatch(n) 668 669 # The nested regions must be terminated. 670 671 for n in node.nodes: 672 self.shelve_branch() 673 674 self.merge_branches() 675 return make_instance() 676 677 # Generic support for classes of operations. 678 679 def _ensureOperators(self, node): 680 attr, scope, namespace = self._get_with_scope("$operator") 681 if attr is None: 682 module = node._module 683 module.complete() 684 self["$operator"] = module 685 else: 686 module = attr.get_value() 687 return module 688 689 def _visitOperator(self, node, operator_name=None): 690 691 "Accounting method for the operator 'node'." 692 693 operator_module = self._ensureOperators(node) 694 operator_fn = operator_functions[operator_name or node.__class__.__name__] 695 self.use_specific_attribute(operator_module.full_name(), operator_fn) 696 return self.OP(node) 697 698 def _visitAttr(self, expr, attrname, node): 699 700 """ 701 Process the attribute provided by the given 'expr' with the given 702 'attrname' and involving the given 'node'. 703 """ 704 705 # Attempt to identify the nature of the attribute. 706 707 if isinstance(expr, Attr): 708 value = expr.get_value() 709 710 # Get the attribute and record its usage. 711 # NOTE: Need to provide concrete values for things like base classes 712 # NOTE: while also handling module attribute modification. 713 714 # Only specific class attributes are detected here since class 715 # attribute finalisation has not yet occurred. 716 717 if isinstance(value, (Class, Module)): 718 719 # Check for class.__class__. 720 721 if attrname == "__class__" and isinstance(value, Class): 722 attr = get_constant_class("type") 723 else: 724 attr = value.get(attrname) or make_instance() 725 self.use_specific_attribute(value.full_name(), attrname) 726 727 elif isinstance(value, UnresolvedName): 728 attr = UnresolvedName(attrname, value.full_name(), self) 729 730 # The actual attribute is not readily identifiable and is assumed 731 # to be an instance. 732 733 else: 734 735 # Record any instance attributes. 736 737 if expr.name == "self": 738 self.store_instance_attr(attrname, tentative=True) 739 740 attr = make_instance() 741 742 # Note usage of the attribute where a local is involved. 743 744 self._visitAttrUser(expr, attrname, node) 745 746 # Constants provide specific kinds of expressions. 747 # NOTE: If attributes are accessed on a pre-made, but not yet defined 748 # NOTE: class, no useful attribute will be available. 749 750 elif isinstance(expr, Const): 751 attr = get_constant_class(expr.get_class_name()).all_attributes().get(attrname) or make_instance() 752 753 # No particular attribute has been identified, thus a general instance 754 # is assumed. 755 756 else: 757 attr = make_instance() 758 self.use_name(attrname, node) 759 760 return attr 761 762 def _visitAttrUser(self, expr, attrname, node, value=None): 763 764 """ 765 Note usage of the attribute provided by 'expr' with the given 'attrname' 766 where a local is involved, annotating the given 'node'. If the optional 767 'value' is given, note an assignment for future effects on attributes 768 where such attributes are inferred from the usage. 769 """ 770 771 # Access to attributes via a local in functions, classes or modules. 772 # Since module-level locals are globals that can be modified 773 # independently of the namespace, any attribute usage observations made 774 # here may be revoked later if such modification is thought to occur. 775 776 if expr.parent is self.get_namespace(): 777 self.define_attribute_accessor(expr.name, attrname, node, value) 778 else: 779 self.use_name(attrname, node.expr, value, ns=expr.parent) 780 781 def _visitConst(self, value): 782 783 """ 784 Register the constant given by 'value', if necessary, returning the 785 resulting object. The type name is noted as being used, thus preserving 786 the class in any generated program. 787 """ 788 789 self.use_specific_attribute("__builtins__", self.importer.get_constant_type_name(value)) 790 const = self.importer.make_constant(value) 791 self.use_constant(const) 792 return const 793 794 def _visitFunction(self, node, name): 795 796 """ 797 Return a function object for the function defined by 'node' with the 798 given 'name'. If a lambda expression is being visited, 'name' should be 799 None. 800 """ 801 802 # Define the function object. 803 804 function = get_function( 805 name, 806 self.get_namespace(), 807 node.argnames, 808 node.defaults, 809 (node.flags & 4 != 0), 810 (node.flags & 8 != 0), 811 self.in_loop or self.in_function, 812 self, 813 node 814 ) 815 816 self.add_object(function, any_scope=1) 817 818 # Make a back reference from the node for code generation. 819 820 node.unit = function 821 822 # Process the defaults. 823 824 for n in node.defaults: 825 self.expr = self.dispatch(n) 826 function.store_default(self.expr) 827 828 # Note attribute usage where tuple parameters are involved. 829 830 if function.tuple_parameters(): 831 self.use_name("__getitem__", node) 832 833 # Record the namespace context of the function for later processing. 834 835 self.functions.append((node, self.namespaces + [function])) 836 837 # Store the function. 838 839 if name is not None: 840 self.store(name, function) 841 else: 842 self.store_lambda(function) 843 844 # Test the defaults and assess whether an dynamic object will result. 845 846 function.make_dynamic() 847 return function 848 849 def _visitFunctionBody(self, node, namespaces): 850 851 "Enter the function." 852 853 # Current namespace is the function. 854 # Previous namespace is the class. 855 856 if self.in_class(namespaces): 857 self.in_method = True 858 859 in_function = self.in_function 860 in_loop = self.in_loop 861 self.in_function = True 862 self.in_loop = False 863 864 self.namespaces = namespaces 865 self.dispatch(node.code) 866 867 self.in_loop = in_loop 868 self.in_function = in_function 869 self.in_method = False 870 871 # Specific handler methods. 872 873 visitAdd = _visitOperator 874 875 visitAnd = TEST_OP 876 877 visitAssert = NOP 878 879 def visitAssign(self, node): 880 self.expr = self.dispatch(node.expr) 881 self.in_assignment = True 882 for n in node.nodes: 883 self.dispatch(n) 884 self.in_assignment = False 885 886 def visitAssAttr(self, node): 887 expr = self.dispatch(node.expr) 888 attrname = node.attrname 889 890 # Record the attribute on the presumed target. 891 892 if isinstance(expr, Attr): 893 value = expr.get_value() 894 895 if expr.name == "self": 896 self.store_instance_attr(attrname) 897 self.use_attribute(expr.name, attrname, value) 898 self._visitAttrUser(expr, attrname, node, self.expr) 899 900 # No definite attribute can be identified, since the instance 901 # being accessed may be a subclass of the method's class. 902 903 attr = make_instance() 904 905 elif isinstance(value, Module): 906 self.store_module_attr(attrname, value) 907 attr = value.get(attrname) 908 909 elif isinstance(value, Class): 910 self.store_class_attr(attrname, value) 911 attr = value.get(attrname) 912 913 # Note usage of the attribute where a local is involved. 914 915 else: 916 self._visitAttrUser(expr, attrname, node, self.expr) 917 attr = make_instance() 918 919 else: 920 self.use_name(attrname, node) 921 attr = make_instance() 922 923 node._expr = expr 924 node._attr = attr 925 926 def visitAssList(self, node): 927 928 # Declare names which will be used by generated code. 929 930 self.use_name("__getitem__", node) 931 932 # Process the assignment. 933 934 for i, n in enumerate(node.nodes): 935 self.dispatch(n) 936 self._visitConst(i) # for __getitem__(i) at run-time 937 938 def visitAssName(self, node): 939 if node.flags == "OP_DELETE": 940 print >>sys.stderr, "Warning: deletion of attribute %r in %r is not supported." % (node.name, self.full_name()) 941 #raise InspectError("Deletion of attribute %r is not supported." % node.name) 942 self._visitAssName(node) 943 944 def _visitAssName(self, node): 945 self.store(node.name, self.expr) 946 self.define_attribute_user(node) 947 948 # Ensure the presence of the given name in this namespace. 949 # NOTE: Consider not registering assignments involving methods, since 950 # NOTE: this is merely creating aliases for such methods. 951 952 if isinstance(self.get_namespace(), (Class, Module)): 953 if not isinstance(self.expr, Attr) or not isinstance(self.expr.get_value(), Function): 954 self.use_specific_attribute(None, node.name) 955 else: 956 fn = self.expr.get_value() 957 ns = self.get_namespace().full_name() 958 self.use_specific_attribute(fn.parent.full_name(), fn.name, "%s.%s" % (ns, node.name)) 959 960 visitAssTuple = visitAssList 961 962 def visitAugAssign(self, node): 963 964 # Accounting. 965 966 operator_fn = operator_functions.get(node.op) 967 operator_module = self._ensureOperators(node) 968 self.use_specific_attribute(operator_module.full_name(), operator_fn) 969 970 # Process the assignment. 971 972 self.expr = self.dispatch(node.expr) 973 974 # NOTE: Similar to micropython.ast handler code. 975 # NOTE: Slices and subscripts are supported by __setitem__(slice) and 976 # NOTE: not __setslice__. 977 978 if isinstance(node.node, compiler.ast.Name): 979 self._visitAssName(node.node) 980 elif isinstance(node.node, compiler.ast.Getattr): 981 self.visitAssAttr(node.node) 982 else: 983 self.dispatch(node.node) 984 self.use_specific_attribute("__builtins__", "slice") 985 self.use_name("__setitem__", node) 986 987 visitBackquote = OP 988 989 visitBitand = _visitOperator 990 991 visitBitor = _visitOperator 992 993 visitBitxor = _visitOperator 994 995 def visitBreak(self, node): 996 self.NOP(node) 997 self.suspend_broken_branch() 998 999 visitCallFunc = OP 1000 1001 def visitClass(self, node): 1002 1003 """ 1004 Register the class at the given 'node' subject to the restrictions 1005 mentioned in the module docstring. 1006 """ 1007 1008 if self.namespaces: 1009 print >>sys.stderr, "Warning: class %r in %r is not global: ignored." % (node.name, self.namespaces[-1].full_name()) 1010 return 1011 else: 1012 if self.in_loop: 1013 print >>sys.stderr, "Warning: class %r in %r defined in a loop." % (node.name, self.full_name()) 1014 1015 cls = get_class(node.name, self.get_namespace(), self, node) 1016 1017 # Make a back reference from the node for code generation. 1018 1019 node.unit = cls 1020 1021 # Process base classes in the context of the class's namespace. 1022 # This confines references to such classes to the class instead of 1023 # the namespace in which it is defined. 1024 1025 self.namespaces.append(cls) 1026 1027 # Visit the base class expressions, attempting to find concrete 1028 # definitions of classes. 1029 1030 for base in node.bases: 1031 expr = self.dispatch(base) 1032 1033 # Each base class must be constant and known at compile-time. 1034 1035 if isinstance(expr, Attr): 1036 if expr.assignments != 1: 1037 raise InspectError("Base class %r for %r is not constant: %r" % (base, cls.full_name(), expr)) 1038 elif not isinstance(expr.get_value(), Class): 1039 raise InspectError("Base class %r for %r is not a class: %r" % (base, cls.full_name(), expr.get_value())) 1040 else: 1041 cls.add_base(expr.get_value()) 1042 1043 # Where no expression value is available, the base class is 1044 # not identifiable. 1045 1046 else: 1047 raise InspectError("Base class %r for %r is not found: it may be hidden in some way." % (base, cls.full_name())) 1048 1049 # NOTE: Potentially dubious measure to permit __init__ availability. 1050 # If no bases exist, adopt the 'object' class. 1051 1052 if not node.bases and not (self.name == "__builtins__" and node.name == "object"): 1053 expr = self.dispatch(compiler.ast.Name("object")) 1054 cls.add_base(expr.get_value()) 1055 1056 # Make an entry for the class in the parent namespace. 1057 1058 self.namespaces.pop() 1059 self.store(node.name, cls) 1060 self.define_attribute_user(node) 1061 self.add_object(cls) 1062 1063 # Process the class body in its own namespace. 1064 # Add __name__ to the namespace. 1065 1066 self.namespaces.append(cls) 1067 self.store("__name__", self._visitConst(node.name)) 1068 self.dispatch(node.code) 1069 self.namespaces.pop() 1070 1071 cls.finalise_attribute_usage() 1072 return cls 1073 1074 def visitCompare(self, node): 1075 1076 # Accounting. 1077 # NOTE: Replicates some code in micropython.ast.visitCompare. 1078 1079 self.use_name("__bool__", node) 1080 1081 this_node = node 1082 1083 for op in node.ops: 1084 op_name, next_node = op 1085 1086 # Define name/attribute usage. 1087 # Get the applicable operation. 1088 1089 operator_fn = operator_functions.get(op_name) 1090 1091 # For operators, reference the specific function involved. 1092 1093 if operator_fn is not None: 1094 operator_module = self._ensureOperators(node) 1095 self.use_specific_attribute(operator_module.full_name(), operator_fn) 1096 1097 # Define __contains__ usage on the next node. 1098 1099 elif op_name.endswith("in"): 1100 self.use_name("__contains__", next_node) 1101 1102 this_node = next_node 1103 1104 return self.OP(node) 1105 1106 def visitConst(self, node): 1107 return self._visitConst(node.value) 1108 1109 def visitContinue(self, node): 1110 self.NOP(node) 1111 self.suspend_continuing_branch() 1112 1113 visitDecorators = NOP 1114 1115 visitDict = OP 1116 1117 visitDiscard = NOP 1118 1119 visitDiv = _visitOperator 1120 1121 visitEllipsis = NOP 1122 1123 visitExec = NOP 1124 1125 visitExpression = OP 1126 1127 visitFloorDiv = _visitOperator 1128 1129 def visitFor(self, node): 1130 self.new_branchpoint(node) 1131 1132 # Declare names which will be used by generated code. 1133 1134 self.use_name("__iter__", node.list) 1135 self.use_name("next") 1136 self.use_name("StopIteration") 1137 1138 in_loop = self.in_loop 1139 self.in_loop = True 1140 self.dispatch(node.list) 1141 1142 # NOTE: Could generate AST nodes for the actual operations instead of 1143 # NOTE: manually generating code in micropython.ast. 1144 1145 self.expr = make_instance() # each element is a result of a function call 1146 self.dispatch(node.assign) 1147 1148 # Enter the loop. 1149 # Propagate attribute usage to branches. 1150 1151 self.new_branch(node) 1152 self.dispatch(node.body) 1153 1154 self.resume_continuing_branches() 1155 1156 self.shelve_branch() 1157 1158 self.in_loop = in_loop 1159 1160 # A null branch is used to record a path around the loop. 1161 1162 self.new_branch(node.else_ or NullBranch()) 1163 self.shelve_branch() 1164 1165 self.merge_branches() 1166 1167 # The else clause is evaluated outside any branch. 1168 1169 if node.else_ is not None: 1170 self.dispatch(node.else_) 1171 1172 # Any suspended branches from the loop can now be resumed. 1173 1174 self.resume_broken_branches() 1175 1176 def visitFrom(self, node): 1177 modname, names = self.get_module_name(node) 1178 1179 if not modname: 1180 return self._visitImport(names) 1181 1182 module = self.complete_import(modname, True) 1183 1184 for name, alias in node.names: 1185 1186 # For specific names, obtain and store referenced objects using 1187 # the name or any alias provided in the current namespace. 1188 1189 if name != "*": 1190 if module: 1191 1192 # Missing names may refer to submodules. 1193 1194 submodule = self.complete_import(modname + "." + name, True) 1195 if submodule: 1196 if not module.has_key(name): 1197 module.store(name, submodule) 1198 1199 # Complete the import if the name was found. 1200 1201 if module.has_key(name): 1202 attr = module[name] 1203 self.store(alias or name, attr) 1204 self.use_specific_attribute(module.full_name(), name) 1205 continue 1206 1207 # Support the import of names from missing modules. 1208 1209 self.store(alias or name, UnresolvedName(name, modname, self)) 1210 1211 # For wildcards, obtain and store all objects from a module in the 1212 # current namespace. 1213 1214 else: 1215 if module: 1216 for n in module.keys(): 1217 attr = module[n] 1218 self.store(n, attr) 1219 self.use_specific_attribute(module.full_name(), n) 1220 1221 def visitFunction(self, node): 1222 return self._visitFunction(node, node.name) 1223 1224 visitGenExpr = OP 1225 1226 visitGenExprFor = NOP 1227 1228 visitGenExprIf = NOP 1229 1230 visitGenExprInner = NOP 1231 1232 def visitGetattr(self, node): 1233 node._expr = self.dispatch(node.expr) 1234 node._attr = self._visitAttr(node._expr, node.attrname, node) 1235 return node._attr 1236 1237 def visitGlobal(self, node): 1238 if self.namespaces: 1239 for name in node.names: 1240 ns = self.namespaces[-1] 1241 if not ns.make_global(name): 1242 raise InspectError("Name %r is global and local in %r" % (name, ns.full_name())) 1243 1244 # The name is recorded in an earlier process. 1245 1246 def visitIf(self, node): 1247 self.use_name("__bool__", node) 1248 self.new_branchpoint() 1249 1250 # Propagate attribute usage to branches. 1251 1252 for test, body in node.tests: 1253 self.dispatch(test) 1254 1255 self.new_branch(body) 1256 self.dispatch(body) 1257 self.shelve_branch() 1258 1259 # Maintain a branch for the else clause. 1260 1261 self.new_branch(node.else_ or NullBranch()) 1262 if node.else_ is not None: 1263 self.dispatch(node.else_) 1264 self.shelve_branch() 1265 1266 self.merge_branches() 1267 1268 def visitIfExp(self, node): 1269 self.use_name("__bool__", node) 1270 self.new_branchpoint() 1271 1272 # Propagate attribute usage to branches. 1273 1274 self.dispatch(node.test) 1275 1276 self.new_branch(node.then) 1277 self.dispatch(node.then) 1278 self.shelve_branch() 1279 1280 self.new_branch(node.else_) 1281 self.dispatch(node.else_) 1282 self.shelve_branch() 1283 1284 self.merge_branches() 1285 return make_instance() # either outcome is possible 1286 1287 def visitImport(self, node): 1288 self._visitImport(node.names) 1289 1290 def _visitImport(self, names): 1291 for name, alias in names: 1292 module = self.complete_import(name, alias) 1293 if alias is not None: 1294 self.store(alias, module or UnresolvedName(None, name, self)) 1295 else: 1296 name_used = name.split(".")[0] 1297 self.store(name_used, module or UnresolvedName(None, name_used, self)) 1298 1299 visitInvert = _visitOperator 1300 1301 def visitKeyword(self, node): 1302 self.dispatch(node.expr) 1303 self._visitConst(node.name) 1304 self.keyword_names.add(node.name) 1305 1306 def visitLambda(self, node): 1307 fn = self._visitFunction(node, None) 1308 self.use_specific_attribute(None, fn.name) 1309 return fn 1310 1311 visitLeftShift = _visitOperator 1312 1313 def visitList(self, node): 1314 self.use_specific_attribute("__builtins__", "list") 1315 return self.OP(node) 1316 1317 def visitListComp(self, node): 1318 1319 # Note that explicit dispatch is performed. 1320 1321 if node.quals: 1322 self.visitListCompFor(node.quals[0], node.quals[1:], node.expr) 1323 return make_instance() 1324 1325 def visitListCompFor(self, node, following_quals, expr): 1326 self.new_branchpoint() 1327 1328 # Declare names which will be used by generated code. 1329 1330 self.use_name("__iter__", node.list) 1331 self.use_name("next") 1332 1333 in_loop = self.in_loop 1334 self.in_loop = True 1335 self.dispatch(node.list) 1336 1337 # NOTE: Could generate AST nodes for the actual operations instead of 1338 # NOTE: manually generating code in micropython.ast. 1339 1340 self.expr = make_instance() # each element is a result of a function call 1341 self.dispatch(node.assign) 1342 1343 # Enter the loop. 1344 # Propagate attribute usage to branches. 1345 1346 self.new_branch(node) 1347 1348 # Note that explicit dispatch is performed. 1349 1350 if node.ifs: 1351 self.visitListCompIf(node.ifs[0], node.ifs[1:], following_quals, expr) 1352 elif following_quals: 1353 self.visitListCompFor(following_quals[0], following_quals[1:], expr) 1354 else: 1355 self.dispatch(expr) 1356 1357 self.shelve_branch() 1358 self.in_loop = in_loop 1359 1360 self.merge_branches() 1361 1362 def visitListCompIf(self, node, following_ifs, following_quals, expr): 1363 self.use_name("__bool__", node) 1364 self.new_branchpoint() 1365 1366 # Propagate attribute usage to branches. 1367 1368 self.dispatch(node.test) 1369 1370 # Note that explicit dispatch is performed. 1371 1372 if following_ifs: 1373 self.visitListCompIf(following_ifs[0], following_ifs[1:], following_quals, expr) 1374 elif following_quals: 1375 self.visitListCompFor(following_quals[0], following_quals[1:], expr) 1376 else: 1377 self.new_branch(expr) 1378 self.dispatch(expr) 1379 self.shelve_branch() 1380 1381 # Maintain a branch for the else clause. 1382 1383 self.new_branch(NullBranch()) 1384 self.shelve_branch() 1385 1386 self.merge_branches() 1387 1388 visitMod = _visitOperator 1389 1390 def visitModule(self, node): 1391 1392 # Make a back reference from the node for code generation. 1393 1394 node.unit = self 1395 return self.dispatch(node.node) 1396 1397 visitMul = _visitOperator 1398 1399 def visitName(self, node): 1400 attr = self.get_namespace().get_using_node(node.name, node) or make_instance() 1401 node._attr = attr 1402 return attr 1403 1404 def visitNot(self, node): 1405 self.use_name("__bool__", node) 1406 self.dispatch(node.expr) 1407 return make_instance() 1408 1409 visitOr = TEST_OP 1410 1411 visitPass = NOP 1412 1413 visitPower = _visitOperator 1414 1415 def _visitPrint(self, node, function_name): 1416 self.NOP(node) 1417 self.use_specific_attribute("__builtins__", function_name) 1418 1419 def visitPrint(self, node): 1420 self._visitPrint(node, "_print") 1421 1422 def visitPrintnl(self, node): 1423 self._visitPrint(node, "_printnl") 1424 1425 visitRaise = NOP_ABANDON 1426 1427 visitReturn = NOP_ABANDON 1428 1429 visitRightShift = _visitOperator 1430 1431 def visitSlice(self, node): 1432 return self._visitOperator(node, self.in_assignment and "AssSlice" or "Slice") 1433 1434 visitSliceobj = OP 1435 1436 def visitStmt(self, node): 1437 for n in node.nodes: 1438 self.dispatch(n) 1439 1440 visitSub = _visitOperator 1441 1442 def visitSubscript(self, node): 1443 return self._visitOperator(node, self.in_assignment and "AssSubscript" or "Subscript") 1444 1445 def visitTryExcept(self, node): 1446 self.new_branchpoint() 1447 self.dispatch(node.body) 1448 1449 for name, var, n in node.handlers: 1450 if name is not None: 1451 self.dispatch(name) 1452 1453 self.new_branch(n) 1454 1455 # Any abandoned branches from the body can now be resumed. 1456 1457 self.resume_abandoned_branches() 1458 1459 # Establish the local for the handler. 1460 1461 if var is not None: 1462 self.dispatch(var) 1463 if n is not None: 1464 self.dispatch(n) 1465 1466 self.shelve_branch() 1467 1468 # The else clause maintains the usage from the body but without the 1469 # abandoned branches since they would never lead to the else clause 1470 # being executed. 1471 1472 self.new_branch(node.else_ or NullBranch()) 1473 if node.else_ is not None: 1474 self.dispatch(node.else_) 1475 self.shelve_branch() 1476 1477 self.merge_branches() 1478 1479 visitTryFinally = NOP 1480 1481 visitTuple = OP 1482 1483 visitUnaryAdd = _visitOperator 1484 1485 visitUnarySub = _visitOperator 1486 1487 def visitWhile(self, node): 1488 self.use_name("__bool__", node) 1489 self.new_branchpoint(node) 1490 1491 # Propagate attribute usage to branches. 1492 1493 in_loop = self.in_loop 1494 self.in_loop = True 1495 1496 # The test is evaluated initially and again in the loop. 1497 1498 self.dispatch(node.test) 1499 1500 self.new_branch(node) 1501 self.dispatch(node.body) 1502 1503 self.resume_continuing_branches() 1504 1505 self.dispatch(node.test) 1506 self.shelve_branch() 1507 1508 self.in_loop = in_loop 1509 1510 # A null branch is used to record a path around the loop. 1511 1512 self.new_branch(node.else_ or NullBranch()) 1513 self.shelve_branch() 1514 1515 self.merge_branches() 1516 1517 # The else clause is evaluated outside any branch. 1518 1519 if node.else_ is not None: 1520 self.dispatch(node.else_) 1521 1522 # Any suspended branches from the loop can now be resumed. 1523 1524 self.resume_broken_branches() 1525 1526 visitWith = NOP 1527 1528 visitYield = NOP 1529 1530 # vim: tabstop=4 expandtab shiftwidth=4