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