1 #!/usr/bin/env python 2 3 """ 4 Translate the AST of a Python program into a more interpretable representation. 5 6 Copyright (C) 2007, 2008, 2009 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.opt import Optimiser 23 from micropython.common import * 24 from micropython.data import * 25 from micropython.rsvp import * 26 from micropython.trans import Helper 27 import compiler.ast 28 from compiler.visitor import ASTVisitor 29 30 # Program visitors. 31 32 class Translation(ASTVisitor, Helper): 33 34 "A translated module." 35 36 # Attribute access instructions, for use with the appropriate handlers. 37 38 attribute_load_instructions = ( 39 LoadAddress, LoadAddressContext, LoadAddressContextCond, 40 LoadAttr, LoadAttrIndex, LoadAttrIndexContext, LoadAttrIndexContextCond 41 ) 42 attribute_store_instructions = ( 43 None, None, None, 44 StoreAttr, StoreAttrIndex, None, None 45 ) 46 47 # Name access instructions, for use with the appropriate handlers. 48 49 name_load_instructions = (LoadName, LoadAddress, None) 50 name_store_instructions = (StoreName, StoreAddress, StoreAddressContext) 51 52 def __init__(self, module, program): 53 54 """ 55 Initialise the translation with an inspected 'module' and the 'program' 56 container. 57 """ 58 59 ASTVisitor.__init__(self) 60 self.visitor = self 61 self.module = module 62 63 # Global program dependencies. 64 65 self.program = program 66 self.objtable = self.program.get_object_table() 67 self.paramtable = self.program.get_parameter_table() 68 self.importer = self.program.get_importer() 69 self.builtins = self.importer.modules.get("__builtins__") 70 71 # Optimisation. 72 73 self.optimiser = Optimiser(self, program.optimisations) 74 75 # The current unit being translated. 76 77 self.unit = None 78 79 # The temporary storage used by the current assignment expression. 80 81 self.expr_temp = [] 82 83 # Wiring within the code. 84 85 self.labels = {} 86 self.label_number = 0 87 self.loop_blocks = [] 88 self.exception_blocks = [] 89 90 self.reset() 91 92 def __repr__(self): 93 return "Translation(%r)" % self.module 94 95 def reset(self): 96 97 "Reset the state of the translator." 98 99 # The code itself. This is limited to the code for a particular block 100 # being processed. 101 102 self.blocks = [] 103 104 # Information about temporary values. 105 106 self.temp_positions = set() 107 self.max_temp_position = -1 108 109 # Information about instructions which construct frames. 110 111 self.frame_makers = [] 112 113 # Optimiser state must be reset for each unit. 114 115 self.optimiser.reset() 116 117 def get_module_code(self, final=0): 118 119 """ 120 Return the top-level module code including finalising code if 'final' is 121 set to a true value. 122 """ 123 124 self.unit = self.module 125 self.reset() 126 127 block = self.new_block() 128 self.set_block(block) 129 130 if self.module.module is not None: 131 self.dispatch(self.module.module) 132 133 # Finish off the translated program if appropriate. 134 135 if final: 136 self.new_op(Return()) 137 138 self.unit.temp_usage = self.max_temp_position + 1 139 self.unit.blocks = self.blocks 140 return self.blocks 141 142 def get_code(self, unit): 143 144 "Return the code for the given 'unit'." 145 146 self.unit = unit 147 self.reset() 148 149 block = self.new_block() 150 self.set_block(block) 151 152 if unit.astnode is not None: 153 self.dispatch(unit.astnode) 154 155 self.unit.temp_usage = self.max_temp_position + 2 # include space for instantiators to expand backwards 156 self.unit.blocks = self.blocks 157 return self.blocks 158 159 def get_instantiator_code(self, cls): 160 161 "Return the code for the given class 'cls'." 162 163 self.unit = cls.get_instantiator() 164 self.reset() 165 166 block = self.new_block() 167 self.set_block(block) 168 169 init_method = cls.get_init_method() 170 171 # Convert this frame back to being an invocation frame. 172 173 self.new_op(RecoverFrame()) 174 175 # Fix the current frame to include a new storage slot at the beginning. 176 177 self.new_op(AdjustFrame(-1)) 178 179 # Make an object. 180 181 self.make_object(cls, len(cls.instance_attributes())) 182 self.new_op(StoreFrame(0)) 183 184 # Invoke the appropriate initialiser. 185 186 self.new_op(LoadFunction(init_method)) 187 self.new_op(LoadCallable()) 188 self.new_op(JumpWithFrame()) 189 190 # Store the object as the result. 191 192 self.new_op(LoadName(init_method.all_locals()["self"])) # load the context in the invocation frame 193 self.new_op(StoreResult()) 194 195 # Fix the current frame to release the storage slot at the beginning. 196 197 self.new_op(AdjustFrame(1)) 198 self.new_op(Return()) 199 200 self.unit.blocks = self.blocks 201 return self.blocks 202 203 # Visitor methods. 204 205 def default(self, node, *args): 206 raise TranslateError(self.module.full_name(), node, "Node class %r is not supported." % node.__class__) 207 208 def dispatch(self, node, *args): 209 return ASTVisitor.dispatch(self, node, *args) 210 211 # Concrete visitor methods. 212 213 # Binary operators. 214 215 visitAdd = Helper._visitBinary 216 visitBitand = Helper._visitBinary 217 visitBitor = Helper._visitBinary 218 visitBitxor = Helper._visitBinary 219 visitDiv = Helper._visitBinary 220 visitFloorDiv = Helper._visitBinary 221 visitLeftShift = Helper._visitBinary 222 visitMod = Helper._visitBinary 223 visitMul = Helper._visitBinary 224 visitPower = Helper._visitBinary 225 visitRightShift = Helper._visitBinary 226 visitSub = Helper._visitBinary 227 228 # Unary operators. 229 230 visitInvert = Helper._visitUnary 231 visitUnaryAdd = Helper._visitUnary 232 visitUnarySub = Helper._visitUnary 233 234 # Logical operators. 235 236 def visitAnd(self, node): 237 end_block = self.new_block() 238 temp_pos = self.reserve_temp() 239 temp = LoadTemp(temp_pos) 240 241 for n in node.nodes[:-1]: 242 self.dispatch(n) 243 self.new_op(StoreTemp(temp_pos)) 244 245 self._generateTestBoolean(n, temp) 246 self.new_op(JumpIfFalse(end_block)) 247 248 self.dispatch(node.nodes[-1]) 249 self.new_op(StoreTemp(temp_pos)) 250 251 self.set_block(end_block) 252 253 self.new_op(temp) 254 self.discard_temp(temp) 255 256 def visitNot(self, node): 257 self.dispatch(node.expr) 258 259 temp = self.optimiser.optimise_temp_storage() 260 self._generateTestBoolean(node.expr, temp) 261 self.discard_temp(temp) 262 263 self.new_op(InvertBoolean()) 264 self._generateLoadBoolean(node) 265 266 def visitOr(self, node): 267 end_block = self.new_block() 268 temp_pos = self.reserve_temp() 269 temp = LoadTemp(temp_pos) 270 271 for n in node.nodes[:-1]: 272 self.dispatch(n) 273 self.new_op(StoreTemp(temp_pos)) 274 275 self._generateTestBoolean(n, temp) 276 self.new_op(JumpIfTrue(end_block)) 277 278 self.dispatch(node.nodes[-1]) 279 self.new_op(StoreTemp(temp_pos)) 280 281 self.set_block(end_block) 282 283 self.new_op(temp) 284 self.discard_temp(temp) 285 286 # Comparisons. 287 288 def visitCompare(self, node): 289 290 """ 291 _t1 = node.expr 292 _t1 op1 _t2 and _t2 op2 _t3 and ... 293 """ 294 295 end_block = self.new_block() 296 297 self.dispatch(node.expr) 298 temp2 = self.optimiser.optimise_temp_storage() 299 300 # NOTE: Replicated by some code in micropython.inspect.visitCompare. 301 302 last_op = node.ops[-1] 303 304 for op in node.ops: 305 op_name, next_node = op 306 methods = comparison_methods[op_name] 307 308 # Propagate the arguments as we traverse the construct. 309 310 temp1 = temp2 311 self.dispatch(next_node) 312 temp2 = self.optimiser.optimise_temp_storage() 313 314 # Use the appropriate mechanism, setting the boolean status for the 315 # comparison. 316 317 if methods is not None: 318 left_method, right_method = methods 319 320 # Generate method call using evaluated argument and next node. 321 322 temp_result = self._generateBinary(node, temp1, temp2, left_method, right_method) 323 self.new_op(temp_result) 324 self._generateTestBoolean(node, temp_result) 325 self.discard_temp(temp_result) 326 327 else: 328 # Deal with the special operators. 329 330 if op_name.startswith("is"): 331 self.new_op(temp1) 332 self.record_value() 333 self.new_op(temp2) 334 self.new_op(TestIdentity()) 335 self.set_source() 336 self.discard_value() 337 338 elif op_name.endswith("in"): 339 self.new_op(temp2) 340 341 # Get method on temp2. 342 343 self._generateAttr(node, "__contains__", self.attribute_load_instructions) 344 temp_method = self.optimiser.optimise_temp_storage() 345 346 # Add arguments. 347 # NOTE: No support for defaults. 348 349 self._startCallFunc() 350 self.new_op(temp2) 351 self.new_op(StoreFrame(0)) 352 self.new_op(temp1) 353 self.new_op(StoreFrame(1)) 354 self._endCallFuncArgs(2) 355 self._doCallFunc(temp_method) 356 self._endCallFunc(temp_method) 357 358 temp_result = self.get_temp() 359 self._generateTestBoolean(node, temp_result) 360 self.discard_temp(temp_result) 361 362 if op_name.find("not") != -1: 363 self.new_op(InvertBoolean()) 364 365 # Test the result and jump to the end block if false. 366 367 if op is not last_op: 368 self.new_op(JumpIfFalse(end_block)) 369 370 # Compilation duties... 371 372 self.discard_temp(temp1) 373 374 self.discard_temp(temp2) 375 376 # With the status set above, produce a boolean result. 377 378 self.set_block(end_block) 379 380 # Yield the appropriate value. 381 382 self._generateLoadBoolean(node) 383 384 # Expressions. 385 386 def visitBackquote(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Backquote") 387 388 def visitCallFunc(self, node): 389 390 """ 391 Evaluate positional arguments, evaluate and store keyword arguments in 392 the correct location, then invoke the function. 393 """ 394 395 # Mark the frame, evaluate the target, generate the call. 396 397 self._startCallFunc() 398 self.dispatch(node.node) 399 temp, target = self._generateCallFunc(node.args, node) 400 self._doCallFunc(temp, target) 401 self._endCallFunc(temp, target) 402 403 def visitConst(self, node): 404 const = self.importer.get_constant(node.value) 405 self.new_op(LoadConst(const)) 406 407 def visitDict(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Dict") 408 409 def visitEllipsis(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Ellipsis") 410 411 def visitExec(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Exec") 412 413 def visitExpression(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Expression") 414 415 def visitGenExpr(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "GenExpr") 416 417 def visitGenExprFor(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "GenExprFor") 418 419 def visitGenExprIf(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "GenExprIf") 420 421 def visitGenExprInner(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "GenExprInner") 422 423 def visitGetattr(self, node): 424 self._visitAttr(node, self.attribute_load_instructions) 425 426 def visitList(self, node): 427 self._generateSequence("list", node) 428 429 def visitListComp(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "ListComp") 430 431 def visitListCompFor(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "ListCompFor") 432 433 def visitListCompIf(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "ListCompIf") 434 435 def visitName(self, node): 436 if self.importer.predefined_constants.has_key(node.name): 437 const = self.importer.get_predefined_constant(node.name) 438 self.new_op(LoadConst(const)) 439 else: 440 self._visitName(node, self.name_load_instructions) 441 442 def visitSlice(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Slice") 443 444 def visitSubscript(self, node): 445 self.dispatch(node.expr) 446 self._startCallFunc() 447 self._generateAttr(node, "__getitem__", self.attribute_load_instructions) 448 temp, target = self._generateCallFunc(node.subs, node) 449 self._doCallFunc(temp, target) 450 self._endCallFunc(temp, target) 451 452 def visitTuple(self, node): 453 self._generateSequence("tuple", node) 454 455 # Definitions. 456 457 def visitAssign(self, node): 458 459 """ 460 Evaluate the expression from the given 'node' and assign it to the 461 associated recipients. 462 """ 463 464 self.dispatch(node.expr) 465 466 # Record the value and then dispatch to the assignment targets. 467 468 self.record_value(self.has_immediate_usage(node.nodes)) 469 470 for n in node.nodes: 471 self.dispatch(n) 472 473 self.discard_value() 474 475 def visitAssAttr(self, node): 476 477 "Assign the assignment expression to the recipient 'node'." 478 479 self._visitAttr(node, self.attribute_store_instructions) 480 self.set_source() 481 482 def visitAssList(self, node): 483 484 """ 485 Assign items from the assignment expression to each of the recipients 486 found within the given 'node'. 487 """ 488 489 for i, n in enumerate(node.nodes): 490 self._startCallFunc() 491 self.new_op(self.expr_temp[-1]) 492 self._generateAttr(node, "__getitem__", self.attribute_load_instructions) 493 temp, target = self._generateCallFunc([compiler.ast.Const(i)], node) 494 self._doCallFunc(temp, target) 495 self._endCallFunc(temp, target) 496 497 # Provide a different source value. 498 # NOTE: Permitting immediate usage given that neither name nor 499 # NOTE: attribute accesses should involve a function call 500 # NOTE: overwriting the above result. 501 502 self.record_value(self.is_immediate_user(n)) 503 self.dispatch(n) 504 self.discard_value() 505 506 def visitAssName(self, node): 507 508 "Assign the assignment expression to the recipient 'node'." 509 510 self._visitName(node, self.name_store_instructions) 511 self.set_source() 512 513 visitAssTuple = visitAssList 514 515 def visitAugAssign(self, node): 516 use_binary_block = self.new_block() 517 end_block = self.new_block() 518 519 # Evaluate the expression. 520 521 self.dispatch(node.expr) 522 temp2 = self.optimiser.optimise_temp_storage() 523 524 # Evaluate the target. 525 526 self.dispatch(node.node) 527 temp1 = self.optimiser.optimise_temp_storage() 528 529 # Find the augmented assignment method and attempt to use it. 530 531 aug_method, (left_method, right_method) = augassign_methods[node.op] 532 temp_out = self._generateOpMethod(node, temp1, temp2, aug_method, use_binary_block, end_block) 533 self.discard_temp(temp_out) # NOTE: Will re-use the same storage. 534 535 # Where no such method exists, use the binary operator methods. 536 537 self.set_block(use_binary_block) 538 temp_out = self._generateBinary(node, temp1, temp2, left_method, right_method) 539 540 # Assign the result to the name. 541 542 self.set_block(end_block) 543 self.new_op(temp_out) 544 self.record_value(1) 545 546 if isinstance(node.node, compiler.ast.Name): 547 self.visitAssName(node.node) 548 elif isinstance(node.node, compiler.ast.Getattr): 549 self.visitAssAttr(node.node) 550 else: 551 raise TranslationNotImplementedError(self.module.full_name(), node, "AugAssign(Slice or Subscript)") 552 553 self.discard_value() 554 555 # Compilation duties... 556 557 self.discard_temp(temp1) 558 self.discard_temp(temp2) 559 560 def visitClass(self, node): 561 if not node.unit.referenced: 562 return 563 564 # Store the name. 565 566 self.new_op(LoadConst(node.unit)) 567 self.record_value() 568 self._visitName(node, self.name_store_instructions) 569 self.set_source() 570 self.discard_value() 571 572 # Visit the code. 573 574 unit = self.unit 575 self.unit = node.unit 576 self.dispatch(node.code) 577 self.unit = unit 578 579 def visitDecorators(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Decorators") 580 581 def visitFrom(self, node): pass 582 583 def visitFunction(self, node): 584 if not node.unit.referenced and (not node.unit.is_method() or not node.unit.parent.has_key(node.unit.name)): 585 return 586 587 # Only store the name when visiting this node from outside. 588 589 if self.unit is not node.unit: 590 self.new_op(LoadFunction(node.unit)) 591 self.record_value() 592 593 self._visitName(node, self.name_store_instructions) # AssName equivalent 594 self.set_source() 595 self.discard_value() 596 597 self._generateFunctionDefaults(node.unit) 598 599 # Visiting of the code occurs when get_code is invoked on this node. 600 601 else: 602 body_block = self.new_block() 603 check_block = self.new_block() 604 605 # Check frames using the function's details. 606 607 fn = node.unit 608 nparams = len(fn.positional_names) 609 ndefaults = len(fn.defaults) 610 611 self._generateFunctionContextTest(node, check_block, body_block) 612 613 # Check the number of parameters and defaults. 614 615 self.set_block(check_block) 616 617 self.new_op(CheckFrame((nparams, ndefaults, fn.has_star))) 618 if ndefaults > 0: 619 self.new_op(FillDefaults((nparams, ndefaults, fn))) 620 621 # Produce the body. 622 623 self.set_block(body_block) 624 625 extend = ExtendFrame() 626 self.new_op(extend) 627 628 self.dispatch(node.code) 629 630 if not isinstance(self.last_op(), Return): 631 self.dispatch(compiler.ast.Name("None")) 632 self.new_op(StoreResult()) 633 self.new_op(Return()) 634 635 # Make sure that enough frame space is reserved from the start. 636 637 self.set_frame_usage(node, extend) 638 639 def visitGlobal(self, node): pass 640 641 def visitImport(self, node): pass 642 643 def visitKeyword(self, node): pass 644 645 def visitLambda(self, node): 646 647 """ 648 Lambda functions can be represented as globally defined functions 649 provided they do not define any default parameter values, since these 650 may defined in a non-global scope. 651 652 Where defaults are defined, an object must be created and its content 653 defined: the callable member of the object's structure must be set to 654 the lambda function definition; each default must be attached to the 655 object as an attribute, as is the case with normal functions and 656 methods. 657 """ 658 659 # Produce the reference to this function when visiting this node from 660 # outside. 661 662 if self.unit is not node.unit: 663 temp = self._generateFunctionDefaults(node.unit) 664 self.new_op(LoadFunction(node.unit)) 665 666 # Populate the new object required for the function. 667 668 if temp is not None: 669 self.new_op(LoadCallable()) 670 self.new_op(temp) 671 self.new_op(StoreCallable()) 672 673 self.new_op(temp) 674 #self.discard_temp(temp) 675 676 # Visiting of the code occurs when get_code is invoked on this node. 677 678 else: 679 body_block = self.new_block() 680 check_block = self.new_block() 681 682 # Check frames using the function's details. 683 684 fn = node.unit 685 nparams = len(fn.positional_names) 686 ndefaults = len(fn.defaults) 687 688 self._generateFunctionContextTest(node, check_block, body_block) 689 690 # Check the number of parameters and defaults. 691 692 self.set_block(check_block) 693 694 self.new_op(CheckFrame((nparams, ndefaults, fn.has_star))) 695 if ndefaults > 0: 696 self.new_op(FillDefaults((nparams, ndefaults, fn))) 697 698 # Produce the body. 699 700 self.set_block(body_block) 701 702 extend = ExtendFrame() 703 self.new_op(extend) 704 705 self.dispatch(node.code) 706 707 self.new_op(StoreResult()) 708 self.new_op(Return()) 709 710 # Make sure that enough frame space is reserved from the start. 711 712 self.set_frame_usage(node, extend) 713 714 def visitModule(self, node): 715 extend = ExtendFrame() 716 self.new_op(extend) 717 self.dispatch(node.node) 718 self.set_frame_usage(node, extend) 719 720 # Statements. 721 722 def visitStmt(self, node): 723 724 "Process the collection of statements provided by 'node'." 725 726 for n in node.nodes: 727 728 # Process the statement. 729 730 self.dispatch(n) 731 732 # Discard temporary storage. 733 734 if self.temp_positions: 735 #print "Had temp", self.temp_positions 736 self.temp_positions = set() 737 738 # Prevent incorrect optimisation by resetting the optimiser after 739 # each statement. 740 741 self.optimiser.reset() 742 743 def visitAssert(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Assert") 744 745 def visitBreak(self, node): 746 next_block, exit_block = self.get_loop_blocks() 747 self.new_op(Jump(exit_block)) 748 749 def visitContinue(self, node): 750 next_block, exit_block = self.get_loop_blocks() 751 self.new_op(Jump(next_block)) 752 753 def visitDiscard(self, node): 754 self.dispatch(node.expr) 755 self.optimiser.optimise_unused_results() 756 757 def visitFor(self, node): 758 next_handler_block = self.new_block() 759 end_handler_block = self.new_block() 760 exit_block = self.new_block() 761 next_block = self.new_block() 762 else_block = self.new_block() 763 764 # Get the "list" to be iterated over, obtain its iterator. 765 766 self._startCallFunc() 767 self.dispatch(node.list) 768 self._generateAttr(node, "__iter__", self.attribute_load_instructions) 769 temp, target = self._generateCallFunc([], node) 770 self._doCallFunc(temp, target) 771 self._endCallFunc(temp, target) 772 773 temp_iterator = self.optimiser.optimise_temp_storage() 774 775 # In the loop... 776 777 self.set_block(next_block) 778 779 # Handle exceptions when calling "next"... 780 781 self.new_op(PushHandler(next_handler_block)) 782 783 # Use the iterator to get the next value. 784 785 self._startCallFunc() 786 self.new_op(temp_iterator) 787 self._generateAttr(node, "next", self.attribute_load_instructions) 788 temp, target = self._generateCallFunc([], node) 789 self._doCallFunc(temp, target) 790 self._endCallFunc(temp, target) 791 792 # Record the value to be assigned. 793 794 self.record_value() 795 796 # Skip the handler where the call was successful. 797 798 self.new_op(Jump(end_handler_block)) 799 800 # Enter the exception handler. 801 802 self.set_block(next_handler_block) 803 self.new_op(PopHandler()) 804 805 # Test for StopIteration. 806 807 self.load_builtin("StopIteration", node) 808 self.new_op(CheckException()) 809 if node.else_ is not None: 810 self.new_op(JumpIfTrue(else_block)) 811 else: 812 self.new_op(JumpIfTrue(exit_block)) 813 814 # Re-raise the exception otherwise. 815 816 self.new_op(RaiseException()) 817 818 # After the handler. 819 820 self.set_block(end_handler_block) 821 822 # Assign to the target. 823 824 self.dispatch(node.assign) 825 self.discard_value() 826 827 # Process the body with the current next and exit points. 828 829 self.add_loop_blocks(next_block, exit_block) 830 self.dispatch(node.body) 831 self.drop_loop_blocks() 832 833 # Repeat the loop. 834 835 self.new_op(Jump(next_block)) 836 837 # Produce the "else" section. 838 839 if node.else_ is not None: 840 self.set_block(exit_block) 841 842 self.dispatch(node.else_) 843 844 # After the loop... 845 846 self.set_block(exit_block) 847 848 # Compilation duties... 849 850 self.discard_temp(temp_iterator) 851 852 def visitIf(self, node): 853 first = 1 854 exit_block = self.new_block() 855 856 clauses = node.tests + [(None, node.else_)] 857 last_clause = clauses[-1] 858 859 for clause in clauses: 860 test, body = clause 861 if body is None: 862 break 863 if not first: 864 self.set_block(next_block) 865 if test is not None: 866 self.dispatch(test) 867 next_block = self.new_block() 868 self.new_op(JumpIfFalse(next_block)) 869 self.dispatch(body) 870 if clause is not last_clause: 871 self.new_op(Jump(exit_block)) 872 873 first = 0 874 875 self.set_block(exit_block) 876 877 def visitPass(self, node): pass 878 879 def visitPrint(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Print") 880 881 def visitPrintnl(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Printnl") 882 883 def visitRaise(self, node): 884 # NOTE: expr1 only => instance provided 885 self.dispatch(node.expr1) 886 887 if node.expr2 is not None: 888 temp = self.optimiser.optimise_temp_storage() 889 890 self.dispatch(node.expr2) 891 temp_arg = self.optimiser.optimise_temp_storage() 892 893 self._startCallFunc() 894 self.new_op(temp_arg) 895 self.new_op(StoreFrame(0)) 896 self._endCallFuncArgs(1) 897 self._doCallFunc(temp) 898 self._endCallFunc(temp) 899 900 self.discard_temp(temp_arg) 901 902 self.new_op(StoreException()) 903 self.new_op(RaiseException()) 904 905 def visitReturn(self, node): 906 if node.value is not None: 907 self.dispatch(node.value) 908 else: 909 self.dispatch(compiler.ast.Name("None")) 910 911 self.new_op(StoreResult()) 912 self.new_op(Return()) 913 914 def visitTryExcept(self, node): 915 exit_block = self.new_block() 916 else_block = self.new_block() 917 handler_block = self.new_block() 918 919 self.add_exception_blocks(handler_block, exit_block) 920 921 # Try... 922 # Produce the code, then jump to the exit. 923 924 self.new_op(PushHandler(handler_block)) 925 self.dispatch(node.body) 926 self.new_op(PopHandler()) 927 928 if node.else_ is not None: 929 self.new_op(Jump(else_block)) 930 else: 931 self.new_op(Jump(exit_block)) 932 933 # Start of handlers. 934 935 self.set_block(handler_block) 936 937 self.new_op(PopHandler()) 938 939 for name, assignment, handler in node.handlers: 940 next_block = self.new_block() 941 942 # Test the given exception against the current exception. 943 944 if name is not None: 945 self.dispatch(name) 946 947 self.new_op(CheckException()) 948 self.new_op(JumpIfFalse(next_block)) 949 950 # Handle assignment to exception variable. 951 952 if assignment is not None: 953 self.new_op(LoadException()) 954 955 # Record the value to be assigned. 956 957 self.record_value() 958 self.dispatch(assignment) 959 self.discard_value() 960 961 # Produce the handler code, then jump to the exit. 962 963 self.dispatch(handler) 964 self.new_op(Jump(exit_block)) 965 966 self.set_block(next_block) 967 968 # Unhandled exceptions. 969 970 self.new_op(RaiseException()) 971 972 # Optional else clause. 973 974 if node.else_ is not None: 975 self.set_block(else_block) 976 977 self.dispatch(node.else_) 978 979 self.set_block(exit_block) 980 self.drop_exception_blocks() 981 982 def visitTryFinally(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "TryFinally") 983 984 def visitWhile(self, node): 985 exit_block = self.new_block() 986 next_block = self.new_block() 987 else_block = self.new_block() 988 989 self.set_block(next_block) 990 self.dispatch(node.test) 991 if node.else_ is not None: 992 self.new_op(JumpIfFalse(else_block)) 993 else: 994 self.new_op(JumpIfFalse(exit_block)) 995 996 self.add_loop_blocks(next_block, exit_block) 997 998 self.dispatch(node.body) 999 self.new_op(Jump(next_block)) 1000 1001 if node.else_ is not None: 1002 self.set_block(else_block) 1003 1004 self.dispatch(node.else_) 1005 1006 self.set_block(exit_block) 1007 1008 self.drop_loop_blocks() 1009 1010 def visitWith(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "With") 1011 1012 def visitYield(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Yield") 1013 1014 # vim: tabstop=4 expandtab shiftwidth=4