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