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