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