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