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