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