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