1 #!/usr/bin/env python 2 3 """ 4 Produce syspython code from an inspected program. 5 6 Copyright (C) 2006, 2007, 2010, 2011, 2012, 2013 Paul Boddie <paul@boddie.org.uk> 7 8 This program is free software; you can redistribute it and/or modify it under 9 the terms of the GNU General Public License as published by the Free Software 10 Foundation; either version 3 of the License, or (at your option) any later 11 version. 12 13 This program is distributed in the hope that it will be useful, but WITHOUT 14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 16 details. 17 18 You should have received a copy of the GNU General Public License along with 19 this program. If not, see <http://www.gnu.org/licenses/>. 20 """ 21 22 from micropython.common import * 23 from micropython.data import * 24 from micropython.errors import * 25 from os.path import exists, extsep, join 26 import compiler.ast 27 import sys 28 import os 29 30 try: 31 set 32 except NameError: 33 from sets import Set as set 34 35 # Convenience definitions. 36 37 module_attribute = compiler.ast.Getattr 38 special_name = compiler.ast.Name 39 40 def quoted_ref(obj): 41 return compiler.ast.CallFunc("__static__", [compiler.ast.Const(obj.full_name())]) 42 43 def quoted_name(s): 44 return compiler.ast.Const(s) 45 46 # Source code classes. 47 48 class ConvertedSource(ASTVisitor): 49 50 "A conversion of module source code to syspython." 51 52 def __init__(self, module, program): 53 self.visitor = self 54 self.module = module 55 self.program = program 56 self.objtable = program.get_object_table() 57 self.in_main = False 58 self.units = [] 59 60 def get_unit(self): 61 return self.units[-1] 62 63 def get_module(self): 64 return self.units[0] 65 66 def to_stream(self, stream): 67 68 "Write the converted code to the given 'stream'." 69 70 module = self.dispatch(self.module.astnode) 71 stream.write(str(module)) 72 73 def NOP(self, node): 74 return node 75 76 def visitModule(self, node): 77 module = node.unit 78 self.units.append(module) 79 80 definitions = self.process_definitions(node) 81 82 # __globalnames__(name, ...) 83 84 globalnames = module.module_attribute_names() and [ 85 compiler.ast.CallFunc( 86 special_name("__globalnames__"), 87 [special_name(name) for name in module.module_attribute_names()] 88 ) 89 ] or [] 90 91 # def __main__(): 92 # ... 93 94 self.in_main = True 95 96 main = compiler.ast.Function( 97 [], "__main__", [], [], 0, "Module initialisation.", 98 compiler.ast.Stmt(globalnames + self.dispatch(node.node).nodes) 99 ) 100 101 self.in_main = False 102 self.units.pop() 103 104 return compiler.ast.Module(node.doc, compiler.ast.Stmt(definitions + [main])) 105 106 # Statements. 107 108 def visitAssert(self, node): 109 return compiler.ast.Assert(self.dispatch(node.test), node.fail and self.dispatch(node.fail)) 110 111 def visitAssign(self, node): 112 expr = self.dispatch(node.expr) 113 return compiler.ast.Stmt([self.dispatch(n, expr) for n in node.nodes]) 114 115 def visitAugAssign(self, node): 116 117 # lvalue = op(lvalue, expr) 118 # -> __fn__(lvalue, op(lvalue, expr)) 119 120 op_name = operator_functions[node.op] 121 122 return self.dispatch(node.node, compiler.ast.CallFunc( 123 module_attribute("operator", op_name), 124 [self.dispatch(node.node), self.dispatch(node.expr)] 125 )) 126 127 visitBreak = NOP 128 129 def visitClass(self, node): 130 if not used_by_unit(node): 131 return compiler.ast.Stmt([]) 132 133 self.units.append(node.unit) 134 try: 135 # Incorporate class body code in the main function. 136 137 if self.in_main: 138 return self.dispatch(node.code) 139 else: 140 return self._visitClassDefinition(node) 141 142 finally: 143 self.units.pop() 144 145 def _visitClassDefinition(self, node): 146 cls = node.unit 147 148 # __instattrs__(name, ...) 149 # __clsattrs__(name, ...) 150 151 instattrs = cls.instance_attribute_names() and [ 152 compiler.ast.CallFunc( 153 special_name("__instattrs__"), 154 [special_name(name) for name in cls.instance_attribute_names()] 155 ) 156 ] or [] 157 158 clsattrs = cls.class_attribute_names() and [ 159 compiler.ast.CallFunc( 160 special_name("__clsattrs__"), 161 [special_name(name) for name in cls.class_attribute_names()] 162 ) 163 ] or [] 164 165 # __inherited__(superclass, name, ...) 166 # ... 167 168 attrs_by_cls = {} 169 for attrname, attr in cls.all_class_attributes().items(): 170 supercls = attr.parent 171 if supercls is cls: 172 continue 173 if not attrs_by_cls.has_key(supercls): 174 attrs_by_cls[supercls] = [] 175 attrs_by_cls[supercls].append(attrname) 176 177 inherited = [] 178 179 for supercls, attrnames in attrs_by_cls.items(): 180 inherited.append( 181 compiler.ast.CallFunc( 182 special_name("__inherited__"), 183 [quoted_ref(supercls)] + [special_name(name) for name in attrnames] 184 )) 185 186 # __descendants__(name, ...) 187 188 descendants = cls.all_descendants() and [ 189 compiler.ast.CallFunc( 190 special_name("__descendants__"), 191 [special_name(name) for name in cls.all_descendants().keys()] 192 ) 193 ] or [] 194 195 # Process all the definitions defined inside the class. 196 197 definitions = self.process_definitions(node) 198 199 return compiler.ast.Class(node.name, [], node.doc, 200 compiler.ast.Stmt(instattrs + clsattrs + inherited + descendants + definitions) 201 ) 202 203 visitContinue = NOP 204 205 def visitDiscard(self, node): 206 return compiler.ast.Discard(self.dispatch(node.expr)) 207 208 def visitFor(self, node): 209 210 """ 211 Convert from... 212 213 for <assign> in <list>: 214 <body> 215 [ else: 216 <else_> ] 217 218 ...to... 219 220 _it = iter(<list>) 221 while True: 222 try: 223 <assign> = _it.next() 224 except StopIteration: 225 [ <else_> ] 226 break 227 else: 228 <body> 229 """ 230 231 unit = self.get_unit() 232 temp = quoted_name(unit.temp_usage) 233 unit.temp_usage += 1 234 235 else_nodes = node.else_ and self.dispatch(node.else_).nodes or [] 236 237 return compiler.ast.Stmt([ 238 # __storetemp__(_it, __loadattr__(__builtins__, iter)(<list>)) 239 compiler.ast.CallFunc(special_name("__storetemp__"), [ 240 temp, 241 compiler.ast.CallFunc( 242 compiler.ast.CallFunc(special_name("__loadattr__"), 243 [special_name("__builtins__"), special_name("iter")] 244 ), 245 [self.dispatch(node.list)] 246 ) 247 ]), 248 # while True: ... 249 compiler.ast.While( 250 special_name("True"), 251 # try: ... 252 compiler.ast.TryExcept( 253 compiler.ast.Stmt([ 254 # <assign> = ... 255 self.dispatch(node.assign, 256 # _it.next() 257 compiler.ast.CallFunc( 258 compiler.ast.CallFunc(special_name("__loadattr__"), [ 259 compiler.ast.CallFunc(special_name("__loadtemp__"), [temp]), 260 special_name("next") 261 ]), 262 [] 263 ) 264 ) 265 ]), 266 # except StopIteration: ... 267 [(special_name("StopIteration"), None, compiler.ast.Stmt(else_nodes + [compiler.ast.Break()]))], 268 # else: ... 269 self.dispatch(node.body) 270 ), 271 None 272 ) 273 ]) 274 275 def visitFrom(self, node): 276 277 # Generate __main__ function calls for each step in the imported module 278 # hierarchy. 279 280 statements = [] 281 282 for modname in self.module.get_module_paths(node.modname): 283 statements.append( 284 compiler.ast.CallFunc(special_name("%s.__main__" % modname ), []) 285 ) 286 287 for name, alias in node.names: 288 statements.append( 289 compiler.ast.Assign( 290 [special_name(alias or name)], 291 compiler.ast.CallFunc( 292 special_name("__loadattribute__"), 293 [special_name(node.modname), special_name(name)] 294 ) 295 ) 296 ) 297 298 return compiler.ast.Stmt(statements) 299 300 def visitFunction(self, node): 301 if not used_by_unit(node): 302 return compiler.ast.Stmt([]) 303 304 self.units.append(node.unit) 305 306 try: 307 # Ignore functions when generating the main function. 308 309 if self.in_main: 310 return compiler.ast.Stmt([]) 311 else: 312 return self._visitFunctionDefinition(node) 313 finally: 314 self.units.pop() 315 316 def _visitFunctionDefinition(self, node): 317 fn = node.unit 318 319 # __localnames__(name, ...) 320 # __globalnames__(name, ...) 321 322 localnames = fn.all_locals() and [ 323 compiler.ast.CallFunc( 324 special_name("__localnames__"), 325 [special_name(name) for name in fn.all_locals().keys()] 326 ) 327 ] or [] 328 329 globalnames = fn.globals and [ 330 compiler.ast.CallFunc( 331 special_name("__globalnames__"), 332 [special_name(name) for name in fn.globals] 333 ) 334 ] or [] 335 336 defaults = [self.dispatch(n) for n in node.defaults] 337 338 # NOTE: Should generate guards for attribute usage operations. 339 340 code = self.dispatch(node.code) 341 342 return compiler.ast.Function(node.decorators, node.name, node.argnames, defaults, node.flags, node.doc, 343 compiler.ast.Stmt(localnames + globalnames + code.nodes)) 344 345 visitGlobal = NOP 346 347 def visitIf(self, node): 348 return compiler.ast.If( 349 [(self.dispatch(compare), self.dispatch(stmt)) for (compare, stmt) in node.tests], 350 node.else_ and self.dispatch(node.else_) 351 ) 352 353 def visitImport(self, node): 354 355 # Generate __main__ function calls for each step in the imported module 356 # hierarchy. 357 358 statements = [] 359 360 for name, alias in node.names: 361 for modname in self.module.get_module_paths(name): 362 statements.append( 363 compiler.ast.CallFunc(compiler.ast.Getattr(modname, "__main__"), []) 364 ) 365 366 statements.append( 367 compiler.ast.Assign( 368 [special_name(alias or name.split(".")[0])], 369 compiler.ast.CallFunc( 370 special_name("__static__"), 371 [special_name(name)] 372 ) 373 ) 374 ) 375 376 return compiler.ast.Stmt(statements) 377 378 def visitPass(self, node): 379 if not isinstance(self.get_unit(), Class): 380 return compiler.ast.Pass() 381 else: 382 return compiler.ast.Stmt([]) 383 384 def visitPrint(self, node): 385 return compiler.ast.Print( 386 [self.dispatch(n) for n in node.nodes], 387 node.dest and self.dispatch(node.dest) 388 ) 389 390 def visitPrintnl(self, node): 391 return compiler.ast.Print( 392 [self.dispatch(n) for n in node.nodes], 393 node.dest and self.dispatch(node.dest) 394 ) 395 396 def visitRaise(self, node): 397 return compiler.ast.Raise( 398 node.expr1 and self.dispatch(node.expr1), 399 node.expr2 and self.dispatch(node.expr2), 400 node.expr3 and self.dispatch(node.expr3) 401 ) 402 403 def visitReturn(self, node): 404 return compiler.ast.Return(self.dispatch(node.value)) 405 406 def visitStmt(self, node): 407 return compiler.ast.Stmt([self.dispatch(n) for n in node.nodes]) 408 409 def visitTryExcept(self, node): 410 # NOTE: Need to dispatch to the assignment with the exception. 411 return compiler.ast.TryExcept( 412 self.dispatch(node.body), 413 [(spec and self.dispatch(spec), assign and self.dispatch(assign), self.dispatch(statement)) 414 for spec, assign, statement in node.handlers], 415 node.else_ and self.dispatch(node.else_) 416 ) 417 418 def visitTryFinally(self, node): 419 return compiler.ast.TryFinally( 420 self.dispatch(node.body), 421 self.dispatch(node.final) 422 ) 423 424 def visitWhile(self, node): 425 return compiler.ast.While( 426 self.dispatch(node.test), 427 self.dispatch(node.body), 428 node.else_ and self.dispatch(node.else_) 429 ) 430 431 def visitYield(self, node): 432 return compiler.ast.Yield(self.dispatch(node.value)) 433 434 # Expression-related helper methods. 435 436 def _visitBitBinary(self, node): 437 op_name = operator_functions[node.__class__.__name__] 438 last = self.dispatch(node.nodes[0]) 439 440 for n in node.nodes[1:]: 441 last = compiler.ast.CallFunc( 442 module_attribute("operator", op_name), 443 [last, self.dispatch(n)] 444 ) 445 446 return last 447 448 def _visitBinary(self, node): 449 op_name = operator_functions[node.__class__.__name__] 450 451 return compiler.ast.CallFunc( 452 module_attribute("operator", op_name), 453 [self.dispatch(node.left), self.dispatch(node.right)] 454 ) 455 456 def _visitUnary(self, node): 457 op_name = operator_functions[node.__class__.__name__] 458 459 return compiler.ast.CallFunc( 460 module_attribute("operator", op_name), 461 [self.dispatch(node.expr)] 462 ) 463 464 def _generateValue(self, value): 465 466 # Literal constants. 467 468 if isinstance(value, Const): 469 return compiler.ast.Const(value.get_value()) 470 471 # Other constant structures. 472 473 if isinstance(value, Constant): 474 return quoted_ref(value) 475 476 return None 477 478 # Expressions. 479 480 def visitAdd(self, node): 481 return self._visitBinary(node) 482 483 def visitAnd(self, node): 484 return compiler.ast.And([self.dispatch(n) for n in node.nodes]) 485 486 def visitAssAttr(self, node, expr): 487 488 # NOTE: Derived from Getattr support. 489 490 accessor = self.dispatch(node.expr) 491 492 # NOTE: Replicate the _generateAttr logic. 493 # NOTE: Should be able to store concrete value details on generated 494 # NOTE: nodes, such as whether an expression yields a constant. 495 496 # NOTE: Known targets: 497 # NOTE: __storeattr__ and __storeattrcontext__ 498 499 # NOTE: Attributes of self. 500 501 # Usage observations. 502 503 targets = self.possible_accessors_from_usage(node, defining_users=0) 504 505 # Record whether types were already deduced. If not, get types using 506 # only this attribute. 507 508 if not targets: 509 targets = self.possible_accessors_for_attribute(node.attrname) 510 511 attrs = self.get_attributes(targets, node.attrname) 512 513 # Generate optimisations where only a single attribute applies. 514 515 if len(attrs) == 1: 516 attr = attrs[0] 517 518 # Static attributes. 519 520 if attr.is_static_attribute(): 521 522 # Static attributes may be accompanied by a different context 523 # depending on the accessor. 524 # NOTE: Should determine whether the context is always replaced. 525 526 return compiler.ast.CallFunc( 527 special_name("__storeattrcontextcond__"), 528 [accessor, special_name(node.attrname), expr] 529 ) 530 531 # Non-static attributes. 532 533 return compiler.ast.CallFunc( 534 special_name("__storeattr__"), 535 [accessor, special_name(node.attrname), expr] 536 ) 537 538 # With no usable deductions, generate a table-based access. 539 540 return compiler.ast.CallFunc( 541 special_name("__storeattrindex__"), 542 [accessor, special_name(node.attrname), expr] 543 ) 544 545 def visitAssList(self, node, expr): 546 return compiler.ast.Stmt([ 547 self.dispatch(n, compiler.ast.CallFunc( 548 module_attribute("operator", "getitem"), 549 [expr, i] 550 )) 551 for (i, n) in enumerate(node.nodes) 552 ]) 553 554 def visitAssName(self, node, expr): 555 unit = self.get_unit() 556 557 # Generate appropriate name access operation. 558 # NOTE: Should generate guards for attribute usage operations. 559 560 scope = getattr(node, "_scope", None) 561 if not scope: 562 attr, scope, from_name = self.get_unit()._get_with_scope(node.name) 563 564 if scope == "constant": 565 return node 566 elif scope == "local": 567 568 # Function locals are stored using a function. 569 570 if isinstance(unit, Function): 571 return compiler.ast.CallFunc( 572 special_name("__storelocal__"), 573 [special_name(node.name), expr] 574 ) 575 576 # Class locals are class attribute references. 577 578 elif isinstance(unit, Class): 579 return compiler.ast.CallFunc( 580 special_name("__storeattrcontext__"), 581 [quoted_ref(unit), special_name(node.name), expr] 582 ) 583 584 # Module locals are module attribute references. 585 586 elif isinstance(unit, Module): 587 return compiler.ast.CallFunc( 588 special_name("__storeattr__"), 589 [quoted_ref(unit), special_name(node.name), expr] 590 ) 591 else: 592 raise TranslateError("Program unit has no local %r." % name) 593 594 elif scope == "global": 595 596 # Globals are references to module attributes. 597 598 return compiler.ast.CallFunc( 599 special_name("__storeattr__"), 600 [quoted_ref(self.get_module()), special_name(node.name), expr] 601 ) 602 603 elif scope == "builtin": 604 605 # Builtins are accessed via the __builtins__ module. 606 607 return compiler.ast.CallFunc( 608 special_name("__storeattr__"), 609 [special_name("__builtins__"), special_name(node.name), expr] 610 ) 611 612 else: 613 # NOTE: This may happen because a class attribute is optimised away. 614 return compiler.ast.CallFunc( 615 special_name("__storeunknown__"), 616 [special_name(node.name), expr] 617 ) 618 619 visitAssTuple = visitAssList 620 621 def visitBitand(self, node): 622 self._visitBitBinary(node) 623 624 def visitBitor(self, node): 625 self._visitBitBinary(node) 626 627 def visitBitxor(self, node): 628 self._visitBitBinary(node) 629 630 def visitCallFunc(self, node): 631 return compiler.ast.CallFunc( 632 self.dispatch(node.node), 633 [self.dispatch(arg) for arg in node.args], 634 node.star_args and [self.dispatch(arg) for arg in node.star_args], 635 node.dstar_args and [self.dispatch(arg) for arg in node.dstar_args] 636 ) 637 638 def visitCompare(self, node): 639 nodes = [] 640 left = node.expr 641 for op_name, right in node.ops: 642 nodes.append( 643 compiler.ast.CallFunc( 644 module_attribute("operator", operator_functions.get(op_name)), 645 [self.dispatch(left), self.dispatch(right)] 646 ) 647 ) 648 left = right 649 return compiler.ast.And(nodes) 650 651 visitConst = NOP 652 653 def visitDict(self, node): 654 return compiler.ast.Dict([(self.dispatch(key), self.dispatch(value)) for (key, value) in node.items]) 655 656 def visitDiv(self, node): 657 return self._visitBinary(node) 658 659 def visitFloorDiv(self, node): 660 return self._visitBinary(node) 661 662 def visitGetattr(self, node, expr=None): 663 if expr: 664 return self.visitAssAttr(node, expr) 665 666 unit = self.get_unit() 667 668 accessor = self.dispatch(node.expr) 669 670 # The target, on which the access is performed, may influence the effect 671 # on the context. We can only reliably assume that a literal constant is 672 # an instance: all other "instances" may actually be classes in certain 673 # cases. 674 675 target = node._expr 676 instance_target = isinstance(target, Const) 677 678 # Attempt to deduce attributes from explicit annotations. 679 680 attrs = self.possible_attributes_from_annotation(node) 681 682 if len(attrs) == 1: 683 attr, value = attrs[0] 684 685 # Constant values can be obtained directly. 686 687 v = self._generateValue(value) 688 if v: return v 689 690 # Static attributes can be obtained via their parent. 691 692 if attr.is_static_attribute(): 693 return compiler.ast.CallFunc( 694 special_name(instance_target and "__loadattrcontext__" or "__loadattr__"), 695 [self._generateValue(attr.parent), special_name(node.attrname)]) 696 697 # Attributes of self, which is by definition an instance. 698 699 if self.provides_self_access(node, unit): 700 701 # Find instance attributes. 702 703 attr = unit.parent.instance_attributes().get(node.attrname) 704 705 if attr: 706 707 # Emit self.attrname without context overriding. 708 709 return compiler.ast.CallFunc( 710 special_name("__loadattr__"), [ 711 accessor, special_name(node.attrname) 712 ]) 713 714 # Find class attributes. 715 # The context will be overridden for compatible class attributes 716 # only. 717 718 attr = unit.parent.get(node.attrname) 719 720 if attr: 721 722 # Constant attributes. 723 724 if attr.is_strict_constant(): 725 v = self._generateValue(attr.get_value()) 726 if v: return v 727 728 # Compatible class attributes. 729 730 if attr.defined_within_hierarchy(): 731 return compiler.ast.CallFunc( 732 special_name("__loadattrcontext__"), [ 733 self._generateValue(attr.parent), special_name(node.attrname) 734 ]) 735 736 # Incompatible class attributes. 737 738 elif attr.defined_outside_hierarchy(): 739 return compiler.ast.CallFunc( 740 special_name("__loadattr__"), [ 741 self._generateValue(attr.parent), special_name(node.attrname) 742 ]) 743 744 # Unknown or mixed compatibility. 745 746 return compiler.ast.CallFunc( 747 special_name("__loadattrcontextcond__"), [ 748 self._generateValue(attr.parent), special_name(node.attrname) 749 ]) 750 751 # Usage observations. 752 753 targets = self.possible_accessors_from_usage(node, defining_users=0) 754 755 # Record whether types were already deduced. If not, get types using 756 # only this attribute. 757 758 if not targets: 759 targets = self.possible_accessors_for_attribute(node.attrname) 760 761 attrs = self.get_attributes(targets, node.attrname) 762 763 # Generate optimisations where only a single attribute applies. 764 765 if len(attrs) == 1: 766 attr = attrs[0] 767 768 # Static attributes, but potentially non-static targets. 769 770 if attr.is_static_attribute(): 771 772 # Static attributes may be accompanied by a different context 773 # depending on the accessor. 774 # NOTE: Should determine whether the context is always replaced. 775 776 return compiler.ast.CallFunc( 777 special_name(instance_target and "__loadattrcontext__" or "__loadattrcontextcond__"), 778 [accessor, special_name(node.attrname)] 779 ) 780 781 # Non-static attributes. 782 783 return compiler.ast.CallFunc( 784 special_name("__loadattr__"), 785 [accessor, special_name(node.attrname)] 786 ) 787 788 # With no usable deductions, generate a table-based access. 789 790 access = compiler.ast.CallFunc( 791 special_name("__loadattrindexcontextcond__"), 792 [accessor, special_name(node.attrname)] 793 ) 794 795 # class.__class__ => __builtins__.type 796 797 if node.attrname == "__class__": 798 799 # __storetemp__(n, <accessor>) 800 # __isclass__(n) and __loadattr__(__builtins__, type) or <access> 801 802 temp = quoted_name(unit.temp_usage) 803 unit.temp_usage += 1 804 805 return compiler.ast.Stmt([ 806 compiler.ast.CallFunc(special_name("__storetemp__"), [temp, access]), 807 compiler.ast.Or([ 808 compiler.ast.And([ 809 compiler.ast.CallFunc( 810 special_name("__isclass__"), 811 [compiler.ast.CallFunc(special_name("__loadtemp__"), [temp])] 812 ), 813 compiler.ast.CallFunc( 814 special_name("__loadattr__"), 815 [special_name("__builtins__"), special_name("type")] 816 ) 817 ]), 818 access 819 ]) 820 ]) 821 822 # General accesses. 823 824 else: 825 return access 826 827 def visitGenExpr(self, node): 828 return compiler.ast.GenExpr(self.dispatch(node.code)) 829 830 def visitGenExprFor(self, node): 831 return compiler.ast.GenExprFor( 832 self.dispatch(node.assign), # NOTE: Needs to dispatch to AssName/AssTuple/AssList with an expression. 833 self.dispatch(node.iter), 834 [self.dispatch(n) for n in node.ifs] 835 ) 836 837 def visitGenExprIf(self, node): 838 return compiler.ast.GenExprIf(self.dispatch(node.test)) 839 840 def visitGenExprInner(self, node): 841 return compiler.ast.GenExprInner( 842 self.dispatch(node.expr), 843 [self.dispatch(n) for n in node.quals] 844 ) 845 846 def visitIfExp(self, node): 847 return compiler.ast.IfExp( 848 self.dispatch(node.then), 849 self.dispatch(node.test), 850 self.dispatch(node.else_) 851 ) 852 853 def visitInvert(self, node): 854 return self._visitUnary(node) 855 856 def visitKeyword(self, node): 857 return compiler.ast.Keyword( 858 node.name, 859 self.dispatch(node.expr) 860 ) 861 862 def visitLambda(self, node): 863 self.units.append(node.unit) 864 865 try: 866 return compiler.ast.Lambda( 867 node.argnames, 868 [self.dispatch(n) for n in node.defaults], 869 node.flags, 870 self.dispatch(node.code) 871 ) 872 finally: 873 self.units.pop() 874 875 def visitLeftShift(self, node): 876 return self._visitBinary(node) 877 878 def visitList(self, node, expr=None): 879 if expr: 880 return self.visitAssList(node, expr) 881 return compiler.ast.List([self.dispatch(n) for n in node.nodes]) 882 883 def visitListComp(self, node): 884 return compiler.ast.ListComp( 885 self.dispatch(node.expr), 886 [self.dispatch(n) for n in node.quals] 887 ) 888 889 def visitListCompFor(self, node): 890 return compiler.ast.ListCompFor( 891 self.dispatch(node.assign), # NOTE: Needs to dispatch to AssName/AssTuple/AssList with an expression. 892 self.dispatch(node.list), 893 [self.dispatch(n) for n in node.ifs] 894 ) 895 896 def visitListCompIf(self, node): 897 return compiler.ast.ListCompIf( 898 self.dispatch(node.test) 899 ) 900 901 def visitMod(self, node): 902 return self._visitBinary(node) 903 904 def visitMul(self, node): 905 return self._visitBinary(node) 906 907 def visitName(self, node, expr=None): 908 if expr: 909 return self.visitAssName(node, expr) 910 911 unit = self.get_unit() 912 attr = node._attr 913 scope = node._scope 914 915 # Generate appropriate name access operation. 916 917 if scope == "constant": 918 return node 919 920 # Function locals are referenced normally. 921 922 elif scope == "local" and isinstance(unit, Function): 923 return node 924 925 # Other attributes should already be resolved. 926 927 elif attr is not None: 928 return compiler.ast.CallFunc( 929 special_name("__loadattr__"), 930 [quoted_ref(attr.parent), special_name(node.name)] 931 ) 932 933 # NOTE: Unknown attributes may arise because a class attribute has been 934 # NOTE: optimised away. 935 936 else: 937 return compiler.ast.CallFunc( 938 special_name("__loadunknown__"), 939 [special_name(node.name)] 940 ) 941 942 def visitNot(self, node): 943 return compiler.ast.Not(self.dispatch(node.expr)) 944 945 def visitOr(self, node): 946 return compiler.ast.Or([self.dispatch(n) for n in node.nodes]) 947 948 def visitPower(self, node): 949 return self._visitBinary(node) 950 951 def visitRightShift(self, node): 952 return self._visitBinary(node) 953 954 def visitSlice(self, node, expr=None): 955 return compiler.ast.CallFunc( 956 module_attribute("operator", expr and "setslice" or "getslice"), 957 [self.dispatch(node.expr), node.lower and self.dispatch(node.lower), node.upper and self.dispatch(node.upper)] 958 + (expr and [expr] or []) 959 ) 960 961 def visitSliceobj(self, node): 962 return compiler.ast.Sliceobj([self.dispatch(n) for n in node.nodes]) 963 964 def visitSub(self, node): 965 return self._visitBinary(node) 966 967 def visitSubscript(self, node, expr=None): 968 return compiler.ast.CallFunc( 969 module_attribute("operator", expr and "setitem" or "getitem"), 970 [self.dispatch(node.expr), compiler.ast.Tuple([self.dispatch(sub) for sub in node.subs])] 971 + (expr and [expr] or []) 972 ) 973 974 def visitTuple(self, node, expr=None): 975 if expr: 976 return self.visitAssTuple(node, expr) 977 return compiler.ast.Tuple([self.dispatch(n) for n in node.nodes]) 978 979 def visitUnaryAdd(self, node): 980 return self._visitUnary(node) 981 982 def visitUnarySub(self, node): 983 return self._visitUnary(node) 984 985 # Type-related methods. 986 987 def possible_accessor_types(self, node, defining_users=1): 988 return set([tn for (tn, st) in ASTVisitor.possible_accessor_types(self, node, defining_users)]) 989 990 def get_possible_accessors(self, attrname): 991 992 "Return a list of accessors supporting 'attrname'." 993 994 targets = [] 995 996 for target_name in self.objtable.any_possible_objects([attrname]): 997 targets.append(self.objtable.get_object(target_name)) 998 999 return targets 1000 1001 def get_attributes(self, targets, attrname): 1002 1003 "Return a list of attributes for 'targets' supporting 'attrname'." 1004 1005 attributes = [] 1006 1007 for target in targets: 1008 attributes.append(self.objtable.access(target.full_name(), attrname)) 1009 1010 return attributes 1011 1012 # Convenience functions. 1013 1014 def convert(module, program, filename): 1015 stream = open(filename, "wb") 1016 try: 1017 source = ConvertedSource(module, program) 1018 source.to_stream(stream) 1019 finally: 1020 stream.close() 1021 1022 def translate(program, directory): 1023 if not exists(directory): 1024 os.mkdir(directory) 1025 1026 # NOTE: Add constants here. 1027 1028 for module in program.get_importer().get_modules(): 1029 convert(module, program, join(directory, "%s%spy" % (module.full_name(), extsep))) 1030 1031 # vim: tabstop=4 expandtab shiftwidth=4