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.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 locals.used_in_scope(name, "global") and not name in locals.globals: 287 raise InspectError("Name %r already used as global." % name) 288 elif 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 943 # Locals. 944 945 elif self.namespaces and self.namespaces[-1].has_key(name): 946 attr = self.namespaces[-1][name] 947 948 # Note usage of the local (potentially a class attribute). 949 950 self.use_specific_attribute(None, name) 951 952 # Globals. 953 954 elif self.has_key(name): 955 attr = self[name] 956 957 # Note usage of the module attribute. 958 959 self.use_specific_attribute(self.full_name(), name) 960 961 # Note global usage in any local namespace. 962 963 if self.namespaces: 964 if not self.namespaces[-1].note_scope(name, "global"): 965 raise InspectError("Name %r cannot be used as global." % name) 966 967 # Builtins. 968 969 elif self.builtins is not None and self.builtins.has_key(name): 970 attr = self.builtins[name] 971 self.use_specific_attribute(self.builtins.full_name(), name) 972 973 # Note builtins usage in any local namespace. 974 975 if self.namespaces: 976 if not self.namespaces[-1].note_scope(name, "builtins"): 977 raise InspectError("Name %r cannot be used as a built-in." % name) 978 else: 979 if not self.note_scope(name, "builtins"): 980 raise InspectError("Name %r cannot be used as a built-in." % name) 981 982 # Unknown. 983 984 else: 985 attr = None 986 self.use_name(name) 987 988 return attr 989 990 visitNot = OP 991 992 visitOr = OP 993 994 visitPass = NOP 995 996 visitPower = _visitBinary 997 998 visitPrint = NOP 999 1000 visitPrintnl = NOP 1001 1002 visitRaise = NOP_ABANDON 1003 1004 visitReturn = NOP_ABANDON 1005 1006 visitRightShift = _visitBinary 1007 1008 visitSlice = OP 1009 1010 visitSliceobj = OP 1011 1012 def visitStmt(self, node): 1013 for n in node.nodes: 1014 self.dispatch(n) 1015 return None 1016 1017 visitSub = _visitBinary 1018 1019 def visitSubscript(self, node): 1020 self.use_name("__getitem__", node) 1021 self.OP(node) 1022 1023 def visitTryExcept(self, node): 1024 self.dispatch(node.body) 1025 1026 self.new_branchpoint() 1027 1028 for name, var, n in node.handlers: 1029 self.new_branch() 1030 1031 # Establish the local for the handler. 1032 1033 if var is not None: 1034 self.dispatch(var) 1035 if n is not None: 1036 self.dispatch(n) 1037 1038 self.shelve_branch() 1039 1040 if node.else_ is not None: 1041 self.new_branch() 1042 self.dispatch(node.else_) 1043 self.shelve_branch() 1044 1045 self.merge_branches() 1046 return None 1047 1048 visitTryFinally = NOP 1049 1050 visitTuple = OP 1051 1052 visitUnaryAdd = _visitUnary 1053 1054 visitUnarySub = _visitUnary 1055 1056 def visitWhile(self, node): 1057 self.new_branchpoint() 1058 1059 # Propagate attribute usage to branches. 1060 1061 in_loop = self.in_loop 1062 self.in_loop = 1 1063 self.dispatch(node.test) 1064 self.new_branch(node) 1065 self.dispatch(node.body) 1066 self.shelve_branch() 1067 self.in_loop = in_loop 1068 1069 # Maintain a branch for the else clause or the current retained usage 1070 # where execution avoids the conditional clauses. 1071 # NOTE: Consider merging here before the else clause. 1072 1073 self.new_branch() 1074 if node.else_ is not None: 1075 self.dispatch(node.else_) 1076 self.shelve_branch() 1077 1078 self.merge_branches() 1079 return None 1080 1081 visitWith = NOP 1082 1083 visitYield = NOP 1084 1085 # vim: tabstop=4 expandtab shiftwidth=4