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 constant_attribute = compiler.ast.Getattr 38 special_name = compiler.ast.Name 39 40 def quoted_name(s): 41 return compiler.ast.Const(s) 42 43 def quoted_ref(obj): 44 return compiler.ast.CallFunc("static", [quoted_name(obj.full_name())]) 45 46 def module_attribute(module_name, attrname): 47 return special_name(module_name + "." + attrname) 48 49 # Special function names. 50 # Some of the assignment operations cannot be supported unless attribute usage 51 # observations are being made. 52 53 assattr_functions = ("storeattrcontext", "storeattrcontext", "storeattr", 54 "storeattrindex", None) 55 getattr_functions = ("loadattrcontext", "loadattrcontextcond", "loadattr", 56 "loadattrindex", "loadattrindexcontextcond") 57 58 # Source code classes. 59 60 class ConvertedSource(ASTVisitor): 61 62 "A conversion of module source code to syspython." 63 64 def __init__(self, module, program): 65 self.visitor = self 66 self.module = module 67 self.program = program 68 self.objtable = program.get_object_table() 69 self.in_main = False 70 self.units = [] 71 72 def get_unit(self): 73 return self.units[-1] 74 75 def get_module(self): 76 return self.units[0] 77 78 def to_stream(self, stream): 79 80 "Write the converted code to the given 'stream'." 81 82 module = self.dispatch(self.module.astnode) 83 stream.write(str(module)) 84 85 def NOP(self, node): 86 return node 87 88 def visitModule(self, node): 89 module = node.unit 90 self.units.append(module) 91 92 definitions = self.process_definitions(node) 93 94 # globalnames(name, ...) 95 96 globalnames = module.module_attribute_names() and [ 97 compiler.ast.CallFunc( 98 special_name("globalnames"), 99 [special_name(attr.name) for attr in module.attributes_as_list()] 100 ) 101 ] or [] 102 103 # def __main__(): 104 # ... 105 106 self.in_main = True 107 108 main = compiler.ast.Function( 109 [], "__main__", [], [], 0, "Module initialisation.", 110 compiler.ast.Stmt(globalnames + self.dispatch(node.node).nodes) 111 ) 112 113 self.in_main = False 114 self.units.pop() 115 116 return compiler.ast.Module(node.doc, compiler.ast.Stmt(definitions + [main])) 117 118 # Statements. 119 120 def visitAssert(self, node): 121 return compiler.ast.Assert(self.dispatch(node.test), node.fail and self.dispatch(node.fail)) 122 123 def visitAssign(self, node): 124 expr = self.dispatch(node.expr) 125 return compiler.ast.Stmt([self.dispatch(n, expr) for n in node.nodes]) 126 127 def visitAugAssign(self, node): 128 129 # lvalue = op(lvalue, expr) 130 # -> fn(lvalue, op(lvalue, expr)) 131 132 op_name = operator_functions[node.op] 133 134 return self.dispatch(node.node, compiler.ast.CallFunc( 135 module_attribute("operator", op_name), 136 [self.dispatch(node.node), self.dispatch(node.expr)] 137 )) 138 139 visitBreak = NOP 140 141 def visitClass(self, node): 142 if not used_by_unit(node): 143 return compiler.ast.Stmt([]) 144 145 self.units.append(node.unit) 146 try: 147 # Incorporate class body code in the main function. 148 149 if self.in_main: 150 return self.dispatch(node.code) 151 else: 152 return self._visitClassDefinition(node) 153 154 finally: 155 self.units.pop() 156 157 def _visitClassDefinition(self, node): 158 cls = node.unit 159 160 # instattrs(name, ...) 161 # clsattrs(name, ...) 162 163 instattrs = cls.instance_attribute_names() and [ 164 compiler.ast.CallFunc( 165 special_name("instattrs"), 166 [special_name(attr.name) for attr in cls.instance_attributes_as_list()] 167 ) 168 ] or [] 169 170 clsattrs = cls.class_attribute_names() and [ 171 compiler.ast.CallFunc( 172 special_name("clsattrs"), 173 [special_name(attr.name) for attr in cls.attributes_as_list()] 174 ) 175 ] or [] 176 177 # inherited(superclass, name, ...) 178 # ... 179 180 attrs_by_cls = {} 181 for attrname, attr in cls.all_class_attributes().items(): 182 supercls = attr.parent 183 if supercls is cls: 184 continue 185 if not attrs_by_cls.has_key(supercls): 186 attrs_by_cls[supercls] = [] 187 attrs_by_cls[supercls].append(attrname) 188 189 inherited = [] 190 191 for supercls, attrnames in attrs_by_cls.items(): 192 inherited.append( 193 compiler.ast.CallFunc( 194 special_name("inherited"), 195 [quoted_ref(supercls)] + [special_name(name) for name in attrnames] 196 )) 197 198 # descendants(name, ...) 199 200 descendants = cls.all_descendants() and [ 201 compiler.ast.CallFunc( 202 special_name("descendants"), 203 [special_name(name) for name in cls.all_descendants().keys()] 204 ) 205 ] or [] 206 207 # Process all the definitions defined inside the class. 208 209 definitions = self.process_definitions(node) 210 211 return compiler.ast.Class(node.name, [], node.doc, 212 compiler.ast.Stmt(instattrs + clsattrs + inherited + descendants + definitions) 213 ) 214 215 visitContinue = NOP 216 217 def visitDiscard(self, node): 218 return compiler.ast.Discard(self.dispatch(node.expr)) 219 220 def visitFor(self, node): 221 222 """ 223 Convert from... 224 225 for <assign> in <list>: 226 <body> 227 [ else: 228 <else_> ] 229 230 ...to... 231 232 _it = iter(<list>) 233 while True: 234 try: 235 <assign> = _it.next() 236 except StopIteration: 237 [ <else_> ] 238 break 239 else: 240 <body> 241 """ 242 243 unit = self.get_unit() 244 temp = quoted_name(unit.temp_usage) 245 unit.temp_usage += 1 246 247 else_nodes = node.else_ and self.dispatch(node.else_).nodes or [] 248 249 return compiler.ast.Stmt([ 250 # storetemp(_it, __builtins__.iter(<list>)) 251 compiler.ast.CallFunc(special_name("storetemp"), [ 252 temp, 253 compiler.ast.CallFunc( 254 module_attribute("__builtins__", "iter"), 255 [self.dispatch(node.list)] 256 ) 257 ]), 258 # while True: ... 259 compiler.ast.While( 260 special_name("True"), 261 # try: ... 262 compiler.ast.TryExcept( 263 compiler.ast.Stmt([ 264 # <assign> = ... 265 self.dispatch(node.assign, 266 # _it.next() 267 compiler.ast.CallFunc( 268 compiler.ast.CallFunc(special_name("loadattrindex"), [ 269 compiler.ast.CallFunc(special_name("loadtemp"), [temp]), 270 special_name("next") 271 ]), 272 [] 273 ) 274 ) 275 ]), 276 # except StopIteration: ... 277 [(special_name("StopIteration"), None, compiler.ast.Stmt(else_nodes + [compiler.ast.Break()]))], 278 # else: ... 279 self.dispatch(node.body) 280 ), 281 None 282 ) 283 ]) 284 285 def visitFrom(self, node): 286 287 # Generate __main__ function calls for each step in the imported module 288 # hierarchy. 289 290 statements = [] 291 292 for modname in self.module.get_module_paths(node.modname): 293 statements.append( 294 compiler.ast.CallFunc(special_name("%s.__main__" % modname ), []) 295 ) 296 297 for name, alias in node.names: 298 statements.append( 299 compiler.ast.CallFunc( 300 special_name("storelocal"), 301 [special_name(alias or name), 302 compiler.ast.CallFunc( 303 special_name("loadattr"), 304 [special_name(node.modname), special_name(name)] 305 ) 306 ]) 307 ) 308 309 return compiler.ast.Stmt(statements) 310 311 def visitFunction(self, node): 312 if not used_by_unit(node): 313 return compiler.ast.Stmt([]) 314 315 self.units.append(node.unit) 316 317 try: 318 if self.in_main: 319 320 # Generate rebindings of functions. 321 322 fn = node.unit 323 if fn.name == fn.original_name: 324 return compiler.ast.Stmt([]) 325 else: 326 return compiler.ast.CallFunc( 327 special_name("storeattr"), 328 [quoted_ref(fn.parent), special_name(fn.original_name), 329 quoted_ref(fn)] 330 ) 331 else: 332 return self._visitFunctionDefinition(node) 333 finally: 334 self.units.pop() 335 336 def _visitFunctionDefinition(self, node): 337 fn = node.unit 338 339 # localnames(name, ...) 340 # globalnames(name, ...) 341 342 localnames = fn.all_locals() and [ 343 compiler.ast.CallFunc( 344 special_name("localnames"), 345 [special_name(name) for name in fn.all_locals().keys()] 346 ) 347 ] or [] 348 349 globalnames = fn.globals and [ 350 compiler.ast.CallFunc( 351 special_name("globalnames"), 352 [special_name(name) for name in fn.globals] 353 ) 354 ] or [] 355 356 defaults = [self.dispatch(n) for n in node.defaults] 357 358 # NOTE: Should generate guards for attribute usage operations. 359 360 code = self.dispatch(node.code) 361 362 return compiler.ast.Function(node.decorators, node.name, node.argnames, defaults, node.flags, node.doc, 363 compiler.ast.Stmt(localnames + globalnames + code.nodes)) 364 365 visitGlobal = NOP 366 367 def visitIf(self, node): 368 return compiler.ast.If( 369 [(self.dispatch(compare), self.dispatch(stmt)) for (compare, stmt) in node.tests], 370 node.else_ and self.dispatch(node.else_) 371 ) 372 373 def visitImport(self, node): 374 375 # Generate __main__ function calls for each step in the imported module 376 # hierarchy. 377 378 statements = [] 379 380 for name, alias in node.names: 381 for modname in self.module.get_module_paths(name): 382 statements.append( 383 compiler.ast.CallFunc(compiler.ast.Getattr(modname, "__main__"), []) 384 ) 385 386 statements.append( 387 compiler.ast.CallFunc( 388 special_name("storelocal"), 389 [special_name(alias or name.split(".")[0]), 390 compiler.ast.CallFunc( 391 special_name("static"), 392 [special_name(name)] 393 ) 394 ]) 395 ) 396 397 return compiler.ast.Stmt(statements) 398 399 def visitPass(self, node): 400 if not isinstance(self.get_unit(), Class): 401 return compiler.ast.Pass() 402 else: 403 return compiler.ast.Stmt([]) 404 405 def visitPrint(self, node): 406 return compiler.ast.Print( 407 [self.dispatch(n) for n in node.nodes], 408 node.dest and self.dispatch(node.dest) 409 ) 410 411 def visitPrintnl(self, node): 412 return compiler.ast.Print( 413 [self.dispatch(n) for n in node.nodes], 414 node.dest and self.dispatch(node.dest) 415 ) 416 417 def visitRaise(self, node): 418 return compiler.ast.Raise( 419 node.expr1 and self.dispatch(node.expr1), 420 node.expr2 and self.dispatch(node.expr2), 421 node.expr3 and self.dispatch(node.expr3) 422 ) 423 424 def visitReturn(self, node): 425 return compiler.ast.Return(self.dispatch(node.value)) 426 427 def visitStmt(self, node): 428 return compiler.ast.Stmt([self.dispatch(n) for n in node.nodes]) 429 430 def visitTryExcept(self, node): 431 # NOTE: Need to dispatch to the assignment with the exception. 432 return compiler.ast.TryExcept( 433 self.dispatch(node.body), 434 [(spec and self.dispatch(spec), assign and self.dispatch(assign), self.dispatch(statement)) 435 for spec, assign, statement in node.handlers], 436 node.else_ and self.dispatch(node.else_) 437 ) 438 439 def visitTryFinally(self, node): 440 return compiler.ast.TryFinally( 441 self.dispatch(node.body), 442 self.dispatch(node.final) 443 ) 444 445 def visitWhile(self, node): 446 return compiler.ast.While( 447 self.dispatch(node.test), 448 self.dispatch(node.body), 449 node.else_ and self.dispatch(node.else_) 450 ) 451 452 def visitYield(self, node): 453 return compiler.ast.Yield(self.dispatch(node.value)) 454 455 # Expression-related helper methods. 456 457 def _visitBitBinary(self, node): 458 op_name = operator_functions[node.__class__.__name__] 459 last = self.dispatch(node.nodes[0]) 460 461 for n in node.nodes[1:]: 462 last = compiler.ast.CallFunc( 463 module_attribute("operator", op_name), 464 [last, self.dispatch(n)] 465 ) 466 467 return last 468 469 def _visitBinary(self, node): 470 op_name = operator_functions[node.__class__.__name__] 471 472 return compiler.ast.CallFunc( 473 module_attribute("operator", op_name), 474 [self.dispatch(node.left), self.dispatch(node.right)] 475 ) 476 477 def _visitUnary(self, node): 478 op_name = operator_functions[node.__class__.__name__] 479 480 return compiler.ast.CallFunc( 481 module_attribute("operator", op_name), 482 [self.dispatch(node.expr)] 483 ) 484 485 def _generateValue(self, value): 486 487 # Literal constants. 488 489 if isinstance(value, Const): 490 return compiler.ast.Const(value.get_value()) 491 492 # Other constant structures. 493 494 if isinstance(value, Constant): 495 return quoted_ref(value) 496 497 return None 498 499 def _visitAttr(self, node, expr=None): 500 unit = self.get_unit() 501 502 # Choose the appropriate special functions. 503 504 (opattrcontext, opattrcontextcond, opattr, 505 opattrindex, opattrindexcontextcond) = expr and assattr_functions or getattr_functions 506 507 accessor = self.dispatch(node.expr) 508 509 # Generate already-deduced accesses. 510 511 if node._access_type == "constant": 512 return self._generateValue(node._value_deduced) 513 514 # Generate accesses via static objects and instances. 515 516 if node._attr_deduced: 517 if node._set_context == "set": 518 op = opattrcontext 519 elif node._set_context == "cond": 520 op = opattrcontextcond 521 else: 522 op = opattr 523 524 # Handle unsupported operations. 525 526 if not op: 527 raise TranslateError("Storing of class attribute %r via self not permitted." % node.attrname) 528 529 # Define the arguments: accessor, attribute name and optional value. 530 531 args = [ 532 node._access_type == "static" and \ 533 self._generateValue(node._attr_deduced.parent) or accessor, 534 special_name(node.attrname) 535 ] 536 537 if expr: 538 args.append(expr) 539 540 # Append any context to be set. 541 542 if node._set_context and args[0] is not accessor: 543 args.append(accessor) 544 545 return compiler.ast.CallFunc(special_name(op), args) 546 547 # Positioned accesses are normal accesses via instances. 548 549 if node._access_type == "positioned": 550 args = [accessor, special_name(node.attrname)] 551 if expr: 552 args.append(expr) 553 return compiler.ast.CallFunc(special_name(opattr), args) 554 555 # With no usable deductions, generate a table-based access. 556 557 args = [accessor, special_name(node.attrname)] 558 if expr: 559 args.append(expr) 560 access = compiler.ast.CallFunc(special_name(opattrindexcontextcond), args) 561 562 # class.__class__ => __builtins__.type 563 564 if node.attrname == "__class__": 565 566 # storetemp(n, <accessor>) 567 # isclass(n) and __builtins__.type or <access> 568 569 temp = quoted_name(unit.temp_usage) 570 unit.temp_usage += 1 571 572 return compiler.ast.Stmt([ 573 compiler.ast.CallFunc(special_name("storetemp"), [temp, access]), 574 compiler.ast.Or([ 575 compiler.ast.And([ 576 compiler.ast.CallFunc( 577 special_name("isclass"), 578 [compiler.ast.CallFunc(special_name("loadtemp"), [temp])] 579 ), 580 module_attribute("__builtins__", "type") 581 ]), 582 access 583 ]) 584 ]) 585 586 # General accesses. 587 588 else: 589 return access 590 591 # Expressions. 592 593 def visitAdd(self, node): 594 return self._visitBinary(node) 595 596 def visitAnd(self, node): 597 return compiler.ast.And([self.dispatch(n) for n in node.nodes]) 598 599 def visitAssAttr(self, node, expr=None): 600 601 # Handle deletion. 602 603 if compiler.ast.is_deletion(node): 604 return compiler.ast.Stmt([]) 605 606 return self._visitAttr(node, expr) 607 608 def visitAssList(self, node, expr=None): 609 610 # Handle deletion. 611 612 if compiler.ast.is_deletion(compiler.ast.flatten_assignment(node)): 613 return compiler.ast.Stmt([]) 614 615 return compiler.ast.Stmt([ 616 self.dispatch(n, compiler.ast.CallFunc( 617 module_attribute("operator", "getitem"), 618 [expr, i] 619 )) 620 for (i, n) in enumerate(node.nodes) 621 ]) 622 623 def visitAssName(self, node, expr=None): 624 625 # Handle deletion. 626 627 if compiler.ast.is_deletion(node): 628 return compiler.ast.Stmt([]) 629 630 unit = self.get_unit() 631 632 # Generate appropriate name access operation. 633 # NOTE: Should generate guards for attribute usage operations. 634 635 scope = getattr(node, "_scope", None) 636 if not scope: 637 attr, scope, from_name = self.get_unit()._get_with_scope(node.name) 638 639 if scope == "constant": 640 return node 641 elif scope == "local": 642 643 # Function locals are stored using a function. 644 645 if isinstance(unit, Function): 646 return compiler.ast.CallFunc( 647 special_name("storelocal"), 648 [special_name(node.name), expr] 649 ) 650 651 # Class locals are class attribute references. 652 653 elif isinstance(unit, Class): 654 return compiler.ast.CallFunc( 655 special_name("storeattrcontext"), 656 [quoted_ref(unit), special_name(node.name), expr] 657 ) 658 659 # Module locals are module attribute references. 660 661 elif isinstance(unit, Module): 662 return compiler.ast.CallFunc( 663 special_name("storeattr"), 664 [quoted_ref(unit), special_name(node.name), expr] 665 ) 666 else: 667 raise TranslateError("Program unit has no local %r." % name) 668 669 elif scope == "global": 670 671 # Globals are references to module attributes. 672 673 return compiler.ast.CallFunc( 674 special_name("storeattr"), 675 [quoted_ref(self.get_module()), special_name(node.name), expr] 676 ) 677 678 elif scope == "builtin": 679 680 # Builtins are accessed via the __builtins__ module. 681 682 return compiler.ast.CallFunc( 683 special_name("storeattr"), 684 [special_name("__builtins__"), special_name(node.name), expr] 685 ) 686 687 else: 688 # NOTE: This may happen because a class attribute is optimised away. 689 return compiler.ast.CallFunc( 690 special_name("storeunknown"), 691 [special_name(node.name), expr] 692 ) 693 694 visitAssTuple = visitAssList 695 696 def visitBitand(self, node): 697 self._visitBitBinary(node) 698 699 def visitBitor(self, node): 700 self._visitBitBinary(node) 701 702 def visitBitxor(self, node): 703 self._visitBitBinary(node) 704 705 def visitCallFunc(self, node): 706 return compiler.ast.CallFunc( 707 special_name("apply"), 708 [self.dispatch(node.node)] + [self.dispatch(arg) for arg in node.args], 709 node.star_args and self.dispatch(node.star_args), 710 node.dstar_args and self.dispatch(node.dstar_args) 711 ) 712 713 def visitCompare(self, node): 714 nodes = [] 715 left = node.expr 716 for op_name, right in node.ops: 717 if op_name == "is": 718 nodes.append( 719 compiler.ast.CallFunc( 720 special_name("__is__"), 721 [self.dispatch(left), self.dispatch(right)] 722 ) 723 ) 724 elif op_name == "is not": 725 nodes.append( 726 compiler.ast.CallFunc( 727 special_name("__is_not__"), 728 [self.dispatch(left), self.dispatch(right)] 729 ) 730 ) 731 else: 732 nodes.append( 733 compiler.ast.CallFunc( 734 module_attribute("operator", operator_functions.get(op_name)), 735 [self.dispatch(left), self.dispatch(right)] 736 ) 737 ) 738 left = right 739 return compiler.ast.And(nodes) 740 741 visitConst = NOP 742 743 def visitDict(self, node): 744 return compiler.ast.Dict([(self.dispatch(key), self.dispatch(value)) for (key, value) in node.items]) 745 746 def visitDiv(self, node): 747 return self._visitBinary(node) 748 749 def visitFloorDiv(self, node): 750 return self._visitBinary(node) 751 752 def visitGetattr(self, node, expr=None): 753 return self._visitAttr(node, expr) 754 755 def visitGenExpr(self, node): 756 return compiler.ast.GenExpr(self.dispatch(node.code)) 757 758 def visitGenExprFor(self, node): 759 expr = self.dispatch(node.iter) 760 return compiler.ast.GenExprFor( 761 self.dispatch(node.assign, expr), # NOTE: Needs to dispatch to AssName/AssTuple/AssList with an expression. 762 expr, 763 [self.dispatch(n) for n in node.ifs] 764 ) 765 766 def visitGenExprIf(self, node): 767 return compiler.ast.GenExprIf(self.dispatch(node.test)) 768 769 def visitGenExprInner(self, node): 770 return compiler.ast.GenExprInner( 771 self.dispatch(node.expr), 772 [self.dispatch(n) for n in node.quals] 773 ) 774 775 def visitIfExp(self, node): 776 return compiler.ast.IfExp( 777 self.dispatch(node.then), 778 self.dispatch(node.test), 779 self.dispatch(node.else_) 780 ) 781 782 def visitInvert(self, node): 783 return self._visitUnary(node) 784 785 def visitKeyword(self, node): 786 return compiler.ast.Keyword( 787 node.name, 788 self.dispatch(node.expr) 789 ) 790 791 def visitLambda(self, node): 792 self.units.append(node.unit) 793 794 try: 795 return compiler.ast.Lambda( 796 node.argnames, 797 [self.dispatch(n) for n in node.defaults], 798 node.flags, 799 self.dispatch(node.code) 800 ) 801 finally: 802 self.units.pop() 803 804 def visitLeftShift(self, node): 805 return self._visitBinary(node) 806 807 def visitList(self, node, expr=None): 808 if expr: 809 return self.visitAssList(node, expr) 810 return compiler.ast.List([self.dispatch(n) for n in node.nodes]) 811 812 def visitListComp(self, node): 813 814 """ 815 Convert from... 816 817 [<expr> for <assign> in <list> [ for <assign> in <list> ]... [ if <test> ]... ] 818 819 ...to... 820 821 _out = [] 822 ... 823 """ 824 825 unit = self.get_unit() 826 temp = quoted_name(unit.temp_usage) 827 unit.temp_usage += 1 828 829 return compiler.ast.Stmt([ 830 # storetemp(_out, __builtins__.list()) 831 compiler.ast.CallFunc(special_name("storetemp"), [ 832 temp, 833 compiler.ast.CallFunc( 834 module_attribute("__builtins__", "list"), 835 [] 836 ) 837 ]), 838 # ... 839 self.dispatch(node.quals[0], temp, node.expr, node.quals[1:]) 840 ]) 841 842 def visitListCompFor(self, node, out_temp, expr, quals): 843 844 """ 845 Convert from... 846 847 [<expr> for <assign> in <list> ...] 848 849 ...to... 850 851 _it = iter(<list>) 852 while True: 853 try: 854 <assign> = _it.next() 855 except StopIteration: 856 break 857 else: 858 ... 859 _out.append(<expr>) 860 """ 861 862 unit = self.get_unit() 863 temp = quoted_name(unit.temp_usage) 864 unit.temp_usage += 1 865 866 # Either generate more "for" or "if" constructs. 867 868 if node.ifs or quals: 869 nodes = node.ifs + quals 870 body = self.dispatch(nodes[0], out_temp, expr, nodes[1:]) 871 872 # Or generate the append statement. 873 874 else: 875 body = self._visitListCompExpr(out_temp, expr) 876 877 # Wrap the above body in the loop construct. 878 879 return compiler.ast.Stmt([ 880 # storetemp(_it, __builtins__.iter(<list>)) 881 compiler.ast.CallFunc(special_name("storetemp"), [ 882 temp, 883 compiler.ast.CallFunc( 884 module_attribute("__builtins__", "iter"), 885 [self.dispatch(node.list)] 886 ) 887 ]), 888 # while True: ... 889 compiler.ast.While( 890 special_name("True"), 891 # try: ... 892 compiler.ast.TryExcept( 893 compiler.ast.Stmt([ 894 # <assign> = ... 895 self.dispatch(node.assign, 896 # _it.next() 897 compiler.ast.CallFunc( 898 compiler.ast.CallFunc(special_name("loadattrindex"), [ 899 compiler.ast.CallFunc(special_name("loadtemp"), [temp]), 900 special_name("next") 901 ]), 902 [] 903 ) 904 ) 905 ]), 906 # except StopIteration: ... 907 [(special_name("StopIteration"), None, compiler.ast.Stmt([compiler.ast.Break()]))], 908 # else: ... 909 body 910 ), 911 None 912 ) 913 ]) 914 915 def visitListCompIf(self, node, out_temp, expr, quals): 916 917 # Either generate more "for" or "if" constructs. 918 919 if quals: 920 body = self.dispatch(quals[0], out_temp, expr, quals[1:]) 921 922 # Or generate the append statement. 923 924 else: 925 body = self._visitListCompExpr(out_temp, expr) 926 927 return compiler.ast.If( 928 [(self.dispatch(node.test), body)], 929 None 930 ) 931 932 def _visitListCompExpr(self, out_temp, expr): 933 934 "To the 'out_temp' object, append the result of 'expr'." 935 936 return compiler.ast.Stmt([ 937 # _out.append(<expr>) 938 compiler.ast.CallFunc( 939 compiler.ast.CallFunc(special_name("loadattrindex"), [ 940 compiler.ast.CallFunc(special_name("loadtemp"), [out_temp]), 941 special_name("append") 942 ]), 943 [self.dispatch(expr)] 944 ) 945 ]) 946 947 def visitMod(self, node): 948 return self._visitBinary(node) 949 950 def visitMul(self, node): 951 return self._visitBinary(node) 952 953 def visitName(self, node, expr=None): 954 if expr: 955 return self.visitAssName(node, expr) 956 957 unit = self.get_unit() 958 attr = node._attr 959 scope = node._scope 960 961 # Generate appropriate name access operation. 962 963 if scope == "constant": 964 return node 965 966 # Function locals are referenced normally. 967 968 elif scope == "local" and isinstance(unit, Function): 969 return node 970 971 # Other attributes should already be resolved. 972 973 elif attr is not None and not isinstance(attr, Instance): 974 if attr.is_constant(): 975 return constant_attribute(quoted_ref(attr.parent), node.name) 976 else: 977 return compiler.ast.CallFunc( 978 special_name("loadattr"), 979 [quoted_ref(attr.parent), special_name(node.name)] 980 ) 981 982 # Function globals are referenced via the module. 983 984 elif scope == "global": 985 return compiler.ast.CallFunc( 986 special_name("loadattr"), 987 [quoted_ref(self.get_module()), special_name(node.name)] 988 ) 989 990 # NOTE: Unknown attributes may arise because a class attribute has been 991 # NOTE: optimised away. 992 993 else: 994 return compiler.ast.CallFunc( 995 special_name("loadunknown"), 996 [special_name(node.name)] 997 ) 998 999 def visitNot(self, node): 1000 return compiler.ast.Not(self.dispatch(node.expr)) 1001 1002 def visitOr(self, node): 1003 return compiler.ast.Or([self.dispatch(n) for n in node.nodes]) 1004 1005 def visitPower(self, node): 1006 return self._visitBinary(node) 1007 1008 def visitRightShift(self, node): 1009 return self._visitBinary(node) 1010 1011 def visitSlice(self, node, expr=None): 1012 return compiler.ast.CallFunc( 1013 module_attribute("operator", expr and "setslice" or "getslice"), 1014 [self.dispatch(node.expr), node.lower and self.dispatch(node.lower), node.upper and self.dispatch(node.upper)] 1015 + (expr and [expr] or []) 1016 ) 1017 1018 def visitSliceobj(self, node): 1019 return compiler.ast.Sliceobj([self.dispatch(n) for n in node.nodes]) 1020 1021 def visitSub(self, node): 1022 return self._visitBinary(node) 1023 1024 def visitSubscript(self, node, expr=None): 1025 return compiler.ast.CallFunc( 1026 module_attribute("operator", expr and "setitem" or "getitem"), 1027 [self.dispatch(node.expr), compiler.ast.Tuple([self.dispatch(sub) for sub in node.subs])] 1028 + (expr and [expr] or []) 1029 ) 1030 1031 def visitTuple(self, node, expr=None): 1032 if expr: 1033 return self.visitAssTuple(node, expr) 1034 return compiler.ast.Tuple([self.dispatch(n) for n in node.nodes]) 1035 1036 def visitUnaryAdd(self, node): 1037 return self._visitUnary(node) 1038 1039 def visitUnarySub(self, node): 1040 return self._visitUnary(node) 1041 1042 # Convenience functions. 1043 1044 def convert(module, program, filename): 1045 stream = open(filename, "wb") 1046 try: 1047 source = ConvertedSource(module, program) 1048 source.to_stream(stream) 1049 finally: 1050 stream.close() 1051 1052 def translate(program, directory): 1053 if not exists(directory): 1054 os.mkdir(directory) 1055 1056 # NOTE: Add constants here. 1057 1058 for module in program.get_importer().get_modules(): 1059 convert(module, program, join(directory, "%s%spy" % (module.full_name(), extsep))) 1060 1061 # vim: tabstop=4 expandtab shiftwidth=4