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