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