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