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