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