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