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