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 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.rsvp import * 25 import compiler.ast 26 from compiler.visitor import ASTVisitor 27 28 # Program visitors. 29 30 class Translation(ASTVisitor): 31 32 "A translated module." 33 34 supported_optimisations = ["constant_storage", "known_target", "self_access", "temp_storage", "load_operations", "unused_results"] 35 36 attribute_load_instructions = (LoadAddress, LoadAddressContext, LoadAttr, LoadAttrIndex) 37 attribute_store_instructions = (None, None, StoreAttr, StoreAttrIndex) 38 name_load_instructions = (LoadName, LoadAddress) 39 name_store_instructions = (StoreName, StoreAddress) 40 41 def __init__(self, module, importer, optimisations=None): 42 43 """ 44 Initialise the translation with an inspected 'module', the 'importer' 45 and optional 'optimisations'. See the 'supported_optimisations' 46 attribute of this class for permitted values. 47 """ 48 49 ASTVisitor.__init__(self) 50 self.visitor = self 51 self.module = module 52 53 # Global program dependencies. 54 55 self.importer = importer 56 self.objtable = self.importer.get_object_table() 57 self.paramtable = self.importer.get_parameter_table() 58 self.builtins = self.importer.modules.get("__builtins__") 59 60 # Desired optimisations. 61 62 self.optimisations = set(optimisations or []) 63 64 # The current unit being translated. 65 66 self.unit = None 67 68 # The current "active" instruction. 69 # As a rule, this will become the last instruction, but some 70 # control-flow operations will flush the "active" instruction. 71 72 self.active = None 73 74 # The temporary storage used by the current assignment expression. 75 76 self.expr_temp = None 77 78 # Wiring within the code. 79 80 self.labels = {} 81 self.label_number = 0 82 self.loop_labels = [] 83 self.exception_labels = [] 84 85 # The code itself. This is limited to the code for a particular block 86 # being processed. Also retained is information about temporary values. 87 88 self.code = None 89 self.temp_position = 0 90 91 def __repr__(self): 92 return "Translation(%r)" % self.module 93 94 def get_module_code(self): 95 96 "Return the top-level module code." 97 98 self.unit = self.module 99 self.code = [] 100 self.temp_position = 0 101 102 if self.module.module is not None: 103 self.dispatch(self.module.module) 104 105 return self.code 106 107 def get_code(self, unit): 108 109 "Return the code for the given 'unit'." 110 111 self.unit = unit 112 self.code = [] 113 self.temp_position = 0 114 115 if unit.astnode is not None: 116 self.dispatch(unit.astnode) 117 118 return self.code 119 120 # Name-related methods. 121 122 def get_scope(self, name): 123 124 "Return the scope for the given 'name'." 125 126 if self.unit.has_key(name): 127 return "local" 128 elif self.module.has_key(name): 129 return "global" 130 else: 131 return "builtins" 132 133 def load_builtin(self, name, node): 134 135 "Generate an instruction loading 'name' for the given 'node'." 136 137 self.new_op(LoadAddress(self.get_builtin(name, node))) 138 139 def get_builtin(self, name, node): 140 141 """ 142 Return the built-in module definition for the given 'name', used by the 143 given 'node'. 144 """ 145 146 if self.builtins is not None: 147 try: 148 return self.builtins[name] 149 except KeyError: 150 raise TranslateError(self.module.full_name(), node, "No __builtins__ definition is available for name %r." % name) 151 else: 152 raise TranslateError(self.module.full_name(), node, "No __builtins__ module is available for name %r." % name) 153 154 # Code feature methods. 155 156 def new_label(self): 157 158 "Return a new label object for use with set_label." 159 160 number = self.label_number 161 label = Label(number) 162 self.labels[label] = label 163 self.label_number += 1 164 return label 165 166 def set_label(self, label): 167 168 """ 169 Set the location of 'label' to that within the entire image: the 170 location within the code combined with location of the code unit. 171 """ 172 173 label.location = len(self.code) + self.unit.code_location 174 175 def get_loop_labels(self): 176 return self.loop_labels[-1] 177 178 def add_loop_labels(self, next_label, exit_label): 179 self.loop_labels.append((next_label, exit_label)) 180 181 def drop_loop_labels(self): 182 self.loop_labels.pop() 183 184 def get_exception_labels(self): 185 return self.exception_labels[-1] 186 187 def add_exception_labels(self, handler_label, exit_label): 188 self.exception_labels.append((handler_label, exit_label)) 189 190 def drop_exception_labels(self): 191 self.exception_labels.pop() 192 193 # Assignment expression values. 194 195 def record_value(self): 196 self.expr_temp = self._optimise_temp_storage() 197 198 def discard_value(self): 199 self.discard_temp(self.expr_temp) 200 self.expr_temp = None 201 202 def set_source(self): 203 if self.active is not None: 204 self.active.source = self.expr_temp 205 206 # Optimise away constant storage if appropriate. 207 208 self._optimise_constant_storage() 209 210 # Temporary storage administration. 211 212 def get_temp(self): 213 214 """ 215 Add a temporary storage instruction for the current value and return a 216 sequence of access instructions. 217 """ 218 219 temp_position = self.reserve_temp(1) 220 self.new_op(StoreTemp(temp_position)) 221 return LoadTemp(temp_position) 222 223 def ensure_temp(self): 224 if isinstance(self.active, LoadTemp): 225 self.temp_position = max(self.temp_position, self.active.attr + 1) 226 227 def reserve_temp(self, n): 228 temp_position = self.temp_position 229 self.temp_position += n 230 return temp_position 231 232 def discard_temp(self, instruction): 233 if isinstance(instruction, LoadTemp): 234 self.temp_position -= 1 235 236 # Code writing methods. 237 238 def new_op(self, op): 239 240 "Add 'op' to the generated code." 241 242 # Optimise load operations employed by this instruction. 243 244 self._optimise_load_operations(op) 245 246 self.code.append(op) 247 self.active = op 248 249 def remove_op(self): 250 251 "Remove the last instruction." 252 253 op = self.code.pop() 254 self.active = None 255 256 def replace_op(self, op): 257 258 "Replace the last added instruction with 'op'." 259 260 self.remove_op() 261 self.new_op(op) 262 263 def last_op(self): 264 265 "Return the last added instruction." 266 267 try: 268 return self.code[-1] 269 except IndexError: 270 return None 271 272 # Optimisation tests. 273 274 def _should_optimise_constant_storage(self): 275 return "constant_storage" in self.optimisations 276 277 def _should_optimise_known_target(self): 278 return "known_target" in self.optimisations 279 280 def _should_optimise_self_access(self): 281 return "self_access" in self.optimisations 282 283 def _should_optimise_temp_storage(self): 284 return "temp_storage" in self.optimisations 285 286 def _should_optimise_load_operations(self): 287 return "load_operations" in self.optimisations 288 289 def _should_optimise_unused_results(self): 290 return "unused_results" in self.optimisations 291 292 # Simple tests. 293 294 def _is_constant_input(self, instruction): 295 296 "Return whether 'instruction' provides a constant input." 297 298 return isinstance(instruction, LoadAddress) and instruction.attr.assignments == 1 or \ 299 isinstance(instruction, LoadConst) 300 301 def _is_constant_target(self, instruction): 302 303 "Return whether 'instruction' provides a constant target." 304 305 return isinstance(instruction, (StoreName, StoreAddress)) and \ 306 instruction.attr.assignments == 1 307 308 def _is_simple_input(self, instruction): 309 310 "Return whether 'instruction' provides a simple input." 311 312 return isinstance(instruction, (LoadConst, LoadName, LoadTemp, LoadResult, LoadAddress, MakeObject)) 313 314 def _is_simple_input_user(self, instruction): 315 316 "Return whether 'instruction' can use simple input from the current value." 317 318 return isinstance(instruction, ( 319 StoreTemp, StoreFrame, StoreResult, StoreException, # as the value being stored 320 LoadAddressContext, LoadAttr, LoadAttrIndex, # as the object being referenced 321 StoreAttr, StoreAttrIndex, StoreCallable # as the object being referenced 322 )) 323 324 def _is_input(self, instruction): 325 326 "Return whether 'instruction' provides an input." 327 328 return isinstance(instruction, (LoadConst, LoadName, LoadTemp, LoadResult) + self.attribute_load_instructions) 329 330 # Convenience tests. 331 332 def _have_constant_input(self): 333 334 "Return whether the active instruction provides a constant input." 335 336 return self._is_constant_input(self.active) 337 338 _have_known_target = _have_constant_input 339 340 def _have_constant_target(self): 341 342 "Return whether the active instruction provides a constant target." 343 344 return self._is_constant_target(self.active) 345 346 def _have_constant_source(self): 347 348 "Return whether the active instruction has a constant source." 349 350 return self._is_constant_input(self.active.source) 351 352 def _have_simple_input(self): 353 354 "Return whether the active instruction provides a simple input." 355 356 return self._is_simple_input(self.active) 357 358 def _have_input(self): 359 360 "Return whether the active instruction provides an input." 361 362 return self._is_input(self.active) 363 364 def _have_self_input(self): 365 366 "Return whether the active instruction is a reference to self." 367 368 return isinstance(self.unit, Function) and \ 369 self.unit.is_method() and isinstance(self.active, LoadName) and \ 370 self.active.attr.name == "self" 371 372 def _have_temp_compatible_access(self): 373 374 """ 375 Indicate whether the active instruction can be used in place of access 376 to a temporary variable retaining the result of the last instruction. 377 """ 378 379 return isinstance(self.active, (LoadName, LoadTemp, LoadAddress, LoadConst, LoadResult)) 380 381 # Optimisation methods. See the supported_optimisations class attribute. 382 383 def _optimise_constant_storage(self): 384 385 """ 386 Where the last operation stores a constant into a target which is also 387 constant, optimise away both operations. 388 """ 389 390 if self._should_optimise_constant_storage() and \ 391 self._have_constant_target() and \ 392 self._have_constant_source(): 393 394 self.remove_op() 395 return 1 396 else: 397 return 0 398 399 def _optimise_known_target(self): 400 401 """ 402 Where the target of an invocation is known, provide information about it 403 and its context. If a class is being invoked and the conditions are 404 appropriate, get information about the specific initialiser. 405 """ 406 407 if self._should_optimise_known_target() and self._have_known_target(): 408 last = self.last_op() 409 target = last.attr.value 410 context = last.attr.context 411 412 # Handle calls to classes. 413 414 if isinstance(target, Class): 415 target = target.get_instantiator() 416 context = Undefined() 417 418 # A special context is chosen to avoid generating unnecessary 419 # context loading and checking instructions. 420 421 return target, context 422 else: 423 return None 424 425 def _optimise_self_access(self, attrname, classes, node): 426 427 """ 428 Where the provided 'attrname' accesses an attribute which occupies the 429 same position in all possible objects which can be accessed, generate an 430 instruction using one of the given 'classes', accessing the attribute 431 directly. 432 """ 433 434 AddressInstruction, AddressContextInstruction, AttrInstruction = classes 435 436 if self._should_optimise_self_access() and self._have_self_input() and \ 437 not self.unit.is_relocated(attrname): 438 439 # Either generate an instruction operating on an instance attribute. 440 441 try: 442 attr = self.unit.parent.instance_attributes()[attrname] 443 self.new_op(AttrInstruction(attr)) 444 445 # Or generate an instruction operating on a class attribute. 446 447 except KeyError: 448 attr = self.unit.parent.all_attributes()[attrname] 449 new_attr = attr.via_instance() 450 451 # Only permit loading (not storing) of class attributes via self. 452 453 if AddressContextInstruction is not None: 454 self.new_op(AddressContextInstruction(new_attr)) 455 else: 456 raise TranslateError(self.module.full_name(), node, 457 "Storing of class attribute %r via self not permitted." % attrname) 458 459 return 1 460 else: 461 return 0 462 463 def _optimise_temp_storage(self): 464 465 """ 466 Where the next operation would involve storing a value into temporary 467 storage at 'temp_position', record and remove any simple instruction 468 which produced the value to be stored such that instead of subsequently 469 accessing the temporary storage, that instruction is substituted. 470 471 If no optimisation can be achieved, a StoreTemp instruction is produced 472 and the appropriate LoadTemp instruction is returned. 473 474 Restriction: for use only in situations where the source of the 475 temporary data will not be disturbed between its first access and its 476 subsequent use. 477 """ 478 479 if self._should_optimise_temp_storage() and \ 480 self._have_temp_compatible_access(): 481 482 # Where an existing temporary storage reference will be retained, 483 # keep it active. 484 485 self.ensure_temp() 486 487 last = self.last_op() 488 self.remove_op() 489 return last 490 else: 491 return self.get_temp() 492 493 def _optimise_load_operations(self, instruction): 494 495 """ 496 Incorporate previous load operations into other operations. 497 """ 498 499 if self._should_optimise_load_operations() and \ 500 self._have_simple_input() and \ 501 self._is_simple_input_user(instruction): 502 503 last = self.last_op() 504 self.remove_op() 505 instruction.input = last 506 507 def _optimise_unused_results(self): 508 509 "Discard results which will not be used." 510 511 if self._have_input(): 512 self.remove_op() 513 514 # Visitor methods. 515 516 def default(self, node, *args): 517 raise TranslateError(self.module.full_name(), node, "Node class %r is not supported." % node.__class__) 518 519 def dispatch(self, node, *args): 520 return ASTVisitor.dispatch(self, node, *args) 521 522 # Internal helper methods. 523 524 def _visitAttr(self, node, classes): 525 526 """ 527 Visit the attribute-related 'node', generating instructions based on the 528 given 'classes'. 529 """ 530 531 self.dispatch(node.expr) 532 self._generateAttr(node, node.attrname, classes) 533 534 def _generateAttr(self, node, attrname, classes): 535 536 """ 537 Generate code for the access to 'attrname' using the given 'classes'. 538 """ 539 540 AddressInstruction, AddressContextInstruction, AttrInstruction, AttrIndexInstruction = classes 541 542 # Where the last operation (defining the attribute owner) yields a 543 # constant... 544 545 if self._have_constant_input(): 546 last = self.active 547 548 # Get the details of the access. 549 550 if isinstance(last.attr, Const): 551 target_name = last.attr.value_type_name() 552 else: 553 target = last.attr.value 554 555 if isinstance(target, Const): 556 target_name = target.value_type_name() 557 elif isinstance(target, Instance): 558 target_name = None # skip production of optimised code 559 else: 560 target_name = target.full_name() 561 562 # Only try and discover the position if the target can be resolved. 563 564 if target_name is not None: 565 566 # Access the object table to get the attribute position. 567 568 try: 569 table_entry = self.objtable.table[target_name] 570 except KeyError: 571 raise TranslateError(self.module.full_name(), node, 572 "No object entry exists for target %r." % target_name) 573 574 try: 575 pos = table_entry[attrname] 576 except KeyError: 577 raise TranslateError(self.module.full_name(), node, 578 "No attribute entry exists for name %r in target %r." % (attrname, target_name)) 579 580 # Produce a suitable instruction. 581 582 if AddressInstruction is not None: 583 self.replace_op(AddressInstruction(pos)) 584 else: 585 raise TranslateError(self.module.full_name(), node, 586 "Storing of class or module attribute %r via an object is not permitted." % attrname) 587 588 return 589 590 # Where the last operation involves the special 'self' name, check to 591 # see if the attribute is acceptably positioned and produce a direct 592 # access to the attribute. 593 594 elif self._optimise_self_access(attrname, (AddressInstruction, AddressContextInstruction, AttrInstruction), node): 595 return 596 597 # Otherwise, perform a normal operation. 598 599 try: 600 index = self.objtable.get_index(attrname) 601 except self.objtable.TableError: 602 raise TranslateError(self.module.full_name(), node, 603 "No attribute entry exists for name %r." % attrname) 604 605 self.new_op(AttrIndexInstruction(index)) 606 607 # Invocations involve the following: 608 # 609 # 1. Reservation of a frame for the arguments 610 # 2. Identification of the target which is then held in temporary storage 611 # 3. Optional inclusion of a context (important for methods) 612 # 4. Preparation of the argument frame 613 # 5. Invocation of the target 614 # 6. Discarding of the frame 615 # 616 # In order to support nested invocations - eg. a(b(c)) - use of the 617 # temporary storage is essential. 618 619 def _startCallFunc(self): 620 621 "Record the location of the invocation." 622 623 self.new_op(MakeFrame()) # records the start of the frame 624 625 def _generateCallFunc(self, args, node): 626 627 """ 628 Support a generic function invocation using the given 'args', occurring 629 on the given 'node', where the expression providing the invocation 630 target has just been generated. 631 632 In other situations, the invocation is much simpler and does not need to 633 handle the full flexibility of a typical Python invocation. Internal 634 invocations, such as those employed by operators and certain 635 control-flow mechanisms, use predetermined arguments and arguably do not 636 need to support the same things as the more general invocations. 637 """ 638 639 target, context, temp = self._generateCallFuncContext() 640 self._generateCallFuncArgs(target, context, temp, args, node) 641 return temp 642 643 def _generateCallFuncContext(self): 644 645 """ 646 Produce code which loads and checks the context of the current 647 invocation, the instructions for whose target have already been 648 produced, returning a list of instructions which reference the 649 invocation target. 650 """ 651 652 t = self._optimise_known_target() 653 if t: 654 target, context = t 655 else: 656 target, context = None, None 657 658 # Store the target in temporary storage for subsequent referencing. 659 660 temp = self._optimise_temp_storage() 661 662 # Where a target or context are not known or where an instance is known 663 # to be the context, load the context. 664 665 if context is None or isinstance(context, Instance): 666 self.new_op(temp) 667 self.new_op(LoadContext()) 668 self.new_op(StoreFrame(0)) 669 670 # Otherwise omit the context. 671 672 else: 673 pass # NOTE: Class methods should be supported. 674 675 return target, context, temp 676 677 def _generateCallFuncArgs(self, target, context, temp, args, node): 678 679 """ 680 Given invocation 'target' and 'context' information, the 'temp' 681 reference to the target, a list of nodes representing the 'args' 682 (arguments), generate instructions which load the arguments for the 683 invocation defined by the given 'node'. 684 """ 685 686 # Evaluate the arguments. 687 688 employed_positions = set() 689 extra_keywords = [] 690 691 # Note the presence of the context in the frame where appropriate. 692 693 if context is None or isinstance(context, Instance): 694 ncontext = 1 695 expect_context = 0 696 elif isinstance(context, Class): 697 ncontext = 0 698 expect_context = 1 699 else: 700 ncontext = 0 701 expect_context = 0 702 703 first = 1 704 frame_pos = ncontext 705 max_keyword_pos = -1 706 707 for arg in args: 708 709 # Handle positional and keyword arguments separately. 710 711 if isinstance(arg, compiler.ast.Keyword): 712 713 # Optimise where the target is known now. 714 715 if target is not None: 716 717 # Find the parameter table entry for the target. 718 719 target_name = target.full_name() 720 721 # Look for a callable with the precise target name. 722 723 table_entry = self.paramtable.table[target_name] 724 725 # Look the name up in the parameter table entry. 726 727 try: 728 pos = table_entry[arg.name] 729 730 # Where no position is found, this could be an extra keyword 731 # argument. 732 733 except KeyError: 734 extra_keywords.append(arg) 735 continue 736 737 # Test for illegal conditions. 738 739 if pos in employed_positions: 740 raise TranslateError(self.module.full_name(), node, 741 "Keyword argument %r overwrites parameter %r." % (arg.name, pos)) 742 743 employed_positions.add(pos) 744 745 # Generate code for the keyword and the positioning 746 # operation. 747 748 self.dispatch(arg.expr) 749 self.new_op(StoreFrame(pos)) 750 751 # Otherwise, generate the code needed to obtain the details of 752 # the parameter location. 753 754 else: 755 756 # Combine the target details with the name to get the location. 757 # See the access method on the List class. 758 759 try: 760 paramindex = self.paramtable.get_index(arg.name) 761 762 # Where no position is found, this could be an extra keyword 763 # argument. 764 765 except self.paramtable.TableError: 766 extra_keywords.append(arg) 767 continue 768 769 # Generate code for the keyword and the positioning 770 # operation. 771 772 self.dispatch(arg.expr) 773 self.new_op(StoreFrameIndex(paramindex)) 774 775 # use (callable+0)+paramindex+table 776 # checks embedded offset against (callable+0) 777 # moves the current value to frame+position 778 779 # Record the highest possible frame position for this argument. 780 781 max_keyword_pos = max(max_keyword_pos, max(self.paramtable.all_attribute_positions(arg.name))) 782 783 else: 784 self.dispatch(arg) 785 self.new_op(StoreFrame(frame_pos)) 786 787 employed_positions.add(frame_pos) 788 789 # Check to see if the first argument is appropriate (compatible with 790 # the target where methods are being invoked via classes). 791 792 if first and expect_context: 793 continue_label = self.new_label() 794 self.new_op(CheckSelf()) 795 self.new_op(JumpIfTrue(continue_label)) 796 797 # Where the context is inappropriate, drop the incomplete frame and 798 # raise an exception. 799 800 self.new_op(DropFrame()) 801 802 self.new_op(LoadResult()) 803 804 self.load_builtin("TypeError", node) 805 self.new_op(StoreException()) 806 self.new_op(RaiseException()) 807 self.set_label(continue_label) 808 809 first = 0 810 frame_pos += 1 811 812 # NOTE: Extra keywords are not supported. 813 # NOTE: Somehow, the above needs to be combined with * arguments. 814 815 if extra_keywords: 816 print "Warning: extra keyword argument(s) %s not handled." % ", ".join([arg.name for arg in extra_keywords]) 817 818 # Either test for a complete set of arguments. 819 820 if target is not None: 821 822 # Make sure that enough arguments have been given. 823 824 nargs_max = len(target.positional_names) 825 ndefaults = len(target.defaults) 826 nargs_min = nargs_max - ndefaults 827 828 for i in range(ncontext, nargs_min): 829 if i not in employed_positions: 830 raise TranslateError(self.module.full_name(), node, 831 "Argument %r not supplied for %r: need at least %d argument(s)." % (i+1, target.name, nargs_min)) 832 833 nargs = len(args) 834 835 if nargs > nargs_max and not target.has_star and not target.has_dstar: 836 raise TranslateError(self.module.full_name(), node, 837 "Too many arguments for %r: need at most %d argument(s)." % (target.name, nargs_max)) 838 839 # Where defaults are involved, put them into the frame. 840 841 self._generateCallFuncDefaultArgs(target, temp, nargs_min, nargs_max, employed_positions) 842 843 # Or generate instructions to do this at run-time. 844 # NOTE: CheckFrame has to check the number of arguments and to fill in 845 # NOTE: defaults; it also has to shift the invocation frame according to 846 # NOTE: the context in use. 847 848 else: 849 850 # Only check non-empty frames. 851 852 if employed_positions or max_keyword_pos >= 0: 853 max_pos = max(max(employed_positions), max_keyword_pos, frame_pos - 1) 854 self.new_op(CheckFrame(max_pos + 1)) 855 856 def _generateCallFuncDefaultArgs(self, target, temp, nargs_min, nargs_max, employed_positions): 857 858 """ 859 For the given 'target' and 'temp' reference to the target, generate 860 default arguments for those positions in the range 'nargs_min'... 861 'nargs_max' which are not present in the 'employed_positions' 862 collection. 863 """ 864 865 # Where a lambda is involved, construct a dynamic object to hold the 866 # defaults. 867 868 dynamic = target.name is None 869 870 # Here, we use negative index values to visit the right hand end of 871 # the defaults list. 872 873 for pos in range(nargs_min, nargs_max): 874 if pos not in employed_positions: 875 if dynamic: 876 self.new_op(temp) 877 self.new_op(LoadAttr(target.default_attrs[pos - nargs_min])) 878 else: 879 self.new_op(LoadAddress(target.default_attrs[pos - nargs_min])) 880 self.new_op(StoreFrame(pos)) 881 882 def _doCallFunc(self, instruction): 883 884 "Make the invocation." 885 886 self.new_op(instruction) 887 self.new_op(JumpWithFrame()) 888 889 def _endCallFunc(self, instruction=None): 890 891 "Finish the invocation and tidy up afterwards." 892 893 self.new_op(DropFrame()) 894 self.new_op(LoadResult()) 895 896 # Discard any temporary storage instructions. 897 898 if instruction is not None: 899 self.discard_temp(instruction) 900 901 def _generateFunctionDefaults(self, function): 902 903 """ 904 Generate the default initialisation code for 'function', returning 905 a temporary storage reference if a dynamic object was created for the 906 function. 907 """ 908 909 attr_to_default = zip(function.default_attrs, function.defaults) 910 if not attr_to_default: 911 return None 912 913 # Where a lambda is involved, construct a dynamic object to hold the 914 # defaults. 915 916 dynamic = function.name is None 917 918 if dynamic: 919 self.new_op(MakeObject(("function", len(attr_to_default)))) 920 temp = self.get_temp() 921 922 for attr, default in attr_to_default: 923 self.dispatch(default) 924 925 self.record_value() 926 if dynamic: 927 self.new_op(temp) 928 self.new_op(StoreAttr(attr)) 929 else: 930 self.new_op(StoreAddress(attr)) 931 self.set_source() 932 self.discard_value() 933 934 if dynamic: 935 return temp 936 else: 937 return None 938 939 def _visitName(self, node, classes): 940 941 """ 942 Visit the name-related 'node', generating instructions based on the 943 given 'classes'. 944 """ 945 946 name = node.name 947 scope = self.get_scope(name) 948 #print self.module.name, node.lineno, name, scope 949 self._generateName(name, scope, classes, node) 950 951 def _generateName(self, name, scope, classes, node): 952 953 """ 954 Generate code for the access to 'name' in 'scope' using the given 955 'classes', and using the given 'node' as the source of the access. 956 """ 957 958 NameInstruction, AddressInstruction = classes 959 960 if scope == "local": 961 unit = self.unit 962 if isinstance(unit, Function): 963 self.new_op(NameInstruction(unit.all_locals()[name])) 964 elif isinstance(unit, Class): 965 self.new_op(AddressInstruction(unit.all_class_attributes()[name])) 966 elif isinstance(unit, Module): 967 self.new_op(AddressInstruction(unit.module_attributes()[name])) 968 else: 969 raise TranslateError(self.module.full_name(), node, "Program unit %r has no local %r." % (unit, name)) 970 971 elif scope == "global": 972 globals = self.module.module_attributes() 973 if globals.has_key(name): 974 self.new_op(AddressInstruction(globals[name])) 975 else: 976 raise TranslateError(self.module.full_name(), node, "Module %r has no attribute %r." % (self.module, name)) 977 978 else: 979 self.new_op(AddressInstruction(self.get_builtin(name, node))) 980 981 def _visitUnary(self, node, method): 982 983 """ 984 _t = node.expr 985 try: 986 _result = _t.__pos__() 987 except AttributeError: 988 raise TypeError 989 """ 990 991 end_call_label = self.new_label() 992 end_label = self.new_label() 993 994 # Evaluate and store the operand in temporary storage. 995 996 self.dispatch(node.expr) 997 temp = self._optimise_temp_storage() 998 999 # Produce the invocation. 1000 1001 self._startCallFunc() 1002 self.new_op(temp) 1003 1004 # Get the method on temp. 1005 1006 self._generateAttr(node, method, self.attribute_load_instructions) 1007 1008 # Add exception handling to the method acquisition instructions where 1009 # the attribute access cannot be resolved at compile-time. 1010 1011 if not self._optimise_known_target(): 1012 self.load_builtin("AttributeError", node) 1013 self.new_op(CheckException()) 1014 self.new_op(JumpIfTrue(end_call_label)) 1015 1016 temp_method = self._optimise_temp_storage() 1017 1018 # Add arguments. 1019 # NOTE: No support for defaults. 1020 1021 self.new_op(temp) # Explicit context as first argument. 1022 self._doCallFunc(temp_method) 1023 self._endCallFunc(temp_method) 1024 self.new_op(Jump(end_label)) 1025 1026 # End method attempt. 1027 1028 self.set_label(end_call_label) 1029 self._endCallFunc() # From the method call. 1030 1031 # Raise a TypeError. 1032 1033 self.load_builtin("TypeError", node) 1034 self.new_op(StoreException()) 1035 self.new_op(RaiseException()) 1036 1037 self.set_label(end_label) 1038 1039 # Compilation duties... 1040 1041 self.discard_temp(temp) 1042 1043 def _visitBinary(self, node, left_method, right_method): 1044 1045 """ 1046 _t1 = node.left 1047 _t2 = node.right 1048 try: 1049 _result = _t1.__add__(_t2) 1050 if _result is NotImplemented: 1051 raise AttributeError 1052 except AttributeError: 1053 try: 1054 _result = _t2.__radd__(_t1) 1055 if _result is NotImplemented: 1056 raise AttributeError 1057 except AttributeError: 1058 raise TypeError 1059 """ 1060 1061 # Evaluate and store the left operand in temporary storage. 1062 1063 self.dispatch(node.left) 1064 temp1 = self._optimise_temp_storage() 1065 1066 # Evaluate and store the right operand in temporary storage. 1067 1068 self.dispatch(node.right) 1069 temp2 = self._optimise_temp_storage() 1070 1071 self._generateBinary(temp1, temp2, left_method, right_method) 1072 1073 # Compilation duties... 1074 1075 self.discard_temp(temp1) 1076 self.discard_temp(temp2) 1077 1078 def _generateBinary(self, temp1, temp2, left_method, right_method): 1079 1080 right_label = self.new_label() 1081 type_error_label = self.new_label() 1082 end_label = self.new_label() 1083 1084 # Left method. 1085 1086 self._generateOpMethod(temp1, temp2, left_method, right_label, end_label) 1087 1088 # Right method. 1089 1090 self.set_label(right_label) 1091 self._generateOpMethod(temp2, temp1, right_method, type_error_label, end_label) 1092 1093 # Raise a TypeError. 1094 1095 self.set_label(type_error_label) 1096 self.load_builtin("TypeError", node) 1097 self.new_op(StoreException()) 1098 self.new_op(RaiseException()) 1099 1100 self.set_label(end_label) 1101 1102 def _generateOpMethod(self, temp1, temp2, method_name, next_method_label, end_label): 1103 1104 end_attempt_label = self.new_label() 1105 1106 self._startCallFunc() 1107 self.new_op(temp1) 1108 1109 # Get method on temp1. 1110 1111 self._generateAttr(node, method_name, self.attribute_load_instructions) 1112 1113 # Add exception handling to the method acquisition instructions where 1114 # the attribute access cannot be resolved at compile-time. 1115 1116 if not self._optimise_known_target(): 1117 self.load_builtin("AttributeError", node) 1118 self.new_op(CheckException()) 1119 self.new_op(JumpIfTrue(end_attempt_label)) 1120 1121 temp_method = self._optimise_temp_storage() 1122 1123 # Add arguments. 1124 # NOTE: No support for defaults. 1125 1126 self.new_op(temp1) # Explicit context as first argument. 1127 self.new_op(temp2) 1128 self._doCallFunc(temp_method) 1129 self._endCallFunc(temp_method) 1130 1131 # Test for NotImplemented. 1132 # Don't actually raise an exception. 1133 1134 self.new_op(TestIdentityAddress(self.get_builtin("NotImplemented", node))) 1135 self.new_op(JumpIfTrue(next_method_label)) 1136 self.new_op(Jump(end_label)) 1137 1138 # End method attempt. 1139 1140 self.set_label(end_attempt_label) 1141 self._endCallFunc() # From the left method call. 1142 1143 def _visitSequence(self, sequence_type, node): 1144 self.new_op(MakeObject((sequence_type, len(node.nodes)))) 1145 temp = self.get_temp() 1146 1147 for i, n in enumerate(node.nodes): 1148 self.dispatch(n) 1149 self.record_value() 1150 self.new_op(temp) 1151 self.new_op(StoreAttr(Attr(i, None, None, None))) 1152 self.set_source() 1153 self.discard_value() 1154 1155 self.new_op(temp) 1156 self.discard_temp(temp) 1157 1158 # Concrete visitor methods. 1159 1160 def visitAdd(self, node): 1161 self._visitBinary(node, "__add__", "__radd__") 1162 1163 def visitAnd(self, node): 1164 next_label = self.new_label() 1165 1166 for n in node.nodes[:-1]: 1167 self.dispatch(n) 1168 self.new_op(TestBoolean()) 1169 self.new_op(JumpIfFalse(next_label)) 1170 1171 self.dispatch(node.nodes[-1]) 1172 self.set_label(next_label) 1173 1174 # Prevent incorrect optimisation. 1175 1176 self.active = None 1177 1178 def visitAssert(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Assert") 1179 1180 def visitAssign(self, node): 1181 self.dispatch(node.expr) 1182 self.record_value() 1183 1184 for n in node.nodes: 1185 self.dispatch(n) 1186 1187 self.discard_value() 1188 1189 def visitAssAttr(self, node): 1190 self._visitAttr(node, self.attribute_store_instructions) 1191 self.set_source() 1192 1193 def visitAssList(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "AssList") 1194 1195 def visitAssName(self, node): 1196 self._visitName(node, self.name_store_instructions) 1197 self.set_source() 1198 1199 visitAssTuple = visitAssList 1200 1201 def visitAugAssign(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "AugAssign") 1202 1203 def visitBackquote(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Backquote") 1204 1205 def visitBitand(self, node): 1206 self._visitBinary(node, "__and__", "__rand__") 1207 1208 def visitBitor(self, node): 1209 self._visitBinary(node, "__or__", "__ror__") 1210 1211 def visitBitxor(self, node): 1212 self._visitBinary(node, "__xor__", "__rxor__") 1213 1214 def visitBreak(self, node): 1215 next_label, exit_label = self.get_loop_labels() 1216 self.new_op(Jump(exit_label)) 1217 1218 def visitCallFunc(self, node): 1219 1220 """ 1221 Evaluate positional arguments, evaluate and store keyword arguments in 1222 the correct location, then invoke the function. 1223 """ 1224 1225 # Mark the frame, evaluate the target, generate the call. 1226 1227 self._startCallFunc() 1228 self.dispatch(node.node) 1229 temp = self._generateCallFunc(node.args, node) 1230 self._doCallFunc(temp) 1231 self._endCallFunc(temp) 1232 1233 def visitClass(self, node): 1234 1235 # Store the name. 1236 1237 self.new_op(LoadConst(node.unit)) 1238 self.record_value() 1239 self._visitName(node, self.name_store_instructions) 1240 self.set_source() 1241 self.discard_value() 1242 1243 # Visit the code. 1244 1245 unit = self.unit 1246 self.unit = node.unit 1247 self.unit.code_location = self.module.code_location # class body code is not independently addressable 1248 self.dispatch(node.code) 1249 self.unit = unit 1250 1251 def visitCompare(self, node): 1252 1253 """ 1254 _t1 = node.expr 1255 _t1 op1 _t2 and _t2 op2 _t3 and ... 1256 """ 1257 1258 end_label = self.new_label() 1259 1260 self.dispatch(node.expr) 1261 temp2 = self._optimise_temp_storage() 1262 1263 for op_name, next_node in compare.ops: 1264 left_method, right_method = self.comparison_methods[op_name] 1265 1266 temp1 = temp2 1267 self.dispatch(next_node) 1268 temp2 = self._optimise_temp_storage() 1269 1270 if methods is not None: 1271 1272 # Generate method call using evaluated argument and next node. 1273 1274 self._generateBinary(temp1, temp2, left_method, right_method) 1275 1276 # Test the result and jump to the end label if false. 1277 1278 self.new_op(LoadResult()) 1279 self.new_op(TestBoolean()) 1280 self.new_op(JumpIfFalse(end_label)) 1281 1282 else: 1283 # NOTE: Deal with the special operators. 1284 1285 pass 1286 1287 # Compilation duties... 1288 1289 self.discard_temp(temp1) 1290 1291 self.discard_temp(temp2) 1292 self.set_label(end_label) 1293 1294 def visitConst(self, node): 1295 const = self.module.constant_values[node.value] 1296 self.new_op(LoadConst(const)) 1297 1298 def visitContinue(self, node): 1299 next_label, exit_label = self.get_loop_labels() 1300 self.new_op(Jump(next_label)) 1301 1302 def visitDecorators(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Decorators") 1303 1304 def visitDict(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Dict") 1305 1306 def visitDiscard(self, node): 1307 self.dispatch(node.expr) 1308 self._optimise_unused_results() 1309 1310 def visitDiv(self, node): 1311 self._visitBinary(node, "__div__", "__rdiv__") 1312 1313 def visitEllipsis(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Ellipsis") 1314 1315 def visitExec(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Exec") 1316 1317 def visitExpression(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Expression") 1318 1319 def visitFloorDiv(self, node): 1320 self._visitBinary(node, "__floordiv__", "__rfloordiv__") 1321 1322 def visitFor(self, node): 1323 exit_label = self.new_label() 1324 next_label = self.new_label() 1325 else_label = self.new_label() 1326 1327 # Get the "list" to be iterated over, obtain its iterator. 1328 1329 self._startCallFunc() 1330 self.dispatch(node.list) 1331 self._generateAttr(node, "__iter__", self.attribute_load_instructions) 1332 temp = self._generateCallFunc([], node) 1333 self._doCallFunc(temp) 1334 self._endCallFunc(temp) 1335 1336 temp_iterator = self._optimise_temp_storage() 1337 1338 # In the loop... 1339 1340 self.set_label(next_label) 1341 1342 # Use the iterator to get the next value. 1343 1344 self._startCallFunc() 1345 self.new_op(temp_iterator) 1346 self._generateAttr(node, "next", self.attribute_load_instructions) 1347 temp = self._generateCallFunc([], node) 1348 self._doCallFunc(temp) 1349 self._endCallFunc(temp) 1350 1351 # Test for StopIteration. 1352 1353 self.load_builtin("StopIteration", node) 1354 self.new_op(CheckException()) 1355 if node.else_ is not None: 1356 self.new_op(JumpIfTrue(else_label)) 1357 else: 1358 self.new_op(JumpIfTrue(exit_label)) 1359 1360 # Assign to the target. 1361 1362 self.dispatch(node.assign) 1363 1364 # Process the body with the current next and exit points. 1365 1366 self.add_loop_labels(next_label, exit_label) 1367 self.dispatch(node.body) 1368 self.drop_loop_labels() 1369 1370 # Repeat the loop. 1371 1372 self.new_op(Jump(next_label)) 1373 1374 # Produce the "else" section. 1375 1376 if node.else_ is not None: 1377 self.set_label(exit_label) 1378 self.dispatch(node.else_) 1379 1380 # After the loop... 1381 1382 self.set_label(exit_label) 1383 1384 # Compilation duties... 1385 1386 self.discard_temp(temp_iterator) 1387 1388 def visitFrom(self, node): pass 1389 1390 def visitFunction(self, node): 1391 1392 # Only store the name when visiting this node from outside. 1393 1394 if self.unit is not node.unit: 1395 self.new_op(LoadConst(node.unit)) 1396 1397 self.record_value() 1398 self._visitName(node, self.name_store_instructions) # AssName equivalent 1399 self.set_source() 1400 self.discard_value() 1401 1402 self._generateFunctionDefaults(node.unit) 1403 1404 # Visiting of the code occurs when get_code is invoked on this node. 1405 1406 else: 1407 self.dispatch(node.code) 1408 if not isinstance(self.last_op(), Return): 1409 self.dispatch(compiler.ast.Name("None")) 1410 self.new_op(StoreResult()) 1411 1412 self.new_op(Return()) 1413 1414 def visitGenExpr(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "GenExpr") 1415 1416 def visitGenExprFor(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "GenExprFor") 1417 1418 def visitGenExprIf(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "GenExprIf") 1419 1420 def visitGenExprInner(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "GenExprInner") 1421 1422 def visitGetattr(self, node): 1423 self._visitAttr(node, self.attribute_load_instructions) 1424 1425 def visitGlobal(self, node): pass 1426 1427 def visitIf(self, node): 1428 first = 1 1429 exit_label = self.new_label() 1430 1431 clauses = node.tests + [(None, node.else_)] 1432 last_clause = clauses[-1] 1433 1434 for clause in clauses: 1435 test, body = clause 1436 if body is None: 1437 break 1438 if not first: 1439 self.set_label(next_label) 1440 if test is not None: 1441 self.dispatch(test) 1442 next_label = self.new_label() 1443 self.new_op(JumpIfFalse(next_label)) 1444 self.dispatch(body) 1445 if clause is not last_clause: 1446 self.new_op(Jump(exit_label)) 1447 first = 0 1448 1449 self.set_label(exit_label) 1450 1451 def visitImport(self, node): pass 1452 1453 def visitInvert(self, node): 1454 self._visitUnary(node, "__invert__") 1455 1456 def visitKeyword(self, node): pass 1457 1458 def visitLambda(self, node): 1459 1460 """ 1461 Lambda functions can be represented as globally defined functions 1462 provided they do not define any default parameter values, since these 1463 may defined in a non-global scope. 1464 1465 Where defaults are defined, an object must be created and its content 1466 defined: the callable member of the object's structure must be set to 1467 the lambda function definition; each default must be attached to the 1468 object as an attribute, as is the case with normal functions and 1469 methods. 1470 """ 1471 1472 # Produce the reference to this function when visiting this node from 1473 # outside. 1474 1475 if self.unit is not node.unit: 1476 temp = self._generateFunctionDefaults(node.unit) 1477 self.new_op(LoadConst(node.unit)) 1478 1479 # Populate the new object required for the function. 1480 1481 if temp is not None: 1482 self.record_value() 1483 self.new_op(temp) 1484 self.new_op(StoreCallable()) 1485 self.set_source() 1486 self.discard_value() 1487 1488 self.new_op(temp) 1489 self.discard_temp(temp) 1490 1491 # Visiting of the code occurs when get_code is invoked on this node. 1492 1493 else: 1494 self.dispatch(node.code) 1495 self.new_op(StoreResult()) 1496 self.new_op(Return()) 1497 1498 def visitLeftShift(self, node): 1499 self._visitBinary(node, "__lshift__", "__rlshift__") 1500 1501 def visitList(self, node): 1502 self._visitSequence("list", node) 1503 1504 def visitListComp(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "ListComp") 1505 1506 def visitListCompFor(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "ListCompFor") 1507 1508 def visitListCompIf(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "ListCompIf") 1509 1510 def visitMod(self, node): 1511 self._visitBinary(node, "__mod__", "__rmod__") 1512 1513 def visitModule(self, node): 1514 self.dispatch(node.node) 1515 1516 def visitMul(self, node): 1517 self._visitBinary(node, "__mul__", "__rmul__") 1518 1519 def visitName(self, node): 1520 if node.name == "None": 1521 const = self.module.constant_values[None] 1522 self.new_op(LoadConst(const)) 1523 else: 1524 self._visitName(node, self.name_load_instructions) 1525 1526 def visitNot(self, node): 1527 next_label = self.new_label() 1528 true_label = self.new_label() 1529 1530 self.dispatch(node.expr) 1531 self.new_op(TestBoolean()) 1532 self.new_op(JumpIfTrue(true_label)) 1533 self.load_builtin("True", node) 1534 self.new_op(Jump(next_label)) 1535 1536 self.set_label(true_label) 1537 self.load_builtin("False", node) 1538 self.set_label(next_label) 1539 1540 # Prevent incorrect optimisation. 1541 1542 self.active = None 1543 1544 def visitOr(self, node): 1545 next_label = self.new_label() 1546 1547 for n in node.nodes[:-1]: 1548 self.dispatch(n) 1549 self.new_op(TestBoolean()) 1550 self.new_op(JumpIfTrue(next_label)) 1551 1552 self.dispatch(node.nodes[-1]) 1553 self.set_label(next_label) 1554 1555 # Prevent incorrect optimisation. 1556 1557 self.active = None 1558 1559 def visitPass(self, node): pass 1560 1561 def visitPower(self, node): 1562 self._visitBinary(node, "__pow__", "__rpow__") 1563 1564 def visitPrint(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Print") 1565 1566 def visitPrintnl(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Printnl") 1567 1568 def visitRaise(self, node): 1569 # NOTE: expr1 only => instance provided 1570 self.dispatch(node.expr1) 1571 1572 if node.expr2 is not None: 1573 temp = self._optimise_temp_storage() 1574 1575 self.dispatch(node.expr2) 1576 temp_arg = self._optimise_temp_storage() 1577 1578 self._startCallFunc() 1579 self.new_op(temp_arg) 1580 self.new_op(StoreFrame(0)) 1581 self._doCallFunc(temp) 1582 self._endCallFunc(temp) 1583 1584 self.discard_temp(temp_arg) 1585 1586 self.new_op(StoreException()) 1587 self.new_op(RaiseException()) 1588 1589 def visitReturn(self, node): 1590 if node.value is not None: 1591 self.dispatch(node.value) 1592 else: 1593 self.dispatch(compiler.ast.Name("None")) 1594 1595 self.new_op(StoreResult()) 1596 self.new_op(Return()) 1597 1598 def visitRightShift(self, node): 1599 self._visitBinary(node, "__rshift__", "__rrshift__") 1600 1601 def visitSlice(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Slice") 1602 1603 def visitStmt(self, node): 1604 for n in node.nodes: 1605 self.dispatch(n) 1606 1607 def visitSub(self, node): 1608 self._visitBinary(node, "__sub__", "__rsub__") 1609 1610 def visitSubscript(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Subscript") 1611 1612 def visitTryExcept(self, node): 1613 exit_label = self.new_label() 1614 success_label = self.new_label() 1615 handler_label = self.new_label() 1616 1617 self.add_exception_labels(handler_label, exit_label) 1618 1619 # Try... 1620 # Produce the code, then jump to the exit. 1621 1622 self.new_op(PushHandler(handler_label)) 1623 self.dispatch(node.body) 1624 self.new_op(PopHandler()) 1625 self.new_op(Jump(exit_label)) 1626 1627 # Start of handlers. 1628 1629 self.set_label(handler_label) 1630 self.new_op(PopHandler()) 1631 1632 for name, assignment, handler in node.handlers: 1633 next_label = self.new_label() 1634 1635 # Test the given exception against the current exception. 1636 1637 if name is not None: 1638 self.dispatch(name) 1639 self.new_op(CheckException()) 1640 self.new_op(JumpIfFalse(next_label)) 1641 1642 # Handle assignment to exception variable. 1643 1644 if assignment is not None: 1645 self.dispatch(assignment) 1646 1647 # Produce the handler code, then jump to the exit. 1648 1649 self.dispatch(handler) 1650 self.new_op(Jump(exit_label)) 1651 1652 self.set_label(next_label) 1653 1654 # Unhandled exceptions. 1655 1656 #self.new_op(LoadException()) 1657 self.new_op(RaiseException()) 1658 1659 # Optional else clause. 1660 1661 if node.else_ is not None: 1662 self.dispatch(node.else_) 1663 1664 self.set_label(exit_label) 1665 self.drop_exception_labels() 1666 1667 def visitTryFinally(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "TryFinally") 1668 1669 def visitTuple(self, node): 1670 self._visitSequence("tuple", node) 1671 1672 def visitUnaryAdd(self, node): 1673 self._visitUnary(node, "__pos__") 1674 1675 def visitUnarySub(self, node): 1676 self._visitUnary(node, "__neg__") 1677 1678 def visitWhile(self, node): 1679 exit_label = self.new_label() 1680 next_label = self.new_label() 1681 else_label = self.new_label() 1682 1683 self.set_label(next_label) 1684 self.dispatch(node.test) 1685 if node.else_ is not None: 1686 self.new_op(JumpIfFalse(else_label)) 1687 else: 1688 self.new_op(JumpIfFalse(exit_label)) 1689 1690 self.add_loop_labels(next_label, exit_label) 1691 1692 self.dispatch(node.body) 1693 self.new_op(Jump(next_label)) 1694 1695 if node.else_ is not None: 1696 self.set_label(else_label) 1697 self.dispatch(node.else_) 1698 1699 self.set_label(exit_label) 1700 self.drop_loop_labels() 1701 1702 # Prevent incorrect optimisation. 1703 1704 self.active = None 1705 1706 def visitWith(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "With") 1707 1708 def visitYield(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Yield") 1709 1710 # Useful data. 1711 1712 comparison_methods = { 1713 "==" : ("__eq__", "__ne__"), 1714 "!=" : ("__ne__", "__eq__"), 1715 "<" : ("__lt__", "__gt__"), 1716 "<=" : ("__le__", "__ge__"), 1717 ">=" : ("__ge__", "__le__"), 1718 ">" : ("__gt__", "__lt__"), 1719 "is" : None, 1720 "is not" : None, 1721 "in" : None, 1722 "not in" : None 1723 } 1724 1725 # vim: tabstop=4 expandtab shiftwidth=4