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