1 #!/usr/bin/env python 2 3 """ 4 Inspect and obtain module structure. 5 6 Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 7 2014, 2015, 2016 Paul Boddie <paul@boddie.org.uk> 8 9 This program is free software; you can redistribute it and/or modify it under 10 the terms of the GNU General Public License as published by the Free Software 11 Foundation; either version 3 of the License, or (at your option) any later 12 version. 13 14 This program is distributed in the hope that it will be useful, but WITHOUT 15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 16 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 17 details. 18 19 You should have received a copy of the GNU General Public License along with 20 this program. If not, see <http://www.gnu.org/licenses/>. 21 """ 22 23 from branching import BranchTracker 24 from common import CommonModule, get_argnames, get_builtin_type, init_item, \ 25 predefined_constants 26 from modules import BasicModule, CacheWritingModule, InspectionNaming 27 from errors import InspectError 28 from referencing import Reference 29 from resolving import NameResolving 30 from results import AccessRef, InstanceRef, InvocationRef, LiteralSequenceRef, \ 31 LocalNameRef, NameRef, ResolvedNameRef, VariableRef 32 import compiler 33 import sys 34 35 class InspectedModule(BasicModule, CacheWritingModule, NameResolving, InspectionNaming): 36 37 "A module inspector." 38 39 def __init__(self, name, importer): 40 41 "Initialise the module with basic details." 42 43 BasicModule.__init__(self, name, importer) 44 45 self.in_class = False 46 self.in_conditional = False 47 48 # Accesses to global attributes. 49 50 self.global_attr_accesses = {} 51 52 # Usage tracking. 53 54 self.trackers = [] 55 self.attr_accessor_branches = {} 56 57 def __repr__(self): 58 return "InspectedModule(%r, %r)" % (self.name, self.importer) 59 60 # Principal methods. 61 62 def parse(self, filename): 63 64 "Parse the file having the given 'filename'." 65 66 self.parse_file(filename) 67 68 # Inspect the module. 69 70 self.start_tracking_in_module() 71 72 # Detect and record imports and globals declared in the module. 73 74 self.process_structure(self.astnode) 75 76 # Set the class of the module after the definition has occurred. 77 78 ref = self.get_builtin("module") 79 self.set_name("__class__", ref) 80 self.set_name("__mname__", self.get_constant("string", self.name).reference()) 81 self.set_name("__file__", self.get_constant("string", filename).reference()) 82 83 # Reserve a constant for the encoding. 84 85 if self.encoding: 86 self.get_constant("string", self.encoding) 87 88 # Get module-level attribute usage details. 89 90 self.stop_tracking_in_module() 91 92 # Collect external name references. 93 94 self.collect_names() 95 96 def complete(self): 97 98 "Complete the module inspection." 99 100 # Resolve names not definitively mapped to objects. 101 102 self.resolve() 103 104 # Define the invocation requirements in each namespace. 105 106 self.set_invocation_usage() 107 108 # Propagate to the importer information needed in subsequent activities. 109 110 self.propagate() 111 112 # Accessory methods. 113 114 def collect_names(self): 115 116 "Collect the names used by each scope." 117 118 for path in self.names_used.keys(): 119 self.collect_names_for_path(path) 120 121 def collect_names_for_path(self, path): 122 123 """ 124 Collect the names used by the given 'path'. These are propagated to the 125 importer in advance of any dependency resolution. 126 """ 127 128 names = self.names_used.get(path) 129 if not names: 130 return 131 132 in_function = self.function_locals.has_key(path) 133 134 for name in names: 135 if in_function and name in self.function_locals[path]: 136 continue 137 138 key = "%s.%s" % (path, name) 139 140 # Find local definitions (within dynamic namespaces). 141 142 ref = self.get_resolved_object(key) 143 if ref: 144 self.set_name_reference(key, ref) 145 continue 146 147 # Find global. 148 149 ref = self.get_global(name) 150 if ref: 151 self.set_name_reference(key, ref) 152 continue 153 154 # Find presumed built-in definitions. 155 156 ref = self.get_builtin(name) 157 self.set_name_reference(key, ref) 158 159 def set_name_reference(self, path, ref): 160 161 "Map the given name 'path' to 'ref'." 162 163 self.importer.all_name_references[path] = self.name_references[path] = ref 164 165 # Module structure traversal. 166 167 def process_structure_node(self, n): 168 169 "Process the individual node 'n'." 170 171 path = self.get_namespace_path() 172 173 # Module global detection. 174 175 if isinstance(n, compiler.ast.Global): 176 self.process_global_node(n) 177 178 # Module import declarations. 179 180 elif isinstance(n, compiler.ast.From): 181 self.process_from_node(n) 182 183 elif isinstance(n, compiler.ast.Import): 184 self.process_import_node(n) 185 186 # Nodes using operator module functions. 187 188 elif isinstance(n, compiler.ast.Operator): 189 return self.process_operator_node(n) 190 191 elif isinstance(n, compiler.ast.AugAssign): 192 self.process_augassign_node(n) 193 194 elif isinstance(n, compiler.ast.Compare): 195 return self.process_compare_node(n) 196 197 elif isinstance(n, compiler.ast.Slice): 198 return self.process_slice_node(n) 199 200 elif isinstance(n, compiler.ast.Sliceobj): 201 return self.process_sliceobj_node(n) 202 203 elif isinstance(n, compiler.ast.Subscript): 204 return self.process_subscript_node(n) 205 206 # Namespaces within modules. 207 208 elif isinstance(n, compiler.ast.Class): 209 self.process_class_node(n) 210 211 elif isinstance(n, compiler.ast.Function): 212 self.process_function_node(n, n.name) 213 214 elif isinstance(n, compiler.ast.Lambda): 215 return self.process_lambda_node(n) 216 217 # Assignments. 218 219 elif isinstance(n, compiler.ast.Assign): 220 221 # Handle each assignment node. 222 223 for node in n.nodes: 224 self.process_assignment_node(node, n.expr) 225 226 # Assignments within non-Assign nodes. 227 228 elif isinstance(n, compiler.ast.AssName): 229 raise InspectError("Name assignment appearing outside assignment statement.", path, n) 230 231 elif isinstance(n, compiler.ast.AssAttr): 232 raise InspectError("Attribute assignment appearing outside assignment statement.", path, n) 233 234 # Accesses. 235 236 elif isinstance(n, compiler.ast.Getattr): 237 return self.process_attribute_access(n) 238 239 # Name recording for later testing. 240 241 elif isinstance(n, compiler.ast.Name): 242 return self.process_name_node(n) 243 244 # Conditional statement tracking. 245 246 elif isinstance(n, compiler.ast.For): 247 self.process_for_node(n) 248 249 elif isinstance(n, compiler.ast.While): 250 self.process_while_node(n) 251 252 elif isinstance(n, compiler.ast.If): 253 self.process_if_node(n) 254 255 elif isinstance(n, (compiler.ast.And, compiler.ast.Or)): 256 return self.process_logical_node(n) 257 258 # Exception control-flow tracking. 259 260 elif isinstance(n, compiler.ast.TryExcept): 261 self.process_try_node(n) 262 263 elif isinstance(n, compiler.ast.TryFinally): 264 self.process_try_finally_node(n) 265 266 # Control-flow modification statements. 267 268 elif isinstance(n, compiler.ast.Break): 269 self.trackers[-1].suspend_broken_branch() 270 271 elif isinstance(n, compiler.ast.Continue): 272 self.trackers[-1].suspend_continuing_branch() 273 274 elif isinstance(n, compiler.ast.Raise): 275 self.process_structure(n) 276 self.trackers[-1].abandon_branch() 277 278 elif isinstance(n, compiler.ast.Return): 279 self.process_structure(n) 280 self.trackers[-1].abandon_returning_branch() 281 282 # Print statements. 283 284 elif isinstance(n, (compiler.ast.Print, compiler.ast.Printnl)): 285 self.process_print_node(n) 286 287 # Invocations. 288 289 elif isinstance(n, compiler.ast.CallFunc): 290 return self.process_invocation_node(n) 291 292 # Constant usage. 293 294 elif isinstance(n, compiler.ast.Const): 295 return self.get_literal_instance(n) 296 297 elif isinstance(n, compiler.ast.Dict): 298 return self.get_literal_instance(n, "dict") 299 300 elif isinstance(n, compiler.ast.List): 301 return self.get_literal_instance(n, "list") 302 303 elif isinstance(n, compiler.ast.Tuple): 304 return self.get_literal_instance(n, "tuple") 305 306 # Unsupported nodes. 307 308 elif isinstance(n, compiler.ast.GenExpr): 309 raise InspectError("Generator expressions are not supported.", path, n) 310 311 elif isinstance(n, compiler.ast.IfExp): 312 raise InspectError("If-else expressions are not supported.", path, n) 313 314 elif isinstance(n, compiler.ast.ListComp): 315 raise InspectError("List comprehensions are not supported.", path, n) 316 317 # All other nodes are processed depth-first. 318 319 else: 320 self.process_structure(n) 321 322 # By default, no expression details are returned. 323 324 return None 325 326 # Specific node handling. 327 328 def process_assignment_node(self, n, expr): 329 330 "Process the individual node 'n' to be assigned the contents of 'expr'." 331 332 # Names and attributes are assigned the entire expression. 333 334 if isinstance(n, compiler.ast.AssName): 335 if n.name == "self": 336 raise InspectError("Redefinition of self is not allowed.", self.get_namespace_path(), n) 337 338 name_ref = expr and self.process_structure_node(expr) 339 340 # Name assignments populate either function namespaces or the 341 # general namespace hierarchy. 342 343 self.assign_general_local(n.name, name_ref) 344 345 # Record usage of the name. 346 347 self.record_name(n.name) 348 349 elif isinstance(n, compiler.ast.AssAttr): 350 if expr: 351 expr = self.process_structure_node(expr) 352 353 in_assignment = self.in_assignment 354 self.in_assignment = True 355 self.process_attribute_access(n) 356 self.in_assignment = in_assignment 357 358 # Lists and tuples are matched against the expression and their 359 # items assigned to expression items. 360 361 elif isinstance(n, (compiler.ast.AssList, compiler.ast.AssTuple)): 362 self.process_assignment_node_items(n, expr) 363 364 # Slices and subscripts are permitted within assignment nodes. 365 366 elif isinstance(n, compiler.ast.Slice): 367 self.process_slice_node(n, expr) 368 369 elif isinstance(n, compiler.ast.Subscript): 370 self.process_subscript_node(n, expr) 371 372 def process_attribute_access(self, n): 373 374 "Process the given attribute access node 'n'." 375 376 # Obtain any completed chain and return the reference to it. 377 378 name_ref = self.process_attribute_chain(n) 379 380 if self.have_access_expression(n): 381 return name_ref 382 383 # Where the start of the chain of attributes has been reached, determine 384 # the complete access. 385 386 # Given a non-access node, this chain can be handled in its entirety, 387 # either being name-based and thus an access rooted on a name, or being 388 # based on some other node and thus an anonymous access of some kind. 389 390 path = self.get_namespace_path() 391 392 # Start with the the full attribute chain. 393 394 remaining = self.attrs 395 attrnames = ".".join(remaining) 396 397 # If the accessor cannot be identified, or where attributes 398 # remain in an attribute chain, record the anonymous accesses. 399 400 if not isinstance(name_ref, NameRef): # includes ResolvedNameRef 401 402 init_item(self.attr_accesses, path, set) 403 self.attr_accesses[path].add(attrnames) 404 405 self.record_access_details(None, attrnames, self.in_assignment, 406 self.in_invocation) 407 del self.attrs[0] 408 return 409 410 # Name-based accesses will handle the first attribute in a 411 # chain. 412 413 else: 414 attrname = remaining[0] 415 416 # Attribute assignments are used to identify instance attributes. 417 418 if isinstance(n, compiler.ast.AssAttr) and \ 419 self.in_class and self.in_function and n.expr.name == "self": 420 421 self.set_instance_attr(attrname) 422 423 # Record attribute usage using any name local to this namespace, 424 # if assigned in the namespace, or using an external name 425 # (presently just globals within classes). 426 427 name = self.get_name_for_tracking(name_ref.name, name_ref.final()) 428 tracker = self.trackers[-1] 429 430 immediate_access = len(self.attrs) == 1 431 assignment = immediate_access and isinstance(n, compiler.ast.AssAttr) 432 433 # Record global-based chains for subsequent resolution. 434 435 is_global = self.in_function and not self.function_locals[path].has_key(name) or \ 436 not self.in_function 437 438 if is_global: 439 self.record_global_access_details(name, attrnames) 440 441 # Make sure the name is being tracked: global names will not 442 # already be initialised in a branch and must be added 443 # explicitly. 444 445 if not tracker.have_name(name): 446 tracker.assign_names([name]) 447 if self.in_function: 448 self.scope_globals[path].add(name) 449 450 # Record attribute usage in the tracker, and record the branch 451 # information for the access. 452 453 branches = tracker.use_attribute(name, attrname, self.in_invocation, assignment) 454 455 if not branches: 456 raise InspectError("Name %s is accessed using %s before an assignment." % ( 457 name, attrname), path, n) 458 459 self.record_branches_for_access(branches, name, attrnames) 460 access_number = self.record_access_details(name, attrnames, 461 self.in_assignment, self.in_invocation) 462 463 del self.attrs[0] 464 return AccessRef(name, attrnames, access_number) 465 466 def process_class_node(self, n): 467 468 "Process the given class node 'n'." 469 470 path = self.get_namespace_path() 471 472 # To avoid notions of class "versions" where the same definition 473 # might be parameterised with different state and be referenced 474 # elsewhere (as base classes, for example), classes in functions or 475 # conditions are forbidden. 476 477 if self.in_function or self.in_conditional: 478 print >>sys.stderr, "In %s, class %s in function or conditional statement ignored." % ( 479 path, n.name) 480 return 481 482 # Resolve base classes. 483 484 bases = [] 485 486 for base in n.bases: 487 base_class = self.get_class(base) 488 489 if not base_class: 490 print >>sys.stderr, "In %s, class %s has unidentifiable base class: %s" % ( 491 path, n.name, base) 492 return 493 else: 494 bases.append(base_class) 495 496 # Detect conflicting definitions. Such definitions cause conflicts in 497 # the storage of namespace-related information. 498 499 class_name = self.get_object_path(n.name) 500 ref = self.get_object(class_name, defer=False) 501 502 if ref and ref.static(): 503 raise InspectError("Multiple definitions for the same name are not permitted.", class_name, n) 504 505 # Record bases for the class and retain the class name. 506 # Note that the function class does not inherit from the object class. 507 508 if not bases and class_name != "__builtins__.core.object" and \ 509 class_name != "__builtins__.core.function": 510 511 ref = self.get_object("__builtins__.object") 512 bases.append(ref) 513 514 self.importer.classes[class_name] = self.classes[class_name] = bases 515 self.importer.subclasses[class_name] = set() 516 self.scope_globals[class_name] = set() 517 518 # Set the definition before entering the namespace rather than 519 # afterwards because methods may reference it. In normal Python, 520 # a class is not accessible until the definition is complete, but 521 # methods can generally reference it since upon being called the 522 # class will already exist. 523 524 self.set_definition(n.name, "<class>") 525 526 in_class = self.in_class 527 self.in_class = class_name 528 self.set_instance_attr("__class__", Reference("<class>", class_name)) 529 self.enter_namespace(n.name) 530 531 # Do not provide the special instantiator attributes on the function 532 # class. Function instances provide these attributes. 533 534 if class_name != "__builtins__.core.function": 535 self.set_name("__fn__") # special instantiator attribute 536 self.set_name("__args__") # special instantiator attribute 537 538 self.set_name("__name__", self.get_constant("string", class_name).reference()) 539 540 self.process_structure_node(n.code) 541 self.exit_namespace() 542 self.in_class = in_class 543 544 def process_from_node(self, n): 545 546 "Process the given node 'n', importing from another module." 547 548 path = self.get_namespace_path() 549 550 module_name, names = self.get_module_name(n) 551 if module_name == self.name: 552 raise InspectError("Cannot import from the current module.", path, n) 553 554 self.queue_module(module_name) 555 556 # Attempt to obtain the referenced objects. 557 558 for name, alias in n.names: 559 if name == "*": 560 raise InspectError("Only explicitly specified names can be imported from modules.", path, n) 561 562 # Explicit names. 563 564 ref = self.import_name_from_module(name, module_name) 565 value = ResolvedNameRef(alias or name, ref) 566 self.set_general_local(alias or name, value) 567 568 def process_function_node(self, n, name): 569 570 """ 571 Process the given function or lambda node 'n' with the given 'name'. 572 """ 573 574 is_lambda = isinstance(n, compiler.ast.Lambda) 575 576 # Where a function is declared conditionally, use a separate name for 577 # the definition, and assign the definition to the stated name. 578 579 if (self.in_conditional or self.in_function) and not is_lambda: 580 original_name = name 581 name = self.get_lambda_name() 582 else: 583 original_name = None 584 585 # Detect conflicting definitions. Such definitions cause conflicts in 586 # the storage of namespace-related information. 587 588 function_name = self.get_object_path(name) 589 ref = self.get_object(function_name, defer=False) 590 591 if ref and ref.static(): 592 raise InspectError("Multiple definitions for the same name are not permitted.", function_name, n) 593 594 # Initialise argument and local records. 595 596 argnames = get_argnames(n.argnames) 597 is_method = self.in_class and not self.in_function 598 599 # Remove explicit "self" from method parameters. 600 601 if is_method and argnames and argnames[0] == "self": 602 del argnames[0] 603 604 # Copy and propagate the parameters. 605 606 self.importer.function_parameters[function_name] = \ 607 self.function_parameters[function_name] = argnames[:] 608 609 # Define all arguments/parameters in the local namespace. 610 611 locals = \ 612 self.importer.function_locals[function_name] = \ 613 self.function_locals[function_name] = {} 614 615 # Insert "self" into method locals. 616 617 if is_method: 618 argnames.insert(0, "self") 619 620 # Define "self" in terms of the class if in a method. 621 # This does not diminish the need for type-narrowing in the deducer. 622 623 if argnames: 624 if self.in_class and not self.in_function and argnames[0] == "self": 625 locals[argnames[0]] = Reference("<instance>", self.in_class) 626 else: 627 locals[argnames[0]] = Reference("<var>") 628 629 for argname in argnames[1:]: 630 locals[argname] = Reference("<var>") 631 632 globals = self.scope_globals[function_name] = set() 633 634 # Process the defaults. 635 636 defaults = self.importer.function_defaults[function_name] = \ 637 self.function_defaults[function_name] = [] 638 639 for argname, default in compiler.ast.get_defaults(n): 640 if default: 641 642 # Obtain any reference for the default. 643 644 name_ref = self.process_structure_node(default) 645 defaults.append((argname, name_ref.is_name() and name_ref.reference() or Reference("<var>"))) 646 647 # Reset conditional tracking to focus on the function contents. 648 649 in_conditional = self.in_conditional 650 self.in_conditional = False 651 652 in_function = self.in_function 653 self.in_function = function_name 654 655 self.enter_namespace(name) 656 657 # Define a name attribute value for the function instance. 658 659 ref = self.get_builtin_class("string") 660 self.reserve_constant(function_name, function_name, ref.get_origin()) 661 662 # Track attribute usage within the namespace. 663 664 path = self.get_namespace_path() 665 666 self.start_tracking(locals) 667 self.process_structure_node(n.code) 668 self.stop_tracking() 669 670 # Exit to the parent. 671 672 self.exit_namespace() 673 674 # Update flags. 675 676 self.in_function = in_function 677 self.in_conditional = in_conditional 678 679 # Define the function using the appropriate name. 680 681 self.set_definition(name, "<function>") 682 683 # Where a function is set conditionally, assign the name. 684 685 if original_name: 686 self.process_assignment_for_object(original_name, compiler.ast.Name(name)) 687 688 def process_global_node(self, n): 689 690 """ 691 Process the given "global" node 'n'. 692 """ 693 694 path = self.get_namespace_path() 695 696 if path != self.name: 697 self.scope_globals[path].update(n.names) 698 699 def process_if_node(self, n): 700 701 """ 702 Process the given "if" node 'n'. 703 """ 704 705 tracker = self.trackers[-1] 706 tracker.new_branchpoint() 707 708 for test, body in n.tests: 709 self.process_structure_node(test) 710 711 tracker.new_branch() 712 713 in_conditional = self.in_conditional 714 self.in_conditional = True 715 self.process_structure_node(body) 716 self.in_conditional = in_conditional 717 718 tracker.shelve_branch() 719 720 # Maintain a branch for the else clause. 721 722 tracker.new_branch() 723 if n.else_: 724 self.process_structure_node(n.else_) 725 tracker.shelve_branch() 726 727 tracker.merge_branches() 728 729 def process_import_node(self, n): 730 731 "Process the given import node 'n'." 732 733 path = self.get_namespace_path() 734 735 # Load the mentioned module. 736 737 for name, alias in n.names: 738 if name == self.name: 739 raise InspectError("Cannot import the current module.", path, n) 740 741 self.set_module(alias or name.split(".")[-1], name) 742 self.queue_module(name, True) 743 744 def process_invocation_node(self, n): 745 746 "Process the given invocation node 'n'." 747 748 path = self.get_namespace_path() 749 750 self.allocate_arguments(path, n.args) 751 752 try: 753 # Communicate to the invocation target expression that it forms the 754 # target of an invocation, potentially affecting attribute accesses. 755 756 in_invocation = self.in_invocation 757 self.in_invocation = True 758 759 # Process the expression, obtaining any identified reference. 760 761 name_ref = self.process_structure_node(n.node) 762 self.in_invocation = False 763 764 # Process the arguments. 765 766 for arg in n.args: 767 self.process_structure_node(arg) 768 769 self.in_invocation = in_invocation 770 771 # Detect class invocations. 772 773 if isinstance(name_ref, ResolvedNameRef) and name_ref.has_kind("<class>"): 774 return InstanceRef(name_ref.reference().instance_of()) 775 776 elif isinstance(name_ref, NameRef): 777 return InvocationRef(name_ref) 778 779 # Provide a general reference to indicate that something is produced 780 # by the invocation, useful for retaining assignment expression 781 # details. 782 783 return VariableRef() 784 785 finally: 786 self.deallocate_arguments(path, n.args) 787 788 def process_lambda_node(self, n): 789 790 "Process the given lambda node 'n'." 791 792 name = self.get_lambda_name() 793 self.process_function_node(n, name) 794 795 origin = self.get_object_path(name) 796 797 if self.function_defaults.get(origin): 798 return None 799 else: 800 return ResolvedNameRef(name, Reference("<function>", origin)) 801 802 def process_logical_node(self, n): 803 804 "Process the given operator node 'n'." 805 806 self.process_operator_chain(n.nodes, self.process_structure_node) 807 808 def process_name_node(self, n): 809 810 "Process the given name node 'n'." 811 812 path = self.get_namespace_path() 813 814 # Find predefined constant names before anything else. 815 816 if n.name in predefined_constants: 817 ref = self.get_builtin(n.name) 818 value = ResolvedNameRef(n.name, ref) 819 return value 820 821 # Special names that have already been identified. 822 823 if n.name.startswith("$"): 824 value = self.get_special(n.name) 825 if value: 826 return value 827 828 # Special case for operator functions introduced through code 829 # transformations. 830 831 if n.name.startswith("$op"): 832 833 # Obtain the location of the actual function defined in the operator 834 # package. 835 836 op = n.name[len("$op"):] 837 838 # Attempt to get a reference. 839 840 ref = self.import_name_from_module(op, "operator") 841 842 # Record the imported name and provide the resolved name reference. 843 844 value = ResolvedNameRef(n.name, ref) 845 self.set_special(n.name, value) 846 return value 847 848 # Special case for print operations. 849 850 elif n.name.startswith("$print"): 851 852 # Attempt to get a reference. 853 854 ref = self.get_builtin("print_") 855 856 # Record the imported name and provide the resolved name reference. 857 858 value = ResolvedNameRef(n.name, ref) 859 self.set_special(n.name, value) 860 return value 861 862 # Test for self usage, which is only allowed in methods. 863 864 if n.name == "self" and not (self.in_function and self.in_class): 865 raise InspectError("Use of self is only allowed in methods.", path, n) 866 867 # Record usage of the name. 868 869 self.record_name(n.name) 870 871 # Search for unknown names in non-function scopes immediately. 872 # External names in functions are resolved later. 873 874 ref = self.find_name(n.name) 875 if ref: 876 return ResolvedNameRef(n.name, ref) 877 878 # Explicitly-declared global names. 879 880 elif self.in_function and n.name in self.scope_globals[path]: 881 return NameRef(n.name) 882 883 # Examine other names. 884 885 else: 886 tracker = self.trackers[-1] 887 888 # Check local names. 889 890 branches = tracker.tracking_name(n.name) 891 892 # Local name. 893 894 if branches: 895 self.record_branches_for_access(branches, n.name, None) 896 access_number = self.record_access_details(n.name, None, False, False) 897 return LocalNameRef(n.name, access_number) 898 899 # Possible global or built-in name. 900 901 else: 902 return NameRef(n.name) 903 904 def process_operator_chain(self, nodes, fn): 905 906 """ 907 Process the given chain of 'nodes', applying 'fn' to each node or item. 908 Each node starts a new conditional region, effectively making a deeply- 909 nested collection of if-like statements. 910 """ 911 912 tracker = self.trackers[-1] 913 914 for item in nodes: 915 tracker.new_branchpoint() 916 tracker.new_branch() 917 fn(item) 918 919 for item in nodes[:-1]: 920 tracker.shelve_branch() 921 tracker.new_branch() 922 tracker.shelve_branch() 923 tracker.merge_branches() 924 925 tracker.shelve_branch() 926 tracker.merge_branches() 927 928 def process_try_node(self, n): 929 930 """ 931 Process the given "try...except" node 'n'. 932 """ 933 934 tracker = self.trackers[-1] 935 tracker.new_branchpoint() 936 937 self.process_structure_node(n.body) 938 939 for name, var, handler in n.handlers: 940 if name is not None: 941 self.process_structure_node(name) 942 943 # Any abandoned branches from the body can now be resumed in a new 944 # branch. 945 946 tracker.resume_abandoned_branches() 947 948 # Establish the local for the handler. 949 950 if var is not None: 951 self.process_assignment_node(var, None) 952 if handler is not None: 953 self.process_structure_node(handler) 954 955 tracker.shelve_branch() 956 957 # The else clause maintains the usage from the body but without the 958 # abandoned branches since they would never lead to the else clause 959 # being executed. 960 961 if n.else_: 962 tracker.new_branch() 963 self.process_structure_node(n.else_) 964 tracker.shelve_branch() 965 966 # Without an else clause, a null branch propagates the successful 967 # outcome. 968 969 else: 970 tracker.new_branch() 971 tracker.shelve_branch() 972 973 tracker.merge_branches() 974 975 def process_try_finally_node(self, n): 976 977 """ 978 Process the given "try...finally" node 'n'. 979 """ 980 981 tracker = self.trackers[-1] 982 self.process_structure_node(n.body) 983 984 # Any abandoned branches from the body can now be resumed. 985 986 branches = tracker.resume_all_abandoned_branches() 987 self.process_structure_node(n.final) 988 989 # At the end of the finally clause, abandoned branches are discarded. 990 991 tracker.restore_active_branches(branches) 992 993 def process_while_node(self, n): 994 995 "Process the given while node 'n'." 996 997 tracker = self.trackers[-1] 998 tracker.new_branchpoint(loop_node=True) 999 1000 # Evaluate any test or iterator outside the loop. 1001 1002 self.process_structure_node(n.test) 1003 1004 # Propagate attribute usage to branches. 1005 1006 tracker.new_branch(loop_node=True) 1007 1008 # Enter the loop. 1009 1010 in_conditional = self.in_conditional 1011 self.in_conditional = True 1012 self.process_structure_node(n.body) 1013 self.in_conditional = in_conditional 1014 1015 # Continuing branches are resumed before any test. 1016 1017 tracker.resume_continuing_branches() 1018 1019 # Evaluate any continuation test within the body. 1020 1021 self.process_structure_node(n.test) 1022 1023 tracker.shelve_branch(loop_node=True) 1024 1025 # Support the non-looping condition. 1026 1027 tracker.new_branch() 1028 tracker.shelve_branch() 1029 1030 tracker.merge_branches() 1031 1032 # Evaluate any else clause outside branches. 1033 1034 if n.else_: 1035 self.process_structure_node(n.else_) 1036 1037 # Connect broken branches to the code after any loop. 1038 1039 tracker.resume_broken_branches() 1040 1041 # Branch tracking methods. 1042 1043 def start_tracking(self, names): 1044 1045 """ 1046 Start tracking attribute usage for names in the current namespace, 1047 immediately registering the given 'names'. 1048 """ 1049 1050 path = self.get_namespace_path() 1051 parent = self.trackers[-1] 1052 tracker = BranchTracker() 1053 self.trackers.append(tracker) 1054 1055 # Record the given names established as new branches. 1056 1057 tracker.assign_names(names) 1058 1059 def assign_name(self, name, name_ref): 1060 1061 "Assign to 'name' the given 'name_ref' in the current namespace." 1062 1063 name = self.get_name_for_tracking(name) 1064 self.trackers[-1].assign_names([name], [name_ref]) 1065 1066 def stop_tracking(self): 1067 1068 """ 1069 Stop tracking attribute usage, recording computed usage for the current 1070 namespace. 1071 """ 1072 1073 path = self.get_namespace_path() 1074 tracker = self.trackers.pop() 1075 self.record_assignments_for_access(tracker) 1076 1077 self.attr_usage[path] = tracker.get_all_usage() 1078 self.name_initialisers[path] = tracker.get_all_values() 1079 1080 def start_tracking_in_module(self): 1081 1082 "Start tracking attribute usage in the module." 1083 1084 tracker = BranchTracker() 1085 self.trackers.append(tracker) 1086 1087 def stop_tracking_in_module(self): 1088 1089 "Stop tracking attribute usage in the module." 1090 1091 tracker = self.trackers[0] 1092 self.record_assignments_for_access(tracker) 1093 self.attr_usage[self.name] = tracker.get_all_usage() 1094 self.name_initialisers[self.name] = tracker.get_all_values() 1095 1096 def record_assignments_for_access(self, tracker): 1097 1098 """ 1099 For the current path, use the given 'tracker' to record assignment 1100 version information for attribute accesses. 1101 """ 1102 1103 path = self.get_path_for_access() 1104 1105 if not self.attr_accessor_branches.has_key(path): 1106 return 1107 1108 init_item(self.attr_accessors, path, dict) 1109 attr_accessors = self.attr_accessors[path] 1110 1111 # Obtain the branches applying during each access. 1112 1113 for access, all_branches in self.attr_accessor_branches[path].items(): 1114 name, attrnames = access 1115 init_item(attr_accessors, access, list) 1116 1117 # Obtain the assignments applying to each branch. 1118 1119 for branches in all_branches: 1120 positions = tracker.get_assignment_positions_for_branches(name, branches) 1121 1122 # Detect missing name information. 1123 1124 if None in positions: 1125 globals = self.global_attr_accesses.get(path) 1126 accesses = globals and globals.get(name) 1127 if not accesses: 1128 print >>sys.stderr, "In %s, %s may not be defined when used." % ( 1129 self.get_namespace_path(), name) 1130 positions.remove(None) 1131 1132 attr_accessors[access].append(positions) 1133 1134 def record_branches_for_access(self, branches, name, attrnames): 1135 1136 """ 1137 Record the given 'branches' for an access involving the given 'name' and 1138 'attrnames'. 1139 """ 1140 1141 access = name, attrnames 1142 path = self.get_path_for_access() 1143 1144 init_item(self.attr_accessor_branches, path, dict) 1145 attr_accessor_branches = self.attr_accessor_branches[path] 1146 1147 init_item(attr_accessor_branches, access, list) 1148 attr_accessor_branches[access].append(branches) 1149 1150 def record_access_details(self, name, attrnames, assignment, invocation): 1151 1152 """ 1153 For the given 'name' and 'attrnames', record an access indicating 1154 whether 'assignment' is occurring. 1155 1156 These details correspond to accesses otherwise recorded by the attribute 1157 accessor and attribute access dictionaries. 1158 """ 1159 1160 access = name, attrnames 1161 path = self.get_path_for_access() 1162 1163 init_item(self.attr_access_modifiers, path, dict) 1164 init_item(self.attr_access_modifiers[path], access, list) 1165 1166 access_number = len(self.attr_access_modifiers[path][access]) 1167 self.attr_access_modifiers[path][access].append((assignment, invocation)) 1168 return access_number 1169 1170 def record_global_access_details(self, name, attrnames): 1171 1172 """ 1173 Record details of a global access via the given 'name' involving the 1174 indicated 'attrnames'. 1175 """ 1176 1177 path = self.get_namespace_path() 1178 1179 init_item(self.global_attr_accesses, path, dict) 1180 init_item(self.global_attr_accesses[path], name, set) 1181 self.global_attr_accesses[path][name].add(attrnames) 1182 1183 # Namespace modification. 1184 1185 def record_name(self, name): 1186 1187 "Record the use of 'name' in a namespace." 1188 1189 path = self.get_namespace_path() 1190 init_item(self.names_used, path, set) 1191 self.names_used[path].add(name) 1192 1193 def set_module(self, name, module_name): 1194 1195 """ 1196 Set a module in the current namespace using the given 'name' associated 1197 with the corresponding 'module_name'. 1198 """ 1199 1200 if name: 1201 self.set_general_local(name, Reference("<module>", module_name)) 1202 1203 def set_definition(self, name, kind): 1204 1205 """ 1206 Set the definition having the given 'name' and 'kind'. 1207 1208 Definitions are set in the static namespace hierarchy, but they can also 1209 be recorded for function locals. 1210 """ 1211 1212 if self.is_global(name): 1213 print >>sys.stderr, "In %s, %s is defined as being global." % ( 1214 self.get_namespace_path(), name) 1215 1216 path = self.get_object_path(name) 1217 self.set_object(path, kind) 1218 1219 ref = self.get_object(path) 1220 if ref.get_kind() == "<var>": 1221 print >>sys.stderr, "In %s, %s is defined more than once." % ( 1222 self.get_namespace_path(), name) 1223 1224 if not self.is_global(name) and self.in_function: 1225 self.set_function_local(name, ref) 1226 1227 def set_function_local(self, name, ref=None): 1228 1229 "Set the local with the given 'name' and optional 'ref'." 1230 1231 locals = self.function_locals[self.get_namespace_path()] 1232 multiple = not ref or locals.has_key(name) and locals[name] != ref 1233 locals[name] = multiple and Reference("<var>") or ref 1234 1235 def assign_general_local(self, name, name_ref): 1236 1237 """ 1238 Set for 'name' the given 'name_ref', recording the name for attribute 1239 usage tracking. 1240 """ 1241 1242 self.set_general_local(name, name_ref) 1243 self.assign_name(name, name_ref) 1244 1245 def set_general_local(self, name, value=None): 1246 1247 """ 1248 Set the 'name' with optional 'value' in any kind of local namespace, 1249 where the 'value' should be a reference if specified. 1250 """ 1251 1252 init_value = self.get_initialising_value(value) 1253 1254 # Module global names. 1255 1256 if self.is_global(name): 1257 path = self.get_global_path(name) 1258 self.set_object(path, init_value) 1259 1260 # Function local names. 1261 1262 elif self.in_function: 1263 path = self.get_object_path(name) 1264 self.set_function_local(name, init_value) 1265 1266 # Other namespaces (classes). 1267 1268 else: 1269 path = self.get_object_path(name) 1270 self.set_name(name, init_value) 1271 1272 def set_name(self, name, ref=None): 1273 1274 "Attach the 'name' with optional 'ref' to the current namespace." 1275 1276 self.set_object(self.get_object_path(name), ref) 1277 1278 def set_instance_attr(self, name, ref=None): 1279 1280 """ 1281 Add an instance attribute of the given 'name' to the current class, 1282 using the optional 'ref'. 1283 """ 1284 1285 self._set_instance_attr(self.in_class, name, ref) 1286 1287 def _set_instance_attr(self, path, name, ref=None): 1288 1289 init_item(self.instance_attrs, path, set) 1290 self.instance_attrs[path].add(name) 1291 1292 if ref: 1293 init_item(self.instance_attr_constants, path, dict) 1294 self.instance_attr_constants[path][name] = ref 1295 1296 def get_initialising_value(self, value): 1297 1298 "Return a suitable initialiser reference for 'value'." 1299 1300 # Includes LiteralSequenceRef, ResolvedNameRef... 1301 1302 if isinstance(value, (NameRef, AccessRef, InstanceRef)): 1303 return value.reference() 1304 1305 # In general, invocations do not produce known results. However, the 1306 # name initialisers are resolved once a module has been inspected. 1307 1308 elif isinstance(value, InvocationRef): 1309 return value.reference() 1310 1311 # Variable references are unknown results. 1312 1313 elif isinstance(value, VariableRef): 1314 return value.reference() 1315 1316 else: 1317 return value 1318 1319 # Static, program-relative naming. 1320 1321 def find_name(self, name): 1322 1323 """ 1324 Return the qualified name for the given 'name' used in the current 1325 non-function namespace. 1326 """ 1327 1328 path = self.get_namespace_path() 1329 ref = None 1330 1331 if not self.in_function and name not in predefined_constants: 1332 if self.in_class: 1333 ref = self.get_object(self.get_object_path(name), False) 1334 if not ref: 1335 ref = self.get_global_or_builtin(name) 1336 1337 return ref 1338 1339 def get_class(self, node): 1340 1341 """ 1342 Use the given 'node' to obtain the identity of a class. Return a 1343 reference for the class. Unresolved dependencies are permitted and must 1344 be resolved later. 1345 """ 1346 1347 ref = self._get_class(node) 1348 return ref.has_kind(["<class>", "<depends>"]) and ref or None 1349 1350 def _get_class(self, node): 1351 1352 """ 1353 Use the given 'node' to find a class definition. Return a reference to 1354 the class. 1355 """ 1356 1357 if isinstance(node, compiler.ast.Getattr): 1358 1359 # Obtain the identity of the access target. 1360 1361 ref = self._get_class(node.expr) 1362 1363 # Where the target is a class or module, obtain the identity of the 1364 # attribute. 1365 1366 if ref.has_kind(["<function>", "<var>"]): 1367 return None 1368 else: 1369 attrname = "%s.%s" % (ref.get_origin(), node.attrname) 1370 return self.get_object(attrname) 1371 1372 # Names can be module-level or built-in. 1373 1374 elif isinstance(node, compiler.ast.Name): 1375 1376 # Record usage of the name and attempt to identify it. 1377 1378 self.record_name(node.name) 1379 return self.find_name(node.name) 1380 else: 1381 return None 1382 1383 def get_constant(self, name, value): 1384 1385 "Return a constant reference for the given type 'name' and 'value'." 1386 1387 ref = self.get_builtin_class(name) 1388 return self.get_constant_reference(ref, value) 1389 1390 def get_literal_instance(self, n, name=None): 1391 1392 """ 1393 For node 'n', return a reference to an instance of 'name', or if 'name' 1394 is not specified, deduce the type from the value. 1395 """ 1396 1397 # Handle stray None constants (Sliceobj seems to produce them). 1398 1399 if name == "NoneType": 1400 return self.process_name_node(compiler.ast.Name("None")) 1401 1402 # Obtain the details of the literal itself. 1403 # An alias to the type is generated for sequences. 1404 1405 if name in ("dict", "list", "tuple"): 1406 ref = self.get_builtin_class(name) 1407 self.set_special_literal(name, ref) 1408 return self.process_literal_sequence_node(n, name, ref, LiteralSequenceRef) 1409 1410 # Constant values are independently recorded. 1411 1412 else: 1413 value, typename, encoding = self.get_constant_value(n.value, n.literal) 1414 name = get_builtin_type(typename) 1415 ref = self.get_builtin_class(name) 1416 return self.get_constant_reference(ref, value, encoding) 1417 1418 # Special names. 1419 1420 def get_special(self, name): 1421 1422 "Return any stored value for the given special 'name'." 1423 1424 return self.special.get(name) 1425 1426 def set_special(self, name, value): 1427 1428 """ 1429 Set a special 'name' that merely tracks the use of an implicit object 1430 'value'. 1431 """ 1432 1433 self.special[name] = value 1434 1435 def set_special_literal(self, name, ref): 1436 1437 """ 1438 Set a special name for the literal type 'name' having type 'ref'. Such 1439 special names provide a way of referring to literal object types. 1440 """ 1441 1442 literal_name = "$L%s" % name 1443 value = ResolvedNameRef(literal_name, ref) 1444 self.set_special(literal_name, value) 1445 1446 # Functions and invocations. 1447 1448 def set_invocation_usage(self): 1449 1450 """ 1451 Discard the current invocation storage figures, retaining the maximum 1452 values. 1453 """ 1454 1455 for path, (current, maximum) in self.function_targets.items(): 1456 self.importer.function_targets[path] = self.function_targets[path] = maximum 1457 1458 for path, (current, maximum) in self.function_arguments.items(): 1459 self.importer.function_arguments[path] = self.function_arguments[path] = maximum 1460 1461 def allocate_arguments(self, path, args): 1462 1463 """ 1464 Allocate temporary argument storage using current and maximum 1465 requirements for the given 'path' and 'args'. 1466 """ 1467 1468 # Class and module initialisation is ultimately combined. 1469 1470 if not self.in_function: 1471 path = self.name 1472 1473 init_item(self.function_targets, path, lambda: [0, 0]) 1474 t = self.function_targets[path] 1475 t[0] += 1 1476 t[1] = max(t[0], t[1]) 1477 1478 init_item(self.function_arguments, path, lambda: [0, 0]) 1479 t = self.function_arguments[path] 1480 t[0] += len(args) + 1 1481 t[1] = max(t[0], t[1]) 1482 1483 def deallocate_arguments(self, path, args): 1484 1485 "Deallocate temporary argument storage for the given 'path' and 'args'." 1486 1487 # Class and module initialisation is ultimately combined. 1488 1489 if not self.in_function: 1490 path = self.name 1491 1492 self.function_targets[path][0] -= 1 1493 self.function_arguments[path][0] -= len(args) + 1 1494 1495 # vim: tabstop=4 expandtab shiftwidth=4