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