1 #!/usr/bin/env python 2 3 """ 4 Inspect source files, obtaining details of classes and attributes. 5 6 Copyright (C) 2007, 2008 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 central classes in this module are the following: 24 25 * Class 26 * Function 27 * Module 28 * InspectedModule (derived from Module) 29 30 All of the above support the Naming interface either explicitly or through 31 general conformance, meaning that all can be asked to provide their 'full_name' 32 using the method of that name. 33 34 Additionally, all of the above also support a dictionary interface in order to 35 access names within their defined scopes. Specific methods also exist in order 36 to distinguish between certain kinds of attributes: 37 38 * Class: (class|all_class|instance|all)_attributes 39 * Function: parameters, locals, all_locals 40 * Module: module_attributes 41 42 These specific methods are useful in certain situations. 43 44 The above classes also provide a 'node' attribute, indicating the AST node where 45 each such object is defined. 46 """ 47 48 from micropython.common import * 49 import compiler.ast 50 from compiler.visitor import ASTVisitor 51 try: 52 set 53 except NameError: 54 from sets import Set as set 55 56 class InspectError(ProcessingError): pass 57 58 class AtLeast: 59 60 "A special representation for numbers of a given value or greater." 61 62 def __init__(self, count): 63 self.count = count 64 65 def __eq__(self, other): 66 return 0 67 68 __lt__ = __le__ = __eq__ 69 70 def __ne__(self, other): 71 return 1 72 73 def __gt__(self, other): 74 if isinstance(other, AtLeast): 75 return 0 76 else: 77 return self.count > other 78 79 def __ge__(self, other): 80 if isinstance(other, AtLeast): 81 return 0 82 else: 83 return self.count >= other 84 85 def __iadd__(self, other): 86 if isinstance(other, AtLeast): 87 self.count += other.count 88 else: 89 self.count += other 90 return self 91 92 def __radd__(self, other): 93 if isinstance(other, AtLeast): 94 return AtLeast(self.count + other.count) 95 else: 96 return AtLeast(self.count + other) 97 98 def __repr__(self): 99 return "AtLeast(%r)" % self.count 100 101 # Mix-ins and abstract classes. 102 103 class NamespaceDict: 104 105 "A mix-in providing dictionary methods." 106 107 def __init__(self, global_namespace=None): 108 self.namespace = {} 109 self.globals = set() 110 self.global_namespace = global_namespace 111 self.attr_position = 0 112 113 def __getitem__(self, name): 114 return self.namespace[name] 115 116 def get(self, name, default=None): 117 return self.namespace.get(name, default) 118 119 def __setitem__(self, name, value): 120 self.set(name, value) 121 122 def set(self, name, value, single_assignment=1): 123 124 """ 125 A more powerful set operation, making 'name' refer to 'value' whilst 126 indicating whether a 'single_assignment' (true by default) occurs in 127 this operation (or whether the operation covers potentially many 128 assignments in the lifetime of a program). 129 """ 130 131 if name in self.globals: 132 self.global_namespace.set(name, value, 0) 133 else: 134 attr = self._set(name, value) 135 136 # NOTE: Insist on assignments with known values. 137 138 if value is not None: 139 attr.update(value, single_assignment) 140 141 def set_module(self, name, value): 142 143 """ 144 A specialised set operation, making 'name' refer to 'value' in the 145 context of making a module reference available in association with 146 'name' as part of the import of that module or a submodule of that 147 module. 148 """ 149 150 attr = self._set(name, value) 151 if attr.assignments is None: 152 attr.assignments = 1 153 attr.assignment_values.add(value) 154 155 def _set(self, name, value): 156 157 "The underlying set operation associating 'name' with 'value'." 158 159 if not self.namespace.has_key(name): 160 self.namespace[name] = Attr(self.attr_position, self, name, value) 161 self.attr_position += 1 162 return self.namespace[name] 163 164 def __delitem__(self, name): 165 del self.namespace[name] 166 167 def has_key(self, name): 168 return self.namespace.has_key(name) 169 170 def keys(self): 171 return self.namespace.keys() 172 173 def values(self): 174 return self.namespace.values() 175 176 def items(self): 177 return self.namespace.items() 178 179 def make_global(self, name): 180 if not self.namespace.has_key(name): 181 self.globals.add(name) 182 else: 183 raise InspectError(self.full_name(), self.node, "Name %r is both global and local in %r" % (name, self.full_name())) 184 185 def get_assignments(self, name): 186 if self.assignments.has_key(name): 187 return max(self.assignments[name], len(self.assignment_values[name])) 188 else: 189 return None 190 191 def to_list(self, d): 192 l = [None] * len(d.keys()) 193 for attr in d.values(): 194 l[attr.position] = attr 195 return l 196 197 class Naming: 198 199 "A mix-in providing naming conveniences." 200 201 def full_name(self): 202 if self.name is not None: 203 return self.parent_name + "." + self.name 204 else: 205 return self.parent_name 206 207 # Program data structures. 208 209 class Attr: 210 211 "An attribute entry." 212 213 def __init__(self, position, parent, name, value=None, assignments=None): 214 self.position = position 215 self.parent = parent 216 self.name = name 217 self.value = value 218 219 # Number of assignments per name. 220 221 self.assignments = assignments 222 self.assignment_values = set() 223 224 def update(self, value, single_assignment): 225 226 """ 227 Update the attribute, adding the 'value' provided to the known values 228 associated with the attribute, changing the number of assignments 229 according to the 'single_assignment' status of the operation, where 230 a true value indicates that only one assignment is associated with the 231 update, and a false value indicates that potentially many assignments 232 may be involved. 233 """ 234 235 if self.assignments is None: 236 if single_assignment: 237 self.assignments = 1 238 else: 239 self.assignments = AtLeast(1) 240 else: 241 if single_assignment: 242 self.assignments += 1 243 else: 244 self.assignments += AtLeast(1) 245 self.assignment_values.add(value) 246 247 def __repr__(self): 248 return "Attr(%r, %r, %r, %r, %r)" % (self.position, self.parent, self.name, self.value, self.assignments) 249 250 class Const: 251 252 "A constant object." 253 254 def __init__(self, value): 255 self.value = value 256 257 # Image generation details. 258 259 self.location = None 260 261 def __repr__(self): 262 if self.location is not None: 263 return "Const(%r, location=%r)" % (self.value, self.location) 264 else: 265 return "Const(%r)" % self.value 266 267 def __eq__(self, other): 268 return self.value == other.value 269 270 def __hash__(self): 271 return hash(self.value) 272 273 class Class(NamespaceDict, Naming): 274 275 "An inspected class." 276 277 def __init__(self, name, parent_name, global_namespace=None, node=None): 278 NamespaceDict.__init__(self, global_namespace) 279 self.name = name 280 self.parent_name = parent_name 281 self.node = node 282 283 # Superclasses and attributes. 284 285 self.bases = [] 286 self.instattr = set() # instance attributes 287 self.instattr_relocated = set() # instance attributes which do not have 288 # the same position as those of the same 289 # name in some superclasses 290 291 # Caches. 292 293 self.all_instattr = None # cache for instance_attributes 294 self.all_instattr_names = None # from all_instattr 295 self.all_classattr = None # cache for all_class_attributes 296 self.all_classattr_names = None # from all_classattr 297 self.allattr = None # cache for all_attributes 298 self.allattr_names = None # from allattr 299 300 # Image generation details. 301 302 self.location = None 303 self.code_location = None 304 305 def __repr__(self): 306 if self.location is not None: 307 return "Class(%r, %r, location=%r)" % (self.name, self.parent_name, self.location) 308 else: 309 return "Class(%r, %r)" % (self.name, self.parent_name) 310 311 def add_base(self, base): 312 self.bases.append(base) 313 314 def add_instance_attribute(self, name): 315 self.instattr.add(name) 316 317 "Return the attribute names provided by this class only." 318 319 class_attribute_names = NamespaceDict.keys 320 321 def class_attributes(self): 322 323 "Return class attributes provided by this class only." 324 325 return self 326 327 def all_class_attribute_names(self): 328 329 "Return the attribute names provided by classes in this hierarchy." 330 331 if self.all_classattr_names is None: 332 self.all_class_attributes() 333 return self.all_classattr_names 334 335 def all_class_attributes(self): 336 337 "Return all class attributes, indicating the class which provides them." 338 339 if self.all_classattr is None: 340 self.all_classattr = {} 341 342 reversed_bases = self.bases[:] 343 reversed_bases.reverse() 344 for cls in reversed_bases: 345 self.all_classattr.update(cls.all_class_attributes()) 346 347 # Record attributes provided by this class, along with their 348 # positions. 349 350 self.all_classattr.update(self.class_attributes()) 351 352 return self.all_classattr 353 354 def instance_attribute_names(self): 355 356 "Return the instance attribute names provided by the class." 357 358 if self.all_instattr_names is None: 359 self.instance_attributes() 360 return self.all_instattr_names 361 362 def instance_attributes(self): 363 364 "Return instance-only attributes for instances of this class." 365 366 if self.all_instattr is None: 367 self.all_instattr = {} 368 instattr = {} 369 370 reversed_bases = self.bases[:] 371 reversed_bases.reverse() 372 373 # For the bases in reverse order, acquire instance attribute 374 # details. 375 376 for cls in reversed_bases: 377 for name, attr in cls.instance_attributes().items(): 378 if not instattr.has_key(name): 379 instattr[name] = set() 380 instattr[name].add(attr.position) 381 382 # Record instance attributes provided by this class and its bases, 383 # along with their positions. 384 385 for name in self.instattr: 386 if not instattr.has_key(name): 387 instattr[name] = set([-1]) # position not yet defined 388 389 if not instattr: 390 self.all_instattr = {} 391 else: 392 positions = instattr.items() 393 instarray = [None] * len(positions) 394 395 # Get the positions in ascending order of list size, with lists 396 # of the same size ordered according to their smallest position 397 # value. 398 399 positions.sort(self._cmp_positions) 400 #print self.name, positions 401 402 # Get the names in position order. 403 404 held = [] 405 406 for name, pos in positions: 407 pos = list(pos) 408 if pos[0] != -1 and instarray[pos[0]] is None: 409 instarray[pos[0]] = name, Attr(pos[0], None, name) 410 else: 411 if pos[0] != -1 or len(pos) > 1: 412 self.instattr_relocated.add(name) 413 held.append((name, pos)) 414 415 for i, attr in enumerate(instarray): 416 if attr is None: 417 name, pos = held.pop() 418 instarray[i] = name, Attr(i, None, name) 419 420 self.all_instattr = dict(instarray) 421 422 self.all_instattr_names = self.all_instattr.keys() 423 424 return self.all_instattr 425 426 def _cmp_positions(self, a, b): 427 name_a, list_a = a 428 name_b, list_b = b 429 if len(list_a) < len(list_b): 430 return -1 431 elif len(list_a) > len(list_b): 432 return 1 433 else: 434 return cmp(min(list_a), min(list_b)) 435 436 def all_attribute_names(self): 437 438 """ 439 Return the names of all attributes provided by instances of this class. 440 """ 441 442 self.allattr_names = self.allattr_names or self.all_attributes().keys() 443 return self.allattr_names 444 445 def all_attributes(self): 446 447 """ 448 Return all attributes for an instance, indicating either the class which 449 provides them or that the instance itself provides them. 450 """ 451 452 if self.allattr is None: 453 self.allattr = {} 454 self.allattr.update(self.all_class_attributes()) 455 for name, attr in self.instance_attributes().items(): 456 if self.allattr.has_key(name): 457 print "Instance attribute %r in %r overrides class attribute." % (name, self) 458 self.allattr[name] = attr 459 return self.allattr 460 461 class Function(NamespaceDict, Naming): 462 463 "An inspected function." 464 465 def __init__(self, name, parent_name, argnames, has_star, has_dstar, global_namespace=None, node=None): 466 NamespaceDict.__init__(self, global_namespace) 467 self.name = name 468 self.parent_name = parent_name 469 self.argnames = argnames 470 self.has_star = has_star 471 self.has_dstar = has_dstar 472 self.node = node 473 474 # Caches. 475 476 self.localnames = None # cache for locals 477 478 # Add parameters to the namespace. 479 480 self._add_parameters(argnames) 481 482 # Image generation details. 483 484 self.location = None 485 self.code_location = None 486 487 def _add_parameters(self, argnames): 488 for name in argnames: 489 if isinstance(name, tuple): 490 self._add_parameters(name) 491 else: 492 self[name] = None 493 494 def __repr__(self): 495 if self.location is not None: 496 return "Function(%r, %r, %r, %r, %r, location=%r)" % ( 497 self.name, self.parent_name, self.argnames, self.has_star, self.has_dstar, self.location 498 ) 499 else: 500 return "Function(%r, %r, %r, %r, %r)" % ( 501 self.name, self.parent_name, self.argnames, self.has_star, self.has_dstar 502 ) 503 504 def make_global(self, name): 505 if name not in self.argnames and not self.has_key(name): 506 self.globals.add(name) 507 else: 508 raise InspectError(self.full_name(), self.node, "Name %r is global and local in %r" % (name, self.full_name())) 509 510 def parameters(self): 511 512 """ 513 Return a dictionary mapping parameter names to their position in the 514 parameter list. 515 """ 516 517 parameters = {} 518 for i, name in enumerate(self.argnames): 519 parameters[name] = i 520 return parameters 521 522 def all_locals(self): 523 524 "Return a dictionary mapping names to local and parameter details." 525 526 return self 527 528 def locals(self): 529 530 "Return a dictionary mapping names to local details." 531 532 if self.localnames is None: 533 self.localnames = {} 534 self.localnames.update(self.all_locals()) 535 for name in self.argnames: 536 del self.localnames[name] 537 return self.localnames 538 539 class UnresolvedName(NamespaceDict, Naming): 540 541 "A module, class or function which was mentioned but could not be imported." 542 543 def __init__(self, name, parent_name, global_namespace=None): 544 NamespaceDict.__init__(self, global_namespace) 545 self.name = name 546 self.parent_name = parent_name 547 548 def all_class_attributes(self): 549 return {} 550 551 def instance_attributes(self): 552 return {} 553 554 def __repr__(self): 555 return "UnresolvedName(%r, %r)" % (self.name, self.parent_name) 556 557 class Module(NamespaceDict): 558 559 "An inspected module's core details." 560 561 def __init__(self, name): 562 NamespaceDict.__init__(self, self) 563 self.name = name 564 565 # Complete lists of classes and functions. 566 567 self.all_objects = set() 568 569 # Constant records. 570 571 self.constant_values = {} 572 self.constant_list = None # cache for constants 573 574 # Image generation details. 575 576 self.location = None 577 self.code_location = None 578 579 # Original location details. 580 581 self.node = None 582 583 def full_name(self): 584 return self.name 585 586 def __repr__(self): 587 if self.location is not None: 588 return "Module(%r, location=%r)" % (self.name, self.location) 589 else: 590 return "Module(%r)" % self.name 591 592 # Attribute methods. 593 594 "Return the module attribute names provided by the module." 595 596 module_attribute_names = NamespaceDict.keys 597 598 def module_attributes(self): 599 600 "Return a dictionary mapping names to module attributes." 601 602 return self 603 604 def constants(self): 605 606 "Return a list of constants." 607 608 if self.constant_list is None: 609 self.constant_list = list(self.constant_values.values()) 610 611 return self.constant_list 612 613 # Program visitors. 614 615 class InspectedModule(ASTVisitor, Module): 616 617 """ 618 An inspected module, providing core details via the Module superclass, but 619 capable of being used as an AST visitor. 620 """ 621 622 def __init__(self, name, importer=None): 623 ASTVisitor.__init__(self) 624 Module.__init__(self, name) 625 self.visitor = self 626 627 self.importer = importer 628 self.loaded = 0 629 630 # Current expression state. 631 632 self.expr = None 633 634 # Namespace state. 635 636 self.in_init = 0 # Find instance attributes in __init__ methods. 637 self.in_loop = 0 # Note loop "membership", affecting assignments. 638 self.namespaces = [] 639 self.module = None 640 641 def parse(self, filename): 642 643 "Parse the file having the given 'filename'." 644 645 module = compiler.parseFile(filename) 646 self.process(module) 647 648 def process(self, module): 649 650 "Process the given 'module'." 651 652 self.node = self.module = module 653 processed = self.dispatch(module) 654 if self.has_key("__all__"): 655 all = self["__all__"] 656 if isinstance(all, compiler.ast.List): 657 for n in all.nodes: 658 self[n.value] = self.importer.add_module(self.name + "." + n.value) 659 return processed 660 661 def vacuum(self): 662 663 "Vacuum the module namespace, removing unloaded module references." 664 665 for name, value in self.items(): 666 if isinstance(value, Module) and not value.loaded: 667 del self[name] 668 669 # Complain about globals not initialised at the module level. 670 671 if isinstance(value, Global): 672 print "Warning: global %r in module %r not initialised at the module level." % (name, self.name) 673 674 # Namespace methods. 675 676 def store(self, name, obj): 677 678 "Record attribute or local 'name', storing 'obj'." 679 680 if not self.namespaces: 681 self.set(name, obj, not self.in_loop) 682 else: 683 self.namespaces[-1].set(name, obj, not self.in_loop) 684 685 # Record all non-local objects. 686 687 if not (self.namespaces and isinstance(self.namespaces[-1], Function)): 688 self.all_objects.add(obj) 689 690 def store_instance_attr(self, name): 691 692 "Record instance attribute 'name' in the current class." 693 694 if self.in_init: 695 696 # Current namespace is the function. 697 # Previous namespace is the class. 698 699 self.namespaces[-2].add_instance_attribute(name) 700 701 def get_parent(self): 702 return (self.namespaces[-1:] or [self])[0] 703 704 # Visitor methods. 705 706 def default(self, node, *args): 707 raise InspectError(self.full_name(), node, "Node class %r is not supported." % node.__class__) 708 709 def dispatch(self, node, *args): 710 return ASTVisitor.dispatch(self, node, *args) 711 712 def NOP(self, node): 713 for n in node.getChildNodes(): 714 self.dispatch(n) 715 return None 716 717 visitAdd = NOP 718 719 visitAnd = NOP 720 721 visitAssert = NOP 722 723 def visitAssign(self, node): 724 self.expr = self.dispatch(node.expr) 725 for n in node.nodes: 726 self.dispatch(n) 727 return None 728 729 def visitAssAttr(self, node): 730 expr = self.dispatch(node.expr) 731 if isinstance(expr, Attr) and expr.name == "self": 732 self.store_instance_attr(node.attrname) 733 return None 734 735 def visitAssList(self, node): 736 for n in node.nodes: 737 self.dispatch(n) 738 return None 739 740 def visitAssName(self, node): 741 if isinstance(self.expr, Attr): 742 self.store(node.name, self.expr.value) 743 else: 744 self.store(node.name, self.expr) 745 return None 746 747 visitAssTuple = visitAssList 748 749 visitAugAssign = NOP 750 751 visitBackquote = NOP 752 753 visitBitand = NOP 754 755 visitBitor = NOP 756 757 visitBitxor = NOP 758 759 visitBreak = NOP 760 761 visitCallFunc = NOP 762 763 def visitClass(self, node): 764 if self.namespaces: 765 print "Class %r in %r is not global: ignored." % (node.name, self.namespaces[-1].full_name()) 766 else: 767 cls = Class(node.name, self.get_parent().full_name(), self, node) 768 769 # Visit the base class expressions, attempting to find concrete 770 # definitions of classes. 771 772 for base in node.bases: 773 expr = self.dispatch(base) 774 if isinstance(expr, Attr): 775 if expr.assignments != 1: 776 raise InspectError(self.full_name(), node, 777 "Base class %r for %r is not constant." % (base, cls.full_name())) 778 else: 779 cls.add_base(expr.value) 780 else: # if expr is None: 781 raise InspectError(self.full_name(), node, 782 "Base class %r for %r is not found: it may be hidden in some way." % (base, cls.full_name())) 783 784 # Make a back reference from the node for code generation. 785 786 node.unit = cls 787 788 # Make an entry for the class. 789 790 self.store(node.name, cls) 791 792 self.namespaces.append(cls) 793 self.dispatch(node.code) 794 self.namespaces.pop() 795 796 return None 797 798 visitCompare = NOP 799 800 def visitConst(self, node): 801 const = Const(node.value) 802 self.constant_values[node.value] = const 803 return const 804 805 visitContinue = NOP 806 807 visitDecorators = NOP 808 809 visitDict = NOP 810 811 visitDiscard = NOP 812 813 visitDiv = NOP 814 815 visitEllipsis = NOP 816 817 visitExec = NOP 818 819 visitExpression = NOP 820 821 visitFloorDiv = NOP 822 823 def visitFor(self, node): 824 self.in_loop = 1 825 self.NOP(node) 826 self.in_loop = 0 827 828 def visitFrom(self, node): 829 if self.importer is None: 830 raise InspectError(self.full_name(), node, 831 "Please use the micropython.Importer class for code which uses the 'from' statement.") 832 833 module = self.importer.load(node.modname, 1) 834 835 #if module is None: 836 # print "Warning:", node.modname, "not imported." 837 838 for name, alias in node.names: 839 if name != "*": 840 if module is not None and module.namespace.has_key(name): 841 attr = module[name] 842 self.store(alias or name, attr.value) 843 if isinstance(attr, Module) and not attr.loaded: 844 self.importer.load(attr.name) 845 846 # Support the import of names from missing modules. 847 848 else: 849 self.store(alias or name, UnresolvedName(name, node.modname, self)) 850 else: 851 if module is not None: 852 for n in module.namespace.keys(): 853 attr = module[n] 854 self.store(n, attr.value) 855 if isinstance(attr, Module) and not attr.loaded: 856 self.importer.load(attr.name) 857 858 return None 859 860 def visitFunction(self, node): 861 function = Function( 862 node.name, 863 self.get_parent().full_name(), 864 node.argnames, 865 (node.flags & 4 != 0), 866 (node.flags & 8 != 0), 867 self, 868 node 869 ) 870 871 # Make a back reference from the node for code generation. 872 873 node.unit = function 874 875 self.namespaces.append(function) 876 877 # Current namespace is the function. 878 # Previous namespace is the class. 879 880 if node.name == "__init__" and isinstance(self.namespaces[-2], Class): 881 self.in_init = 1 882 883 self.dispatch(node.code) 884 self.in_init = 0 885 self.namespaces.pop() 886 887 self.store(node.name, function) 888 return None 889 890 visitGenExpr = NOP 891 892 visitGenExprFor = NOP 893 894 visitGenExprIf = NOP 895 896 visitGenExprInner = NOP 897 898 def visitGetattr(self, node): 899 expr = self.dispatch(node.expr) 900 if isinstance(expr, Attr): 901 value = expr.value 902 if isinstance(value, Module): 903 return value.namespace.get(node.attrname) 904 elif isinstance(value, UnresolvedName): 905 return UnresolvedName(node.attrname, value.full_name(), self) 906 return builtins.get(node.attrname) 907 908 def visitGlobal(self, node): 909 if self.namespaces: 910 for name in node.names: 911 self.namespaces[-1].make_global(name) 912 913 # Record a global entry for the name in the module. 914 915 if not self.has_key(name): 916 self[name] = Global() 917 918 def visitIf(self, node): 919 for test, body in node.tests: 920 self.dispatch(body) 921 if node.else_ is not None: 922 self.dispatch(node.else_) 923 return None 924 925 visitIfExp = NOP 926 927 def visitImport(self, node): 928 if self.importer is None: 929 raise InspectError(self.full_name(), node, 930 "Please use the micropython.Importer class for code which uses the 'import' statement.") 931 932 for name, alias in node.names: 933 if alias is not None: 934 self.store(alias, self.importer.load(name, 1) or UnresolvedName(None, name, self)) 935 else: 936 self.store(name.split(".")[0], self.importer.load(name) or UnresolvedName(None, name.split(".")[0], self)) 937 938 return None 939 940 visitInvert = NOP 941 942 visitKeyword = NOP 943 944 visitLambda = NOP 945 946 visitLeftShift = NOP 947 948 visitList = NOP 949 950 visitListComp = NOP 951 952 visitListCompFor = NOP 953 954 visitListCompIf = NOP 955 956 visitMod = NOP 957 958 def visitModule(self, node): 959 return self.dispatch(node.node) 960 961 visitMul = NOP 962 963 def visitName(self, node): 964 name = node.name 965 if self.namespaces and self.namespaces[-1].has_key(name): 966 return self.namespaces[-1][name] 967 elif self.has_key(name): 968 return self[name] 969 elif builtins.has_key(name): 970 return builtins[name] 971 else: 972 return None 973 974 visitNot = NOP 975 976 visitOr = NOP 977 978 visitPass = NOP 979 980 visitPower = NOP 981 982 visitPrint = NOP 983 984 visitPrintnl = NOP 985 986 visitRaise = NOP 987 988 visitReturn = NOP 989 990 visitRightShift = NOP 991 992 visitSlice = NOP 993 994 visitSliceobj = NOP 995 996 def visitStmt(self, node): 997 for n in node.nodes: 998 self.dispatch(n) 999 return None 1000 1001 visitSub = NOP 1002 1003 visitSubscript = NOP 1004 1005 def visitTryExcept(self, node): 1006 self.dispatch(node.body) 1007 for name, var, n in node.handlers: 1008 self.dispatch(n) 1009 if node.else_ is not None: 1010 self.dispatch(node.else_) 1011 return None 1012 1013 visitTryFinally = NOP 1014 1015 visitTuple = NOP 1016 1017 visitUnaryAdd = NOP 1018 1019 visitUnarySub = NOP 1020 1021 def visitWhile(self, node): 1022 self.in_loop = 1 1023 self.NOP(node) 1024 self.in_loop = 0 1025 1026 visitWith = NOP 1027 1028 visitYield = NOP 1029 1030 class Global: 1031 1032 """ 1033 A reference to an object assigned to a global from outside the module 1034 top-level. 1035 """ 1036 1037 pass 1038 1039 # Built-in types initialisation. 1040 1041 class Builtins(Module): 1042 1043 "The special built-in types module." 1044 1045 def __init__(self): 1046 Module.__init__(self, "__builtins__") 1047 self.loaded = 1 1048 self.module = None 1049 1050 for key in ['ArithmeticError', 'AssertionError', 'AttributeError', 1051 'BaseException', 'DeprecationWarning', 'EOFError', 'Ellipsis', 1052 'EnvironmentError', 'Exception', 'False', 'FloatingPointError', 1053 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 1054 'ImportWarning', 'IndentationError', 'IndexError', 'KeyError', 1055 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'NameError', 1056 'None', 'NotImplemented', 'NotImplementedError', 'OSError', 1057 'OverflowError', 'PendingDeprecationWarning', 'ReferenceError', 1058 'RuntimeError', 'RuntimeWarning', 'StandardError', 'StopIteration', 1059 'SyntaxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 1060 'TabError', 'True', 'TypeError', 'UnboundLocalError', 1061 'UnicodeDecodeError', 'UnicodeEncodeError', 'UnicodeError', 1062 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning', 1063 'ValueError', 'Warning', 'ZeroDivisionError', 1064 'basestring', 'bool', 'buffer', 'complex', 'dict', 'file', 'float', 1065 'frozenset', 'int', # 'list', 1066 'long', 'object', 'set', 'slice', 'str', 1067 'tuple', 'type', 'unicode', 'xrange']: 1068 self.store(key, Class(key, self.full_name(), self)) 1069 1070 # NOTE: Temporary measure - provide detailed built-ins. 1071 1072 cls = Class("list", self.full_name(), self) 1073 cls.set("__iter__", Function("__iter__", cls.full_name(), [], 0, 0, cls)) 1074 self.store("list", cls) 1075 1076 cls = Class("listiterator", self.full_name(), self) 1077 cls.set("next", Function("next", cls.full_name(), [], 0, 0, cls)) 1078 self.store("listiterator", cls) 1079 1080 # NOTE: Incomplete: some functions have more than one parameter. 1081 1082 for key in ['__import__', 'abs', 'all', 'any', 'callable', 'chr', 1083 'classmethod', 'cmp', 'compile', 'delattr', 'dir', 'divmod', 1084 'enumerate', 'eval', 'execfile', 'filter', 'getattr', 'globals', 1085 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'isinstance', 1086 'issubclass', 'iter', 'len', 'locals', 'map', 'max', 'min', 'oct', 1087 'open', 'ord', 'pow', 'property', 'range', 'raw_input', 'reduce', 1088 'reload', 'repr', 'reversed', 'round', 'setattr', 'sorted', 1089 'staticmethod', 'sum', 'super', 'unichr', 'vars', 'zip']: 1090 self[key] = Function(key, self.full_name(), ['arg'], 0, 0, self) 1091 1092 def store(self, name, obj): 1093 self.set(name, obj) 1094 self.all_objects.add(obj) 1095 1096 def vacuum(self): 1097 pass 1098 1099 builtins = Builtins() 1100 1101 # vim: tabstop=4 expandtab shiftwidth=4