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