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.last_op() 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._startCallFunc() 1253 self.new_op(temp1) 1254 1255 # Get method on temp1. 1256 1257 self._generateAttr(node, method_name, self.attribute_load_instructions) 1258 temp_method = self._optimise_temp_storage() 1259 1260 self._handleAttributeError(node, end_attempt_label) 1261 1262 # Add arguments. 1263 # NOTE: No support for defaults. 1264 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 self._endCallFunc(load_result=0) # From the method call. 1284 1285 def _handleAttributeError(self, node, end_call_label): 1286 1287 """ 1288 Add exception handling to the method acquisition instructions where the 1289 attribute access cannot be resolved at compile-time. 1290 """ 1291 1292 if not self._optimise_known_target(): 1293 self.load_builtin("AttributeError", node) 1294 self.new_op(CheckException()) 1295 self.new_op(JumpIfTrue(end_call_label)) 1296 1297 def _generateSequence(self, sequence_type, node): 1298 1299 "Make a sequence of 'sequence_type' for the given program 'node'." 1300 1301 self.new_op(MakeObject((sequence_type, len(node.nodes)))) 1302 temp = self.get_temp() 1303 1304 for i, n in enumerate(node.nodes): 1305 self.dispatch(n) 1306 self.record_value() 1307 self.new_op(temp) 1308 self.new_op(StoreAttr(Attr(i, None, None, None))) 1309 self.set_source() 1310 self.discard_value() 1311 1312 self.new_op(temp) 1313 self.discard_temp(temp) 1314 1315 def _generateTestBoolean(self, node, temp): 1316 1317 """ 1318 Generate a test of the boolean status of the current value for the given 1319 program 'node'. 1320 """ 1321 1322 # Get method on temp. 1323 # NOTE: Using __bool__ instead of __nonzero__. 1324 1325 self._generateAttr(node, "__bool__", self.attribute_load_instructions) 1326 temp_method = self._optimise_temp_storage() 1327 1328 self._startCallFunc() 1329 self.new_op(temp) 1330 self.new_op(StoreFrame(0)) 1331 self._endCallFuncArgs(1) 1332 self._doCallFunc(temp_method) 1333 self._endCallFunc(temp_method) 1334 1335 self.discard_temp(temp_method) 1336 1337 # Convert result to boolean (a StoreBoolean operation). 1338 1339 self.new_op(TestIdentityAddress(self.get_builtin("True", node))) 1340 1341 def _generateLoadBoolean(self, node): 1342 1343 """ 1344 Generate instructions to load the appropriate value given the current 1345 boolean status. 1346 """ 1347 1348 true_label = self.new_label() 1349 end_label = self.new_label() 1350 1351 self.new_op(JumpIfTrue(true_label)) 1352 self.load_builtin("False", node) 1353 self.new_op(Jump(end_label)) 1354 1355 self.set_label(true_label) 1356 self.load_builtin("True", node) 1357 1358 self.set_label(end_label) 1359 1360 # Concrete visitor methods. 1361 1362 def visitAdd(self, node): 1363 self._visitBinary(node, "__add__", "__radd__") 1364 1365 def visitAnd(self, node): 1366 end_label = self.new_label() 1367 temp_pos = self.reserve_temp() 1368 temp = LoadTemp(temp_pos) 1369 1370 for n in node.nodes[:-1]: 1371 self.dispatch(n) 1372 self.new_op(StoreTemp(temp_pos)) 1373 1374 self._generateTestBoolean(n, temp) 1375 self.new_op(JumpIfFalse(end_label)) 1376 1377 self.dispatch(node.nodes[-1]) 1378 self.new_op(StoreTemp(temp_pos)) 1379 1380 self.set_label(end_label) 1381 1382 # Prevent incorrect optimisation. 1383 1384 self.clear_active() 1385 1386 self.new_op(temp) 1387 self.discard_temp(temp) 1388 1389 def visitAssert(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Assert") 1390 1391 def visitAssign(self, node): 1392 self.dispatch(node.expr) 1393 self.record_value() 1394 1395 for n in node.nodes: 1396 self.dispatch(n) 1397 1398 self.discard_value() 1399 1400 def visitAssAttr(self, node): 1401 self._visitAttr(node, self.attribute_store_instructions) 1402 self.set_source() 1403 1404 def visitAssList(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "AssList") 1405 1406 def visitAssName(self, node): 1407 self._visitName(node, self.name_store_instructions) 1408 self.set_source() 1409 1410 visitAssTuple = visitAssList 1411 1412 def visitAugAssign(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "AugAssign") 1413 1414 def visitBackquote(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Backquote") 1415 1416 def visitBitand(self, node): 1417 self._visitBinary(node, "__and__", "__rand__") 1418 1419 def visitBitor(self, node): 1420 self._visitBinary(node, "__or__", "__ror__") 1421 1422 def visitBitxor(self, node): 1423 self._visitBinary(node, "__xor__", "__rxor__") 1424 1425 def visitBreak(self, node): 1426 next_label, exit_label = self.get_loop_labels() 1427 self.new_op(Jump(exit_label)) 1428 1429 def visitCallFunc(self, node): 1430 1431 """ 1432 Evaluate positional arguments, evaluate and store keyword arguments in 1433 the correct location, then invoke the function. 1434 """ 1435 1436 # Mark the frame, evaluate the target, generate the call. 1437 1438 self._startCallFunc() 1439 self.dispatch(node.node) 1440 temp = self._generateCallFunc(node.args, node) 1441 self._doCallFunc(temp) 1442 self._endCallFunc(temp) 1443 1444 def visitClass(self, node): 1445 1446 # Store the name. 1447 1448 self.new_op(LoadConst(node.unit)) 1449 self.record_value() 1450 self._visitName(node, self.name_store_instructions) 1451 self.set_source() 1452 self.discard_value() 1453 1454 # Visit the code. 1455 1456 unit = self.unit 1457 self.unit = node.unit 1458 self.unit.code_location = self.module.code_location # class body code is not independently addressable 1459 self.dispatch(node.code) 1460 self.unit = unit 1461 1462 def visitCompare(self, node): 1463 1464 """ 1465 _t1 = node.expr 1466 _t1 op1 _t2 and _t2 op2 _t3 and ... 1467 """ 1468 1469 end_label = self.new_label() 1470 temp_pos = self.reserve_temp() 1471 temp_result = LoadTemp(temp_pos) 1472 1473 self.dispatch(node.expr) 1474 temp2 = self._optimise_temp_storage() 1475 1476 last_op = node.ops[-1] 1477 1478 for op in node.ops: 1479 op_name, next_node = op 1480 methods = self.comparison_methods[op_name] 1481 1482 temp1 = temp2 1483 self.dispatch(next_node) 1484 temp2 = self._optimise_temp_storage() 1485 1486 # Use the appropriate mechanism, setting the boolean status for the 1487 # comparison. 1488 1489 if methods is not None: 1490 left_method, right_method = methods 1491 1492 # Generate method call using evaluated argument and next node. 1493 1494 self._generateBinary(node, temp1, temp2, left_method, right_method) 1495 self.new_op(StoreTemp(temp_pos)) 1496 self._generateTestBoolean(node, temp_result) 1497 1498 else: 1499 # Deal with the special operators. 1500 1501 if op_name.startswith("is"): 1502 self.new_op(temp1) 1503 self.record_value() 1504 self.new_op(temp2) 1505 self.new_op(TestIdentity()) 1506 self.set_source() 1507 self.discard_value() 1508 1509 elif op_name.endswith("in"): 1510 self._startCallFunc() 1511 self.new_op(temp2) 1512 1513 # Get method on temp2. 1514 1515 self._generateAttr(node, "__contains__", self.attribute_load_instructions) 1516 temp_method = self._optimise_temp_storage() 1517 1518 # Add arguments. 1519 # NOTE: No support for defaults. 1520 1521 self.new_op(temp2) 1522 self.new_op(StoreFrame(0)) 1523 self.new_op(temp1) 1524 self.new_op(StoreFrame(1)) 1525 self._endCallFuncArgs(2) 1526 self._doCallFunc(temp_method) 1527 self._endCallFunc(temp_method) 1528 1529 self.new_op(StoreTemp(temp_pos)) 1530 self._generateTestBoolean(node, temp_result) 1531 1532 if op_name.find("not") != -1: 1533 self.new_op(InvertBoolean()) 1534 1535 # Test the result and jump to the end label if false. 1536 1537 if op is not last_op: 1538 self.new_op(JumpIfFalse(end_label)) 1539 1540 # Compilation duties... 1541 1542 self.discard_temp(temp1) 1543 1544 self.discard_temp(temp2) 1545 self.discard_temp(temp_result) 1546 self.set_label(end_label) 1547 1548 # Yield the appropriate value. 1549 1550 self._generateLoadBoolean(node) 1551 1552 def visitConst(self, node): 1553 const = self.module.constant_values[node.value] 1554 self.new_op(LoadConst(const)) 1555 1556 def visitContinue(self, node): 1557 next_label, exit_label = self.get_loop_labels() 1558 self.new_op(Jump(next_label)) 1559 1560 def visitDecorators(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Decorators") 1561 1562 def visitDict(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Dict") 1563 1564 def visitDiscard(self, node): 1565 self.dispatch(node.expr) 1566 self._optimise_unused_results() 1567 1568 def visitDiv(self, node): 1569 self._visitBinary(node, "__div__", "__rdiv__") 1570 1571 def visitEllipsis(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Ellipsis") 1572 1573 def visitExec(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Exec") 1574 1575 def visitExpression(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Expression") 1576 1577 def visitFloorDiv(self, node): 1578 self._visitBinary(node, "__floordiv__", "__rfloordiv__") 1579 1580 def visitFor(self, node): 1581 exit_label = self.new_label() 1582 next_label = self.new_label() 1583 else_label = self.new_label() 1584 1585 # Get the "list" to be iterated over, obtain its iterator. 1586 1587 self._startCallFunc() 1588 self.dispatch(node.list) 1589 self._generateAttr(node, "__iter__", self.attribute_load_instructions) 1590 temp = self._generateCallFunc([], node) 1591 self._doCallFunc(temp) 1592 self._endCallFunc(temp) 1593 1594 temp_iterator = self._optimise_temp_storage() 1595 1596 # In the loop... 1597 1598 self.set_label(next_label) 1599 1600 # Use the iterator to get the next value. 1601 1602 self._startCallFunc() 1603 self.new_op(temp_iterator) 1604 self._generateAttr(node, "next", self.attribute_load_instructions) 1605 temp = self._generateCallFunc([], node) 1606 self._doCallFunc(temp) 1607 self._endCallFunc(temp) 1608 1609 # Test for StopIteration. 1610 1611 self.load_builtin("StopIteration", node) 1612 self.new_op(CheckException()) 1613 if node.else_ is not None: 1614 self.new_op(JumpIfTrue(else_label)) 1615 else: 1616 self.new_op(JumpIfTrue(exit_label)) 1617 1618 # Assign to the target. 1619 1620 self.dispatch(node.assign) 1621 1622 # Process the body with the current next and exit points. 1623 1624 self.add_loop_labels(next_label, exit_label) 1625 self.dispatch(node.body) 1626 self.drop_loop_labels() 1627 1628 # Repeat the loop. 1629 1630 self.new_op(Jump(next_label)) 1631 1632 # Produce the "else" section. 1633 1634 if node.else_ is not None: 1635 self.set_label(exit_label) 1636 self.dispatch(node.else_) 1637 1638 # After the loop... 1639 1640 self.set_label(exit_label) 1641 1642 # Compilation duties... 1643 1644 self.discard_temp(temp_iterator) 1645 1646 def visitFrom(self, node): pass 1647 1648 def visitFunction(self, node): 1649 1650 # Only store the name when visiting this node from outside. 1651 1652 if self.unit is not node.unit: 1653 self.new_op(LoadConst(node.unit)) 1654 1655 self.record_value() 1656 self._visitName(node, self.name_store_instructions) # AssName equivalent 1657 self.set_source() 1658 self.discard_value() 1659 1660 self._generateFunctionDefaults(node.unit) 1661 1662 # Visiting of the code occurs when get_code is invoked on this node. 1663 1664 else: 1665 self.dispatch(node.code) 1666 if not isinstance(self.last_op(), Return): 1667 self.dispatch(compiler.ast.Name("None")) 1668 self.new_op(StoreResult()) 1669 1670 self.new_op(Return()) 1671 1672 def visitGenExpr(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "GenExpr") 1673 1674 def visitGenExprFor(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "GenExprFor") 1675 1676 def visitGenExprIf(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "GenExprIf") 1677 1678 def visitGenExprInner(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "GenExprInner") 1679 1680 def visitGetattr(self, node): 1681 self._visitAttr(node, self.attribute_load_instructions) 1682 1683 def visitGlobal(self, node): pass 1684 1685 def visitIf(self, node): 1686 first = 1 1687 exit_label = self.new_label() 1688 1689 clauses = node.tests + [(None, node.else_)] 1690 last_clause = clauses[-1] 1691 1692 for clause in clauses: 1693 test, body = clause 1694 if body is None: 1695 break 1696 if not first: 1697 self.set_label(next_label) 1698 if test is not None: 1699 self.dispatch(test) 1700 next_label = self.new_label() 1701 self.new_op(JumpIfFalse(next_label)) 1702 self.dispatch(body) 1703 if clause is not last_clause: 1704 self.new_op(Jump(exit_label)) 1705 first = 0 1706 1707 self.set_label(exit_label) 1708 1709 def visitImport(self, node): pass 1710 1711 def visitInvert(self, node): 1712 self._visitUnary(node, "__invert__") 1713 1714 def visitKeyword(self, node): pass 1715 1716 def visitLambda(self, node): 1717 1718 """ 1719 Lambda functions can be represented as globally defined functions 1720 provided they do not define any default parameter values, since these 1721 may defined in a non-global scope. 1722 1723 Where defaults are defined, an object must be created and its content 1724 defined: the callable member of the object's structure must be set to 1725 the lambda function definition; each default must be attached to the 1726 object as an attribute, as is the case with normal functions and 1727 methods. 1728 """ 1729 1730 # Produce the reference to this function when visiting this node from 1731 # outside. 1732 1733 if self.unit is not node.unit: 1734 temp = self._generateFunctionDefaults(node.unit) 1735 self.new_op(LoadConst(node.unit)) 1736 1737 # Populate the new object required for the function. 1738 1739 if temp is not None: 1740 self.record_value() 1741 self.new_op(temp) 1742 self.new_op(StoreCallable()) 1743 self.set_source() 1744 self.discard_value() 1745 1746 self.new_op(temp) 1747 #self.discard_temp(temp) 1748 1749 # Visiting of the code occurs when get_code is invoked on this node. 1750 1751 else: 1752 self.dispatch(node.code) 1753 self.new_op(StoreResult()) 1754 self.new_op(Return()) 1755 1756 def visitLeftShift(self, node): 1757 self._visitBinary(node, "__lshift__", "__rlshift__") 1758 1759 def visitList(self, node): 1760 self._generateSequence("list", node) 1761 1762 def visitListComp(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "ListComp") 1763 1764 def visitListCompFor(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "ListCompFor") 1765 1766 def visitListCompIf(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "ListCompIf") 1767 1768 def visitMod(self, node): 1769 self._visitBinary(node, "__mod__", "__rmod__") 1770 1771 def visitModule(self, node): 1772 self.dispatch(node.node) 1773 1774 def visitMul(self, node): 1775 self._visitBinary(node, "__mul__", "__rmul__") 1776 1777 def visitName(self, node): 1778 if node.name == "None": 1779 const = self.module.constant_values[None] 1780 self.new_op(LoadConst(const)) 1781 else: 1782 self._visitName(node, self.name_load_instructions) 1783 1784 def visitNot(self, node): 1785 self.dispatch(node.expr) 1786 1787 temp = self._optimise_temp_storage() 1788 self._generateTestBoolean(node.expr, temp) 1789 self.discard_temp(temp) 1790 1791 self.new_op(InvertBoolean()) 1792 self._generateLoadBoolean(node) 1793 1794 # Prevent incorrect optimisation. 1795 1796 self.clear_active() 1797 1798 def visitOr(self, node): 1799 end_label = self.new_label() 1800 temp_pos = self.reserve_temp() 1801 temp = LoadTemp(temp_pos) 1802 1803 for n in node.nodes[:-1]: 1804 self.dispatch(n) 1805 self.new_op(StoreTemp(temp_pos)) 1806 1807 self._generateTestBoolean(n, temp) 1808 self.new_op(JumpIfTrue(end_label)) 1809 1810 self.dispatch(node.nodes[-1]) 1811 self.new_op(StoreTemp(temp_pos)) 1812 1813 self.set_label(end_label) 1814 1815 # Prevent incorrect optimisation. 1816 1817 self.clear_active() 1818 1819 self.new_op(temp) 1820 self.discard_temp(temp) 1821 1822 def visitPass(self, node): pass 1823 1824 def visitPower(self, node): 1825 self._visitBinary(node, "__pow__", "__rpow__") 1826 1827 def visitPrint(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Print") 1828 1829 def visitPrintnl(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Printnl") 1830 1831 def visitRaise(self, node): 1832 # NOTE: expr1 only => instance provided 1833 self.dispatch(node.expr1) 1834 1835 if node.expr2 is not None: 1836 temp = self._optimise_temp_storage() 1837 1838 self.dispatch(node.expr2) 1839 temp_arg = self._optimise_temp_storage() 1840 1841 self._startCallFunc() 1842 self.new_op(temp_arg) 1843 self.new_op(StoreFrame(0)) 1844 self._endCallFuncArgs(1) 1845 self._doCallFunc(temp) 1846 self._endCallFunc(temp) 1847 1848 self.discard_temp(temp_arg) 1849 1850 self.new_op(StoreException()) 1851 self.new_op(RaiseException()) 1852 1853 def visitReturn(self, node): 1854 if node.value is not None: 1855 self.dispatch(node.value) 1856 else: 1857 self.dispatch(compiler.ast.Name("None")) 1858 1859 self.new_op(StoreResult()) 1860 self.new_op(Return()) 1861 1862 def visitRightShift(self, node): 1863 self._visitBinary(node, "__rshift__", "__rrshift__") 1864 1865 def visitSlice(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Slice") 1866 1867 def visitStmt(self, node): 1868 for n in node.nodes: 1869 self.dispatch(n) 1870 1871 def visitSub(self, node): 1872 self._visitBinary(node, "__sub__", "__rsub__") 1873 1874 def visitSubscript(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Subscript") 1875 1876 def visitTryExcept(self, node): 1877 exit_label = self.new_label() 1878 success_label = self.new_label() 1879 handler_label = self.new_label() 1880 1881 self.add_exception_labels(handler_label, exit_label) 1882 1883 # Try... 1884 # Produce the code, then jump to the exit. 1885 1886 self.new_op(PushHandler(handler_label)) 1887 self.dispatch(node.body) 1888 self.new_op(PopHandler()) 1889 self.new_op(Jump(exit_label)) 1890 1891 # Start of handlers. 1892 1893 self.set_label(handler_label) 1894 self.new_op(PopHandler()) 1895 1896 for name, assignment, handler in node.handlers: 1897 next_label = self.new_label() 1898 1899 # Test the given exception against the current exception. 1900 1901 if name is not None: 1902 self.dispatch(name) 1903 self.new_op(CheckException()) 1904 self.new_op(JumpIfFalse(next_label)) 1905 1906 # Handle assignment to exception variable. 1907 1908 if assignment is not None: 1909 self.dispatch(assignment) 1910 1911 # Produce the handler code, then jump to the exit. 1912 1913 self.dispatch(handler) 1914 self.new_op(Jump(exit_label)) 1915 1916 self.set_label(next_label) 1917 1918 # Unhandled exceptions. 1919 1920 #self.new_op(LoadException()) 1921 self.new_op(RaiseException()) 1922 1923 # Optional else clause. 1924 1925 if node.else_ is not None: 1926 self.dispatch(node.else_) 1927 1928 self.set_label(exit_label) 1929 self.drop_exception_labels() 1930 1931 def visitTryFinally(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "TryFinally") 1932 1933 def visitTuple(self, node): 1934 self._generateSequence("tuple", node) 1935 1936 def visitUnaryAdd(self, node): 1937 self._visitUnary(node, "__pos__") 1938 1939 def visitUnarySub(self, node): 1940 self._visitUnary(node, "__neg__") 1941 1942 def visitWhile(self, node): 1943 exit_label = self.new_label() 1944 next_label = self.new_label() 1945 else_label = self.new_label() 1946 1947 self.set_label(next_label) 1948 self.dispatch(node.test) 1949 if node.else_ is not None: 1950 self.new_op(JumpIfFalse(else_label)) 1951 else: 1952 self.new_op(JumpIfFalse(exit_label)) 1953 1954 self.add_loop_labels(next_label, exit_label) 1955 1956 self.dispatch(node.body) 1957 self.new_op(Jump(next_label)) 1958 1959 if node.else_ is not None: 1960 self.set_label(else_label) 1961 self.dispatch(node.else_) 1962 1963 self.set_label(exit_label) 1964 self.drop_loop_labels() 1965 1966 # Prevent incorrect optimisation. 1967 1968 self.clear_active() 1969 1970 def visitWith(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "With") 1971 1972 def visitYield(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Yield") 1973 1974 # Useful data. 1975 1976 comparison_methods = { 1977 "==" : ("__eq__", "__ne__"), 1978 "!=" : ("__ne__", "__eq__"), 1979 "<" : ("__lt__", "__gt__"), 1980 "<=" : ("__le__", "__ge__"), 1981 ">=" : ("__ge__", "__le__"), 1982 ">" : ("__gt__", "__lt__"), 1983 "is" : None, 1984 "is not" : None, 1985 "in" : None, 1986 "not in" : None 1987 } 1988 1989 # vim: tabstop=4 expandtab shiftwidth=4