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 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 the module 66 namespace or in class 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 * 76 from micropython.data import * 77 import compiler.ast 78 from compiler.visitor import ASTVisitor 79 80 # Program visitors. 81 82 class InspectedModule(ASTVisitor, Module): 83 84 """ 85 An inspected module, providing core details via the Module superclass, but 86 capable of being used as an AST visitor. 87 """ 88 89 def __init__(self, name, importer): 90 91 """ 92 Initialise this visitor with a module 'name' and an 'importer' which is 93 used to provide access to other modules when required. 94 """ 95 96 ASTVisitor.__init__(self) 97 Module.__init__(self, name) 98 self.visitor = self 99 100 # Import machinery links. 101 102 self.importer = importer 103 self.optimisations = importer.optimisations 104 self.builtins = self.importer.modules.get("__builtins__") 105 self.loaded = 0 106 107 # Current expression state. 108 109 self.expr = None 110 111 # Namespace state. 112 113 self.in_init = 0 # Find instance attributes in __init__ methods. 114 self.in_method = 0 # Find instance attributes in all methods. 115 self.in_function = 0 # Note function presence, affecting definitions. 116 self.in_loop = 0 # Note loop "membership", affecting assignments. 117 self.namespaces = [] 118 self.module = None 119 self.functions = [] 120 121 def parse(self, filename): 122 123 "Parse the file having the given 'filename'." 124 125 module = compiler.parseFile(filename) 126 self.process(module) 127 128 def process(self, module): 129 130 "Process the given 'module'." 131 132 self.astnode = self.module = module 133 134 # Add __name__ to the namespace by adding an explicit assignment to the 135 # module. 136 137 module.node.nodes.insert(0, compiler.ast.Assign( 138 [compiler.ast.AssName("__name__", 0)], 139 compiler.ast.Const(self.full_name()) 140 )) 141 142 # First, visit module-level code, recording global names. 143 144 processed = self.dispatch(module) 145 146 # Then, for each function, detect and record globals declared in those 147 # functions. 148 149 for node, namespaces in self.functions: 150 self.process_globals(node) 151 152 self.finalise_namespace(self) 153 154 # Then, visit each function, recording other names. 155 156 for node, namespaces in self.functions: 157 self._visitFunctionBody(node, namespaces) 158 self.finalise_namespace(namespaces[-1]) 159 160 # Add references to other modules declared using the __all__ global. 161 162 if self.has_key("__all__"): 163 all = self["__all__"] 164 if isinstance(all, compiler.ast.List): 165 for n in all.nodes: 166 self.store(n.value, self.importer.add_module(self.name + "." + n.value)) 167 168 return processed 169 170 def process_globals(self, node): 171 172 """ 173 Within the given 'node', process global declarations, adjusting the 174 module namespace. 175 """ 176 177 for n in node.getChildNodes(): 178 if isinstance(n, compiler.ast.Global): 179 for name in n.names: 180 if not self.has_key(name): 181 self[name] = None 182 else: 183 self.process_globals(n) 184 185 def finalise_namespace(self, namespace): 186 187 "Finalise the given 'namespace'." 188 189 for names in namespace.get_all_attribute_usage(): 190 self.importer.use_names(names, namespace.full_name()) 191 192 def vacuum(self): 193 194 """ 195 Vacuum the module namespace, removing unreferenced objects and unused 196 names. 197 """ 198 199 if self.should_optimise_unused_objects(): 200 self.vacuum_object(self) 201 202 all_objects = list(self.all_objects) 203 204 for obj in all_objects: 205 if isinstance(obj, Class): 206 self.vacuum_object(obj) 207 208 def vacuum_object(self, obj, delete_all=0): 209 210 "Vacuum the given object 'obj'." 211 212 for name, attr in obj.items(): 213 214 # Only consider deleting entire unused objects or things accessible 215 # via names which are never used. 216 217 if delete_all or not self.importer.uses_attribute(obj, name): 218 del obj[name] 219 220 # Delete any unambiguous attribute value. Such values can only 221 # have been defined within the object and therefore are not 222 # redefined by other code regions. 223 224 if attr.assignments == 1: 225 value = attr.get_value() 226 227 if value is not obj and value in self.all_objects: 228 self.all_objects.remove(value) 229 230 # Delete class contents. 231 232 if isinstance(value, Class): 233 self.vacuum_object(value, 1) 234 235 def unfinalise(self): 236 237 "Reset finalised information for the module." 238 239 for obj in self.all_objects: 240 obj.unfinalise_attributes() 241 242 def finalise(self): 243 244 "Finalise the module." 245 246 for obj in self.all_objects: 247 obj.finalise_attributes() 248 249 def add_object(self, obj, any_scope=0): 250 251 """ 252 Record 'obj' if non-local or if the optional 'any_scope' is set to a 253 true value. 254 """ 255 256 if any_scope or not (self.namespaces and isinstance(self.namespaces[-1], Function)): 257 self.all_objects.add(obj) 258 259 # Optimisation tests. 260 261 def should_optimise_unused_objects(self): 262 return "unused_objects" in self.optimisations 263 264 # Namespace methods. 265 266 def in_class(self, namespaces=None): 267 namespaces = namespaces or self.namespaces 268 return len(namespaces) > 1 and isinstance(namespaces[-2], Class) 269 270 def store(self, name, obj): 271 272 "Record attribute or local 'name', storing 'obj'." 273 274 if not self.namespaces: 275 self.set(name, obj, not self.in_loop) 276 else: 277 self.namespaces[-1].set(name, obj, not self.in_loop) 278 279 def store_lambda(self, obj): 280 281 "Store a lambda function 'obj'." 282 283 self.add_object(obj) 284 285 def store_module_attr(self, name, module): 286 287 """ 288 Record module attribute 'name' in the given 'module' using the current 289 expression. 290 """ 291 292 module.set(name, self.expr, 0) 293 294 def store_class_attr(self, name): 295 296 """ 297 Record class attribute 'name' in the current class using the current 298 expression. 299 """ 300 301 if self.in_method and self.namespaces[-2].has_key(name): 302 self.namespaces[-2].set(name, self.expr, 0) 303 return 1 304 305 return 0 306 307 def store_instance_attr(self, name): 308 309 "Record instance attribute 'name' in the current class." 310 311 if self.in_method: 312 313 # Current namespace is the function. 314 # Previous namespace is the class. 315 316 self.namespaces[-2].add_instance_attribute(name) 317 318 def get_namespace(self): 319 320 "Return the parent (or most recent) namespace currently exposed." 321 322 return (self.namespaces[-1:] or [self])[0] 323 324 def use_name(self, name, node=None): 325 326 """ 327 Use the given 'name' within the current namespace/unit, either in 328 conjunction with a particular object (if 'node' is specified and not 329 None) or unconditionally. 330 """ 331 332 if node is not None and isinstance(node, compiler.ast.Name): 333 self.use_attribute(node.name, name) 334 335 # For general name usage, declare usage of the given name from this 336 # particular unit. 337 338 else: 339 unit = self.get_namespace() 340 self.importer.use_name(name, unit.full_name()) 341 342 # Attribute usage methods. 343 # These are convenience methods which refer to the specific namespace's 344 # implementation of these operations. 345 346 def new_branchpoint(self): 347 self.get_namespace()._new_branchpoint() 348 349 def new_branch(self, loop_node=None): 350 self.get_namespace()._new_branch(loop_node) 351 352 def abandon_branch(self): 353 self.get_namespace()._abandon_branch() 354 355 def shelve_branch(self): 356 self.get_namespace()._shelve_branch() 357 358 def merge_branches(self): 359 self.get_namespace()._merge_branches() 360 361 def define_attribute_user(self, node): 362 363 """ 364 Define 'node' as the user of attributes, indicating the point where the 365 user is defined. 366 """ 367 368 self.get_namespace()._define_attribute_user(node) 369 370 def use_attribute(self, name, attrname): 371 372 "Note usage on the attribute user 'name' of the attribute 'attrname'." 373 374 return self.get_namespace()._use_attribute(name, attrname) 375 376 def use_specific_attribute(self, objname, attrname): 377 378 """ 379 Note attribute usage specifically on 'objname' - an object which is 380 known at inspection time - or in the current unit if 'objname' is None, 381 nominating a specific attribute 'attrname'. 382 383 This bypasses attribute user mechanisms. 384 """ 385 386 from_name = self.get_namespace().full_name() 387 objname = objname or from_name 388 self.importer.use_specific_name(objname, attrname, from_name) 389 390 # Visitor methods. 391 392 def default(self, node, *args): 393 raise InspectError(self.full_name(), node, "Node class %r is not supported." % node.__class__) 394 395 def NOP(self, node): 396 for n in node.getChildNodes(): 397 self.dispatch(n) 398 return None 399 400 def NOP_ABANDON(self, node): 401 self.NOP(node) 402 self.abandon_branch() 403 404 def OP(self, node): 405 for n in node.getChildNodes(): 406 self.dispatch(n) 407 return Instance() 408 409 # Generic support for classes of operations. 410 411 def _visitUnary(self, node): 412 413 "Accounting method for the unary operator 'node'." 414 415 method = unary_methods[node.__class__.__name__] 416 self.use_name(method, node) 417 return self.OP(node) 418 419 def _visitBinary(self, node): 420 421 "Accounting method for the binary operator 'node'." 422 423 left_method, right_method = binary_methods[node.__class__.__name__] 424 self.use_name(left_method, node) 425 self.use_name(right_method, node) 426 return self.OP(node) 427 428 def _visitFunction(self, node, name): 429 430 """ 431 Return a function object for the function defined by 'node' with the 432 given 'name'. If a lambda expression is being visited, 'name' should be 433 None. 434 """ 435 436 # Define the function object. 437 438 function = Function( 439 name, 440 self.get_namespace(), 441 node.argnames, 442 node.defaults, 443 (node.flags & 4 != 0), 444 (node.flags & 8 != 0), 445 self.in_loop or self.in_function, 446 self, 447 node 448 ) 449 450 self.add_object(function, any_scope=1) 451 452 # Make a back reference from the node for code generation. 453 454 node.unit = function 455 456 # Process the defaults. 457 458 for n in node.defaults: 459 self.expr = self.dispatch(n) 460 function.store_default(self.expr) 461 462 self.functions.append((node, self.namespaces + [function])) 463 464 # Store the function. 465 466 if name is not None: 467 self.store(name, function) 468 else: 469 self.store_lambda(function) 470 471 # Test the defaults and assess whether an dynamic object will result. 472 473 function.make_dynamic() 474 return function 475 476 def _visitFunctionBody(self, node, namespaces): 477 478 "Enter the function." 479 480 # Current namespace is the function. 481 # Previous namespace is the class. 482 483 if self.in_class(namespaces): 484 if namespaces[-1].name == "__init__": 485 self.in_init = 1 486 self.in_method = 1 487 488 in_function = self.in_function 489 in_loop = self.in_loop 490 self.in_function = 1 491 self.in_loop = 0 492 493 self.namespaces = namespaces 494 self.dispatch(node.code) 495 496 self.in_loop = in_loop 497 self.in_function = in_function 498 self.in_init = 0 499 self.in_method = 0 500 501 # Specific handler methods. 502 503 visitAdd = _visitBinary 504 505 visitAnd = OP 506 507 visitAssert = NOP 508 509 def visitAssign(self, node): 510 self.expr = self.dispatch(node.expr) 511 for n in node.nodes: 512 self.dispatch(n) 513 return None 514 515 def visitAssAttr(self, node): 516 expr = self.dispatch(node.expr) 517 518 # Record the attribute on the presumed target. 519 520 if isinstance(expr, Attr): 521 if expr.name == "self": 522 if not self.store_class_attr(node.attrname): 523 self.store_instance_attr(node.attrname) 524 elif isinstance(expr.get_value(), Module): 525 self.store_module_attr(node.attrname, expr.get_value()) 526 print "Warning: attribute %r of module %r set outside the module." % (node.attrname, expr.get_value().name) 527 528 # Note usage of the attribute where a local is involved. 529 530 if expr.parent is self.get_namespace(): 531 node._attrusers = self.use_attribute(expr.name, node.attrname) 532 node._username = expr.name 533 534 return None 535 536 def visitAssList(self, node): 537 538 # Declare names which will be used by generated code. 539 540 self.use_name("__getitem__", node) 541 542 # Process the assignment. 543 544 for i, n in enumerate(node.nodes): 545 self.dispatch(n) 546 self.importer.make_constant(i) # for __getitem__(i) at run-time 547 return None 548 549 def visitAssName(self, node): 550 if hasattr(node, "flags") and node.flags == "OP_DELETE": 551 print "Warning: deletion of attribute %r in %r is not supported." % (node.name, self.full_name()) 552 #raise InspectError(self.full_name(), node, "Deletion of attribute %r is not supported." % node.name) 553 554 self.store(node.name, self.expr) 555 self.define_attribute_user(node) 556 557 # Ensure the presence of the given name in this namespace. 558 559 self.use_specific_attribute(None, node.name) 560 return None 561 562 visitAssTuple = visitAssList 563 564 def visitAugAssign(self, node): 565 566 # Accounting. 567 568 aug_method, (left_method, right_method) = augassign_methods[node.op] 569 self.use_name(aug_method, node) 570 self.use_name(left_method, node) 571 self.use_name(right_method, node) 572 573 # Process the assignment. 574 575 self.expr = self.dispatch(node.expr) 576 577 # NOTE: Similar to micropython.ast handler code. 578 # NOTE: Slices and subscripts not supported. 579 580 if isinstance(node.node, compiler.ast.Name): 581 self.visitAssName(node.node) 582 elif isinstance(node.node, compiler.ast.Getattr): 583 self.visitAssAttr(node.node) 584 else: 585 raise InspectError(self.full_name(), node, "AugAssign(Slice or Subscript)") 586 587 return None 588 589 visitBackquote = OP 590 591 visitBitand = _visitBinary 592 593 visitBitor = _visitBinary 594 595 visitBitxor = _visitBinary 596 597 visitBreak = NOP_ABANDON 598 599 visitCallFunc = OP 600 601 def visitClass(self, node): 602 603 """ 604 Register the class at the given 'node' subject to the restrictions 605 mentioned in the module docstring. 606 """ 607 608 if self.namespaces: 609 print "Class %r in %r is not global: ignored." % (node.name, self.namespaces[-1].full_name()) 610 return None 611 else: 612 if self.in_loop: 613 print "Warning: class %r in %r defined in a loop." % (node.name, self.full_name()) 614 615 cls = Class(node.name, self.get_namespace(), self, node) 616 617 # Visit the base class expressions, attempting to find concrete 618 # definitions of classes. 619 620 for base in node.bases: 621 expr = self.dispatch(base) 622 if isinstance(expr, Attr): 623 if expr.assignments != 1: 624 raise InspectError(self.full_name(), node, 625 "Base class %r for %r is not constant." % (base, cls.full_name())) 626 else: 627 cls.add_base(expr.get_value()) 628 else: # if expr is None: 629 raise InspectError(self.full_name(), node, 630 "Base class %r for %r is not found: it may be hidden in some way." % (base, cls.full_name())) 631 632 # NOTE: Potentially dubious measure to permit __init__ availability. 633 # If no bases exist, adopt the 'object' class. 634 635 if not node.bases and not (self.name == "__builtins__" and node.name == "object") : 636 expr = self.dispatch(compiler.ast.Name("object")) 637 cls.add_base(expr.get_value()) 638 639 # Make a back reference from the node for code generation. 640 641 node.unit = cls 642 643 # Make an entry for the class. 644 645 self.store(node.name, cls) 646 self.add_object(cls) 647 648 # Process the class body. 649 650 self.namespaces.append(cls) 651 self.dispatch(node.code) 652 self.finalise_namespace(cls) 653 self.namespaces.pop() 654 655 return cls 656 657 def visitCompare(self, node): 658 659 # Accounting. 660 # NOTE: Replicates some code in micropython.ast.visitCompare. 661 662 this_node = node 663 664 for op in node.ops: 665 op_name, next_node = op 666 667 # Get the applicable methods. 668 669 methods = comparison_methods[op_name] 670 671 # Define name/attribute usage. 672 673 if methods is not None: 674 self.use_name(methods[0], this_node) 675 self.use_name(methods[1], next_node) 676 elif op_name.endswith("in"): 677 self.use_name("__contains__", next_node) 678 679 this_node = next_node 680 681 return self.OP(node) 682 683 def visitConst(self, node): 684 685 # Register the constant, if necessary, returning the resulting object. 686 687 self.use_name(self.importer.get_constant_type_name(node.value), node) 688 return self.importer.make_constant(node.value) 689 690 visitContinue = NOP_ABANDON 691 692 visitDecorators = NOP 693 694 visitDict = OP 695 696 visitDiscard = NOP 697 698 visitDiv = _visitBinary 699 700 visitEllipsis = NOP 701 702 visitExec = NOP 703 704 visitExpression = OP 705 706 visitFloorDiv = _visitBinary 707 708 def visitFor(self, node): 709 self.new_branchpoint() 710 711 # Declare names which will be used by generated code. 712 713 self.use_name("__iter__", node.list) 714 self.use_name("next") 715 716 in_loop = self.in_loop 717 self.in_loop = 1 718 self.dispatch(node.assign) 719 self.dispatch(node.list) 720 721 # Enter the loop. 722 # Propagate attribute usage to branches. 723 724 self.new_branch() 725 self.dispatch(node.body) 726 self.shelve_branch() 727 self.in_loop = in_loop 728 729 # Maintain a branch for the else clause or the current retained usage 730 # where execution avoids the conditional clauses. 731 732 self.new_branch() 733 if node.else_ is not None: 734 self.dispatch(node.else_) 735 self.shelve_branch() 736 737 self.merge_branches() 738 return None 739 740 def visitFrom(self, node): 741 module = self.importer.load(node.modname, 1) 742 743 #if module is None: 744 # print "Warning:", node.modname, "not imported." 745 746 for name, alias in node.names: 747 if name != "*": 748 if module is not None and module.has_key(name): 749 attr = module[name] 750 self.store(alias or name, attr) 751 if isinstance(attr.get_value(), Module) and not attr.get_value().loaded: 752 self.importer.load(attr.get_value().name) 753 754 # Support the import of names from missing modules. 755 756 else: 757 self.store(alias or name, UnresolvedName(name, node.modname, self)) 758 else: 759 if module is not None: 760 for n in module.keys(): 761 attr = module[n] 762 self.store(n, attr) 763 if isinstance(attr.get_value(), Module) and not attr.get_value().loaded: 764 self.importer.load(attr.get_value().name) 765 766 return None 767 768 def visitFunction(self, node): 769 return self._visitFunction(node, node.name) 770 771 visitGenExpr = OP 772 773 visitGenExprFor = NOP 774 775 visitGenExprIf = NOP 776 777 visitGenExprInner = NOP 778 779 def visitGetattr(self, node): 780 expr = self.dispatch(node.expr) 781 attrname = node.attrname 782 783 # Attempt to identify the nature of the attribute. 784 785 if isinstance(expr, Attr): 786 value = expr.get_value() 787 788 # Get the attribute and record its usage. 789 790 if isinstance(value, (Class, Module)): 791 attr = value.get(attrname) 792 self.use_specific_attribute(value.full_name(), attrname) 793 794 elif isinstance(value, UnresolvedName): 795 attr = UnresolvedName(attrname, value.full_name(), self) 796 797 else: 798 attr = None 799 800 # Note usage of the attribute where a local is involved. 801 802 if expr.parent is self.get_namespace(): 803 node._attrusers = self.use_attribute(expr.name, attrname) 804 node._username = expr.name 805 else: 806 self.use_name(attrname, node.expr) 807 808 elif self.builtins is not None: 809 attr = self.builtins.get(attrname) 810 self.use_specific_attribute(self.builtins.full_name(), attrname) 811 812 else: 813 attr = UnresolvedName(attrname, value.full_name(), self) 814 815 return attr 816 817 def visitGlobal(self, node): 818 if self.namespaces: 819 for name in node.names: 820 ns = self.namespaces[-1] 821 if not ns.make_global(name): 822 raise InspectError(ns.full_name(), node, "Name %r is global and local in %r" % (name, ns.full_name())) 823 824 # The name is recorded in an earlier process. 825 826 def visitIf(self, node): 827 self.new_branchpoint() 828 829 # Propagate attribute usage to branches. 830 831 for test, body in node.tests: 832 self.dispatch(test) 833 834 self.new_branch() 835 self.dispatch(body) 836 self.shelve_branch() 837 838 # Maintain a branch for the else clause or the current retained usage 839 # where execution avoids the conditional clauses. 840 841 self.new_branch() 842 if node.else_ is not None: 843 self.dispatch(node.else_) 844 self.shelve_branch() 845 846 self.merge_branches() 847 return None 848 849 visitIfExp = NOP 850 851 def visitImport(self, node): 852 for name, alias in node.names: 853 if alias is not None: 854 module = self.importer.load(name, 1) or UnresolvedName(None, name, self) 855 self.store(alias, module) 856 else: 857 module = self.importer.load(name) or UnresolvedName(None, name.split(".")[0], self) 858 self.store(name.split(".")[0], module) 859 860 return None 861 862 visitInvert = _visitUnary 863 864 def visitKeyword(self, node): 865 self.dispatch(node.expr) 866 self.importer.make_constant(node.name) 867 self.keyword_names.add(node.name) 868 return None 869 870 def visitLambda(self, node): 871 self.use_name(None) # lambda functions have no names but are assumed to be invoked 872 return self._visitFunction(node, None) 873 874 visitLeftShift = _visitBinary 875 876 visitList = OP 877 878 visitListComp = OP 879 880 visitListCompFor = NOP 881 882 visitListCompIf = NOP 883 884 visitMod = _visitBinary 885 886 def visitModule(self, node): 887 888 # Make a back reference from the node for code generation. 889 890 node.unit = self 891 return self.dispatch(node.node) 892 893 visitMul = _visitBinary 894 895 def visitName(self, node): 896 name = node.name 897 898 # Constants. 899 900 if self.importer.predefined_constants.has_key(name): 901 attr = self.importer.get_predefined_constant(name) 902 903 # Locals. 904 905 elif self.namespaces and self.namespaces[-1].has_key(name): 906 attr = self.namespaces[-1][name] 907 908 # Note usage of the local (potentially a class attribute). 909 910 self.use_specific_attribute(None, name) 911 912 # Globals. 913 914 elif self.has_key(name): 915 attr = self[name] 916 917 # Note usage of the module attribute. 918 919 self.use_specific_attribute(self.full_name(), name) 920 921 # Builtins. 922 923 elif self.builtins is not None and self.builtins.has_key(name): 924 attr = self.builtins[name] 925 self.use_specific_attribute(self.builtins.full_name(), name) 926 927 # Unknown. 928 929 else: 930 attr = None 931 self.use_name(name) 932 933 return attr 934 935 visitNot = OP 936 937 visitOr = OP 938 939 visitPass = NOP 940 941 visitPower = _visitBinary 942 943 visitPrint = NOP 944 945 visitPrintnl = NOP 946 947 visitRaise = NOP_ABANDON 948 949 visitReturn = NOP_ABANDON 950 951 visitRightShift = _visitBinary 952 953 visitSlice = OP 954 955 visitSliceobj = OP 956 957 def visitStmt(self, node): 958 for n in node.nodes: 959 self.dispatch(n) 960 return None 961 962 visitSub = _visitBinary 963 964 def visitSubscript(self, node): 965 self.use_name("__getitem__", node) 966 self.OP(node) 967 968 def visitTryExcept(self, node): 969 self.dispatch(node.body) 970 971 self.new_branchpoint() 972 973 for name, var, n in node.handlers: 974 self.new_branch() 975 976 # Establish the local for the handler. 977 978 if var is not None: 979 self.dispatch(var) 980 if n is not None: 981 self.dispatch(n) 982 983 self.shelve_branch() 984 985 if node.else_ is not None: 986 self.new_branch() 987 self.dispatch(node.else_) 988 self.shelve_branch() 989 990 self.merge_branches() 991 return None 992 993 visitTryFinally = NOP 994 995 visitTuple = OP 996 997 visitUnaryAdd = _visitUnary 998 999 visitUnarySub = _visitUnary 1000 1001 def visitWhile(self, node): 1002 self.new_branchpoint() 1003 1004 # Propagate attribute usage to branches. 1005 1006 in_loop = self.in_loop 1007 self.in_loop = 1 1008 self.dispatch(node.test) 1009 self.new_branch(node) 1010 self.dispatch(node.body) 1011 self.shelve_branch() 1012 self.in_loop = in_loop 1013 1014 # Maintain a branch for the else clause or the current retained usage 1015 # where execution avoids the conditional clauses. 1016 # NOTE: Consider merging here before the else clause. 1017 1018 self.new_branch() 1019 if node.else_ is not None: 1020 self.dispatch(node.else_) 1021 self.shelve_branch() 1022 1023 self.merge_branches() 1024 return None 1025 1026 visitWith = NOP 1027 1028 visitYield = NOP 1029 1030 # vim: tabstop=4 expandtab shiftwidth=4