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