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. process_functions 94 3. vacuum 95 4. finalise 96 97 A module importer can be expected to perform these invocations. 98 """ 99 100 def __init__(self, name, importer): 101 102 """ 103 Initialise this visitor with a module 'name' and an 'importer' which is 104 used to provide access to other modules when required. 105 """ 106 107 Module.__init__(self, name, importer) 108 self.visitor = self 109 110 # Import machinery links. 111 112 self.optimisations = self.importer.optimisations 113 self.builtins = self.importer.modules.get("__builtins__") 114 self.loaded = 0 115 116 # Current expression state. 117 118 self.expr = None 119 self.in_assignment = 0 # For slice and subscript handling. 120 121 # Namespace state. 122 123 self.in_method = 0 # Find instance attributes in all methods. 124 self.in_function = 0 # Note function presence, affecting definitions. 125 self.in_loop = 0 # Note loop "membership", affecting assignments. 126 self.namespaces = [] 127 self.functions = [] 128 129 def parse(self, filename): 130 131 "Parse the file having the given 'filename'." 132 133 module = compiler.parseFile(filename) 134 self.process(module) 135 136 def process(self, module): 137 138 """ 139 Process the given 'module', visiting only module-level code and only 140 extracting global declarations from functions. In order to support 141 deferred imports, the function code is processed separately after all 142 modules have been initially processed. 143 """ 144 145 self.astnode = module 146 147 # Add __name__ to the namespace. 148 149 self.store("__name__", self._visitConst(self.full_name())) 150 151 # Detect and record globals declared in the module. 152 153 self.process_globals(module) 154 155 # Visit module-level code, also recording global names. 156 157 processed = self.dispatch(module) 158 159 self.finalise_attribute_usage() 160 161 # Add references to other modules declared using the __all__ global. 162 163 if self.has_key("__all__"): 164 all = self["__all__"] 165 if isinstance(all, compiler.ast.List): 166 for n in all.nodes: 167 self.store(n.value, self.importer.add_module(self.name + "." + n.value)) 168 169 return processed 170 171 def process_functions(self): 172 173 """ 174 Process all function bodies. Deferred imports may occur during this 175 process. 176 """ 177 178 # Then, visit each function, recording other names. This happens to 179 # work for lambda definitions inside functions since they are added to 180 # the end of self.functions and are thus visited as the iteration 181 # reaches the end of the original list. 182 183 for node, namespaces in self.functions: 184 self._visitFunctionBody(node, namespaces) 185 namespaces[-1].finalise_attribute_usage() 186 187 def process_globals(self, node): 188 189 """ 190 Within the given 'node', process global declarations, adjusting the 191 module namespace. 192 """ 193 194 for n in node.getChildNodes(): 195 if isinstance(n, compiler.ast.Global): 196 for name in n.names: 197 198 # Each name may potentially be assigned many times. 199 # NOTE: We don't try and find out the specifics at this 200 # NOTE: point and just set an instance instead. 201 202 self.set(name, make_instance(), False) 203 self.modified_names.add(name) 204 205 else: 206 self.process_globals(n) 207 208 def vacuum(self): 209 210 """ 211 Vacuum the module namespace, removing unreferenced objects and unused 212 names. 213 """ 214 215 if self.should_optimise_unused_objects(): 216 self.vacuum_object(self) 217 218 all_objects = list(self.all_objects) 219 220 for obj in all_objects: 221 self.vacuum_object(obj) 222 223 def vacuum_object(self, obj, delete_all=0): 224 225 "Vacuum the given object 'obj'." 226 227 # Get all constant objects in apparent use. 228 229 if delete_all: 230 obj_objects = set() 231 else: 232 obj_objects = [] 233 for name, attr in obj.items_for_vacuum(): 234 235 # Get constant objects for attributes in use. 236 237 if self.importer.uses_attribute(obj.full_name(), name) and \ 238 attr is not None and attr.is_constant(): 239 240 value = attr.get_value() 241 obj_objects.append(value) 242 243 # Now vacuum unused attributes and objects not in use. 244 245 for name, attr in obj.items_for_vacuum(): 246 247 # Only consider deleting entire unused objects or things accessible 248 # via names which are never used. 249 250 if delete_all or not self.importer.uses_attribute(obj.full_name(), name): 251 obj.vacuum_item(name) 252 253 # Delete any unambiguous attribute value. Such values can only 254 # have been defined within the object and therefore are not 255 # redefined by other code regions. 256 257 if attr is not None and attr.is_constant(): 258 value = attr.get_value() 259 260 # The value must have this object as a parent. 261 # However, it must not be shared by several names. 262 263 if value is not obj and value.parent is obj and \ 264 value in self.all_objects and value not in obj_objects: 265 266 self.all_objects.remove(value) 267 268 # Delete class contents and lambdas from functions. 269 270 self.vacuum_object(value, 1) 271 272 def unfinalise(self): 273 274 "Reset finalised information for the module." 275 276 for obj in self.all_objects: 277 obj.unfinalise_attributes() 278 279 def finalise(self, objtable): 280 281 "Finalise the module." 282 283 for obj in self.all_objects: 284 obj.finalise(objtable) 285 286 self.finalise_users(objtable) 287 288 def add_object(self, obj, any_scope=0): 289 290 """ 291 Record 'obj' if non-local or if the optional 'any_scope' is set to a 292 true value. 293 """ 294 295 if any_scope or not (self.namespaces and isinstance(self.namespaces[-1], Function)): 296 self.all_objects.add(obj) 297 298 # Optimisation tests. 299 300 def should_optimise_unused_objects(self): 301 return "unused_objects" in self.optimisations 302 303 # Namespace methods. 304 305 def in_class(self, namespaces=None): 306 namespaces = namespaces or self.namespaces 307 return len(namespaces) > 1 and isinstance(namespaces[-2], Class) 308 309 def store(self, name, obj): 310 311 "Record attribute or local 'name', storing 'obj'." 312 313 # Store in the module. 314 315 if not self.namespaces: 316 if self.in_loop and self.used_in_scope(name, "builtins"): 317 raise InspectError("Name %r already used as a built-in." % name) 318 else: 319 self.set(name, obj, not self.in_loop) 320 321 # Or store locally. 322 323 else: 324 locals = self.namespaces[-1] 325 326 if self.in_loop and locals.used_in_scope(name, "global") and not name in locals.globals: 327 raise InspectError("Name %r already used as global." % name) 328 elif self.in_loop and locals.used_in_scope(name, "builtins"): 329 raise InspectError("Name %r already used as a built-in." % name) 330 else: 331 locals.set(name, obj, not self.in_loop) 332 333 def store_lambda(self, obj): 334 335 "Store a lambda function 'obj'." 336 337 self.add_object(obj) 338 self.get_namespace().add_lambda(obj) 339 340 def store_module_attr(self, name, module): 341 342 """ 343 Record module attribute 'name' in the given 'module' using the current 344 expression. 345 """ 346 347 module.set(name, self.expr, 0) 348 self.use_specific_attribute(module.full_name(), name) 349 350 def store_class_attr(self, name, cls): 351 352 """ 353 Record class attribute 'name' in the given class 'cls' using the current 354 expression. 355 """ 356 357 cls.set(name, self.expr, 0) 358 self.use_specific_attribute(cls.full_name(), name) 359 360 def store_instance_attr(self, name, tentative=False): 361 362 """ 363 Record instance attribute 'name' in the current class. If 'tentative' is 364 set to a true value, the instance attribute will be discarded if a class 365 attribute is observed. 366 """ 367 368 if self.in_method: 369 370 # Current namespace is the function. 371 # Previous namespace is the class. 372 373 cls = self.namespaces[-2] 374 cls.add_instance_attribute(name, tentative) 375 376 # NOTE: The instance attribute, although defined in a specific 377 # NOTE: class, obviously appears in all descendant classes. 378 379 self.use_specific_attribute(cls.full_name(), name) 380 381 def get_namespace(self): 382 383 "Return the parent (or most recent) namespace currently exposed." 384 385 return (self.namespaces[-1:] or [self])[0] 386 387 def use_name(self, name, node=None, value=None, ns=None): 388 389 """ 390 Use the given 'name' within the current namespace/unit, either in 391 conjunction with a particular object (if 'node' is specified and not 392 None) or unconditionally. 393 """ 394 395 unit = self.get_namespace() 396 397 # Handle attribute usage situations within the current unit. 398 399 if node is not None and isinstance(node, compiler.ast.Name) and ns is unit: 400 self.use_attribute(node.name, name, value) 401 402 # For general name usage, declare usage of the given name from this 403 # particular unit. 404 405 else: 406 self.importer.use_name(name, unit.full_name(), value) 407 408 def use_constant(self, const): 409 410 "Use the given 'const' within the current namespace/unit." 411 412 unit = self.get_namespace() 413 self.importer.use_constant(const, unit.full_name()) 414 415 # Attribute usage methods. 416 # These are convenience methods which refer to the specific namespace's 417 # implementation of these operations. 418 419 def new_branchpoint(self, loop_node=None): 420 self.get_namespace()._new_branchpoint(loop_node) 421 422 def new_branch(self, node): 423 self.get_namespace()._new_branch(node) 424 425 def abandon_branch(self): 426 self.get_namespace()._abandon_branch() 427 428 def suspend_broken_branch(self): 429 self.get_namespace()._suspend_broken_branch() 430 431 def suspend_continuing_branch(self): 432 self.get_namespace()._suspend_continuing_branch() 433 434 def shelve_branch(self): 435 self.get_namespace()._shelve_branch() 436 437 def merge_branches(self): 438 self.get_namespace()._merge_branches() 439 440 def resume_broken_branches(self): 441 self.get_namespace()._resume_broken_branches() 442 443 def resume_continuing_branches(self): 444 self.get_namespace()._resume_continuing_branches() 445 446 def resume_abandoned_branches(self): 447 self.get_namespace()._resume_abandoned_branches() 448 449 def define_attribute_user(self, node): 450 451 """ 452 Define 'node' as the user of attributes, indicating the point where the 453 user is defined. 454 """ 455 456 self.get_namespace()._define_attribute_user(node) 457 458 def use_attribute(self, name, attrname, value=None): 459 460 """ 461 Note usage on the attribute user 'name' of the attribute 'attrname', 462 noting an assignment if 'value' is specified. 463 """ 464 465 return self.get_namespace()._use_attribute(name, attrname, value) 466 467 def use_specific_attribute(self, objname, attrname, from_name=None): 468 469 """ 470 Note usage on the object having the given 'objname' of the attribute 471 'attrname'. If 'objname' is None, the current namespace is chosen as the 472 object providing the attribute. 473 """ 474 475 return self.get_namespace()._use_specific_attribute(objname, attrname, from_name) 476 477 def define_attribute_accessor(self, name, attrname, node, value=None): 478 479 """ 480 Note applicable attribute users providing the given 'name' when 481 accessing the given 'attrname' on the specified 'node', with the 482 optional 'value' indicating an assignment. 483 """ 484 485 self.get_namespace()._define_attribute_accessor(name, attrname, node, value) 486 487 # Visitor methods. 488 489 def default(self, node, *args): 490 raise InspectError("Node class %r is not supported." % node.__class__) 491 492 def NOP(self, node): 493 for n in node.getChildNodes(): 494 self.dispatch(n) 495 496 def NOP_ABANDON(self, node): 497 self.NOP(node) 498 self.abandon_branch() 499 500 def TEST_NOP(self, node): 501 self.use_name("__bool__", node) 502 self.NOP(node) 503 504 def OP(self, node): 505 for n in node.getChildNodes(): 506 self.dispatch(n) 507 return make_instance() 508 509 def TEST_OP(self, node): 510 self.use_name("__bool__", node) 511 self.new_branchpoint() 512 513 # Propagate attribute usage to branches. 514 # Each node starts a new conditional region, effectively making a deeply 515 # nested collection of if-like statements. 516 517 for n in node.nodes: 518 self.new_branch(n) 519 self.dispatch(n) 520 521 # The nested regions must be terminated. 522 523 for n in node.nodes: 524 self.shelve_branch() 525 526 self.merge_branches() 527 return make_instance() 528 529 # Generic support for classes of operations. 530 531 def _ensureOperators(self): 532 attr, scope, namespace = self._get_with_scope("$operator") 533 if attr is None: 534 module = self.importer.load("operator") 535 self["$operator"] = module 536 else: 537 module = attr.get_value() 538 return module 539 540 def _visitOperator(self, node, operator_name=None): 541 542 "Accounting method for the operator 'node'." 543 544 operator_module = self._ensureOperators() 545 operator_fn = operator_functions[operator_name or node.__class__.__name__] 546 self.use_specific_attribute(operator_module.full_name(), operator_fn) 547 return self.OP(node) 548 549 _visitBinary = \ 550 _visitUnary = _visitOperator 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 = _visitBinary 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 = _visitBinary 820 821 visitBitor = _visitBinary 822 823 visitBitxor = _visitBinary 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 = _visitBinary 949 950 visitEllipsis = NOP 951 952 visitExec = NOP 953 954 visitExpression = OP 955 956 visitFloorDiv = _visitBinary 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: 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 self.importer.load(attr.get_value().name, importer=node) 1040 continue 1041 1042 # Support the import of names from missing modules. 1043 1044 self.store(alias or name, UnresolvedName(name, node.modname, self)) 1045 1046 # For wildcards, obtain and store all objects from a module in the 1047 # current namespace. 1048 1049 else: 1050 if module: 1051 for n in module.keys(): 1052 attr = module[n] 1053 self.store(n, attr) 1054 self.use_specific_attribute(module.full_name(), n) 1055 if isinstance(attr.get_value(), Module) and not attr.get_value().loaded: 1056 self.importer.load(attr.get_value().name, importer=node) 1057 1058 def visitFunction(self, node): 1059 return self._visitFunction(node, node.name) 1060 1061 visitGenExpr = OP 1062 1063 visitGenExprFor = NOP 1064 1065 visitGenExprIf = NOP 1066 1067 visitGenExprInner = NOP 1068 1069 def visitGetattr(self, node): 1070 expr = self.dispatch(node.expr) 1071 attrname = node.attrname 1072 node._attr = self._visitAttr(expr, attrname, node) 1073 return node._attr 1074 1075 def visitGlobal(self, node): 1076 if self.namespaces: 1077 for name in node.names: 1078 ns = self.namespaces[-1] 1079 if not ns.make_global(name): 1080 raise InspectError("Name %r is global and local in %r" % (name, ns.full_name())) 1081 1082 # The name is recorded in an earlier process. 1083 1084 def visitIf(self, node): 1085 self.use_name("__bool__", node) 1086 self.new_branchpoint() 1087 1088 # Propagate attribute usage to branches. 1089 1090 for test, body in node.tests: 1091 self.dispatch(test) 1092 1093 self.new_branch(body) 1094 self.dispatch(body) 1095 self.shelve_branch() 1096 1097 # Maintain a branch for the else clause. 1098 1099 self.new_branch(node.else_ or NullBranch()) 1100 if node.else_ is not None: 1101 self.dispatch(node.else_) 1102 self.shelve_branch() 1103 1104 self.merge_branches() 1105 1106 def visitIfExp(self, node): 1107 self.use_name("__bool__", node) 1108 self.new_branchpoint() 1109 1110 # Propagate attribute usage to branches. 1111 1112 self.dispatch(node.test) 1113 1114 self.new_branch(node.then) 1115 self.dispatch(node.then) 1116 self.shelve_branch() 1117 1118 self.new_branch(node.else_) 1119 self.dispatch(node.else_) 1120 self.shelve_branch() 1121 1122 self.merge_branches() 1123 return make_instance() # either outcome is possible 1124 1125 def visitImport(self, node): 1126 for name, alias in node.names: 1127 if alias is not None: 1128 module = self.importer.load(name, 1, importer=node) or UnresolvedName(None, name, self) 1129 self.store(alias, module) 1130 else: 1131 module = self.importer.load(name, importer=node) or UnresolvedName(None, name.split(".")[0], self) 1132 self.store(name.split(".")[0], module) 1133 1134 visitInvert = _visitUnary 1135 1136 def visitKeyword(self, node): 1137 self.dispatch(node.expr) 1138 self._visitConst(node.name) 1139 self.keyword_names.add(node.name) 1140 1141 def visitLambda(self, node): 1142 fn = self._visitFunction(node, None) 1143 self.use_specific_attribute(None, fn.name) 1144 return fn 1145 1146 visitLeftShift = _visitBinary 1147 1148 def visitList(self, node): 1149 self.use_specific_attribute("__builtins__", "list") 1150 return self.OP(node) 1151 1152 def visitListComp(self, node): 1153 1154 # Note that explicit dispatch is performed. 1155 1156 if node.quals: 1157 self.visitListCompFor(node.quals[0], node.quals[1:], node.expr) 1158 return make_instance() 1159 1160 def visitListCompFor(self, node, following_quals, expr): 1161 self.new_branchpoint() 1162 1163 # Declare names which will be used by generated code. 1164 1165 self.use_name("__iter__", node.list) 1166 self.use_name("next") 1167 1168 in_loop = self.in_loop 1169 self.in_loop = 1 1170 self.dispatch(node.list) 1171 1172 # NOTE: Could generate AST nodes for the actual operations instead of 1173 # NOTE: manually generating code in micropython.ast. 1174 1175 self.expr = make_instance() # each element is a result of a function call 1176 self.dispatch(node.assign) 1177 1178 # Enter the loop. 1179 # Propagate attribute usage to branches. 1180 1181 self.new_branch(node) 1182 1183 # Note that explicit dispatch is performed. 1184 1185 if node.ifs: 1186 self.visitListCompIf(node.ifs[0], node.ifs[1:], following_quals, expr) 1187 elif following_quals: 1188 self.visitListCompFor(following_quals[0], following_quals[1:], expr) 1189 else: 1190 self.dispatch(expr) 1191 1192 self.shelve_branch() 1193 self.in_loop = in_loop 1194 1195 self.merge_branches() 1196 1197 def visitListCompIf(self, node, following_ifs, following_quals, expr): 1198 self.use_name("__bool__", node) 1199 self.new_branchpoint() 1200 1201 # Propagate attribute usage to branches. 1202 1203 self.dispatch(node.test) 1204 1205 # Note that explicit dispatch is performed. 1206 1207 if following_ifs: 1208 self.visitListCompIf(following_ifs[0], following_ifs[1:], following_quals, expr) 1209 elif following_quals: 1210 self.visitListCompFor(following_quals[0], following_quals[1:], expr) 1211 else: 1212 self.new_branch(expr) 1213 self.dispatch(expr) 1214 self.shelve_branch() 1215 1216 # Maintain a branch for the else clause. 1217 1218 self.new_branch(NullBranch()) 1219 self.shelve_branch() 1220 1221 self.merge_branches() 1222 1223 visitMod = _visitBinary 1224 1225 def visitModule(self, node): 1226 1227 # Make a back reference from the node for code generation. 1228 1229 node.unit = self 1230 return self.dispatch(node.node) 1231 1232 visitMul = _visitBinary 1233 1234 def visitName(self, node): 1235 return self.get_namespace().get_using_node(node.name, node) or make_instance() 1236 1237 def visitNot(self, node): 1238 self.use_name("__bool__", node) 1239 self.dispatch(node.expr) 1240 return make_instance() 1241 1242 visitOr = TEST_OP 1243 1244 visitPass = NOP 1245 1246 visitPower = _visitBinary 1247 1248 def _visitPrint(self, node, function_name): 1249 self.NOP(node) 1250 self.use_specific_attribute("__builtins__", function_name) 1251 1252 def visitPrint(self, node): 1253 self._visitPrint(node, "_print") 1254 1255 def visitPrintnl(self, node): 1256 self._visitPrint(node, "_printnl") 1257 1258 visitRaise = NOP_ABANDON 1259 1260 visitReturn = NOP_ABANDON 1261 1262 visitRightShift = _visitBinary 1263 1264 def visitSlice(self, node): 1265 return self._visitOperator(node, self.in_assignment and "AssSlice" or "Slice") 1266 1267 visitSliceobj = OP 1268 1269 def visitStmt(self, node): 1270 for n in node.nodes: 1271 self.dispatch(n) 1272 1273 visitSub = _visitBinary 1274 1275 def visitSubscript(self, node): 1276 return self._visitOperator(node, self.in_assignment and "AssSubscript" or "Subscript") 1277 1278 def visitTryExcept(self, node): 1279 self.new_branchpoint() 1280 self.dispatch(node.body) 1281 1282 for name, var, n in node.handlers: 1283 if name is not None: 1284 self.dispatch(name) 1285 1286 self.new_branch(n) 1287 1288 # Any abandoned branches from the body can now be resumed. 1289 1290 self.resume_abandoned_branches() 1291 1292 # Establish the local for the handler. 1293 1294 if var is not None: 1295 self.dispatch(var) 1296 if n is not None: 1297 self.dispatch(n) 1298 1299 self.shelve_branch() 1300 1301 # The else clause maintains the usage from the body but without the 1302 # abandoned branches since they would never lead to the else clause 1303 # being executed. 1304 1305 self.new_branch(node.else_ or NullBranch()) 1306 if node.else_ is not None: 1307 self.dispatch(node.else_) 1308 self.shelve_branch() 1309 1310 self.merge_branches() 1311 1312 visitTryFinally = NOP 1313 1314 visitTuple = OP 1315 1316 visitUnaryAdd = _visitUnary 1317 1318 visitUnarySub = _visitUnary 1319 1320 def visitWhile(self, node): 1321 self.use_name("__bool__", node) 1322 self.new_branchpoint(node) 1323 1324 # Propagate attribute usage to branches. 1325 1326 in_loop = self.in_loop 1327 self.in_loop = 1 1328 1329 # The test is evaluated initially and again in the loop. 1330 1331 self.dispatch(node.test) 1332 1333 self.new_branch(node) 1334 self.dispatch(node.body) 1335 1336 self.resume_continuing_branches() 1337 1338 self.dispatch(node.test) 1339 self.shelve_branch() 1340 1341 self.in_loop = in_loop 1342 1343 # A null branch is used to record a path around the loop. 1344 1345 self.new_branch(node.else_ or NullBranch()) 1346 self.shelve_branch() 1347 1348 self.merge_branches() 1349 1350 # The else clause is evaluated outside any branch. 1351 1352 if node.else_ is not None: 1353 self.dispatch(node.else_) 1354 1355 # Any suspended branches from the loop can now be resumed. 1356 1357 self.resume_broken_branches() 1358 1359 visitWith = NOP 1360 1361 visitYield = NOP 1362 1363 # vim: tabstop=4 expandtab shiftwidth=4