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