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): 46 47 """ 48 Initialise the translation with an inspected 'module' and the module 49 'importer'. 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, importer.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 if isinstance(target, Instance): # lambda object 628 target, context = None, None 629 else: 630 target, context = None, None 631 632 # Store the target in temporary storage for subsequent referencing. 633 # NOTE: This may not be appropriate for class invocations 634 # NOTE: (instantiation). 635 636 temp = self.optimiser.optimise_temp_storage() 637 638 # Where a target or context are not known or where an instance is known 639 # to be the context, load the context. 640 641 if target is None or isinstance(context, Instance): 642 self.new_op(temp) 643 self.new_op(LoadContext()) 644 self.new_op(StoreFrame(0)) 645 646 # For known instantiations, provide a new object as the first argument 647 # to the __init__ method. 648 649 elif isinstance(target, Class): 650 self.make_object(target, len(target.instance_attributes())) 651 self.new_op(StoreFrame(0)) 652 653 # Otherwise omit the context. 654 655 else: 656 pass # NOTE: Class methods should be supported. 657 658 return target, context, temp 659 660 def _generateCallFuncArgs(self, target, context, temp, args, node): 661 662 """ 663 Given invocation 'target' and 'context' information, the 'temp' 664 reference to the target, a list of nodes representing the 'args' 665 (arguments), generate instructions which load the arguments for the 666 invocation defined by the given 'node'. 667 """ 668 669 # Evaluate the arguments. 670 671 employed_positions = set() 672 employed_keywords = set() 673 extra_keywords = [] 674 675 # Find keyword arguments in advance in order to help resolve targets. 676 677 for arg in args: 678 if isinstance(arg, compiler.ast.Keyword): 679 employed_keywords.add(arg.name) 680 681 possible_targets = self.paramtable.all_possible_objects(employed_keywords) 682 683 # Note the presence of the context in the frame where appropriate. 684 685 if target is None or isinstance(context, Instance): 686 ncontext = 1 687 expect_context = 0 688 689 # Handle calls to classes. 690 691 elif isinstance(target, Class): 692 ncontext = 1 693 expect_context = 0 694 target = target.get_init_method() 695 696 # Method calls via classes. 697 698 elif isinstance(context, Class): 699 ncontext = 0 700 expect_context = 1 701 702 # Function calls. 703 704 else: 705 ncontext = 0 706 expect_context = 0 707 708 first = 1 709 frame_pos = ncontext 710 max_keyword_pos = -1 711 712 for arg in args: 713 714 # Handle positional and keyword arguments separately. 715 716 if isinstance(arg, compiler.ast.Keyword): 717 718 # Optimise where the target is known now. 719 720 if target is not None: 721 722 # Find the parameter table entry for the target. 723 724 target_name = target.full_name() 725 726 # Look for a callable with the precise target name. 727 728 table_entry = self.paramtable.table[target_name] 729 730 # Look the name up in the parameter table entry. 731 732 try: 733 pos = table_entry[arg.name] 734 735 # Where no position is found, this could be an extra keyword 736 # argument. 737 738 except KeyError: 739 extra_keywords.append(arg) 740 continue 741 742 # Test for illegal conditions. 743 744 if pos in employed_positions: 745 raise TranslateError(self.module.full_name(), node, 746 "Keyword argument %r overwrites parameter %r." % (arg.name, pos)) 747 748 employed_positions.add(pos) 749 750 # Generate code for the keyword and the positioning 751 # operation. 752 753 self.dispatch(arg.expr) 754 self.new_op(StoreFrame(pos)) 755 756 # Otherwise, generate the code needed to obtain the details of 757 # the parameter location. 758 759 else: 760 761 # Combine the target details with the name to get the location. 762 # See the access method on the List class. 763 764 try: 765 paramindex = self.paramtable.get_index(arg.name) 766 767 # Where no position is found, this could be an extra keyword 768 # argument. 769 770 except self.paramtable.TableError: 771 extra_keywords.append(arg) 772 continue 773 774 # Generate code for the keyword and the positioning 775 # operation. 776 777 self.dispatch(arg.expr) 778 self.new_op(StoreFrameIndex(paramindex)) 779 780 # use (callable+0)+paramindex+table 781 # checks embedded offset against (callable+0) 782 # moves the current value to frame+position 783 784 # Record the highest possible frame position for this argument. 785 786 max_keyword_pos = max(max_keyword_pos, max(self.paramtable.all_attribute_positions(arg.name))) 787 788 else: 789 self.dispatch(arg) 790 self.new_op(StoreFrame(frame_pos)) 791 792 employed_positions.add(frame_pos) 793 794 # Check to see if the first argument is appropriate (compatible with 795 # the target where methods are being invoked via classes). 796 797 if first and expect_context: 798 799 # Drop any test if the target and the context are known. 800 801 if not self.optimiser.have_correct_self_for_target(context, self.unit): 802 803 continue_block = self.new_block() 804 805 self.new_op(CheckSelf()) 806 self.optimiser.set_source(temp) 807 self.new_op(JumpIfTrue(continue_block)) 808 809 # Where the context is inappropriate, drop the incomplete frame and 810 # raise an exception. 811 812 self.new_op(DropFrame()) 813 self.new_op(LoadResult()) 814 815 self.load_builtin("TypeError", node) 816 self.new_op(StoreException()) 817 self.new_op(RaiseException()) 818 819 self.set_block(continue_block) 820 821 first = 0 822 frame_pos += 1 823 824 # NOTE: Extra keywords are not supported. 825 # NOTE: Somehow, the above needs to be combined with * arguments. 826 827 if extra_keywords: 828 print "Warning: extra keyword argument(s) %s not handled." % ", ".join([arg.name for arg in extra_keywords]) 829 830 # Either test for a complete set of arguments. 831 832 if target is not None: 833 834 # Make sure that enough arguments have been given. 835 836 nargs_max = len(target.positional_names) 837 ndefaults = len(target.defaults) 838 nargs_min = nargs_max - ndefaults 839 840 for i in range(ncontext, nargs_min): 841 if i not in employed_positions: 842 raise TranslateError(self.module.full_name(), node, 843 "Argument %r not supplied for %r: need at least %d argument(s)." % (i+1, target.name, nargs_min)) 844 845 nargs = frame_pos 846 847 if nargs > nargs_max and not target.has_star and not target.has_dstar: 848 raise TranslateError(self.module.full_name(), node, 849 "Too many arguments for %r: need at most %d argument(s)." % (target.name, nargs_max)) 850 851 # Where defaults are involved, put them into the frame. 852 853 self._generateCallFuncDefaultArgs(target, temp, nargs_min, nargs_max, employed_positions) 854 855 # Set the frame size. 856 857 self._endCallFuncArgs(nargs_max) 858 859 # Or generate instructions to do this at run-time. 860 # NOTE: CheckFrame has to check the number of arguments and to fill in 861 # NOTE: defaults; it also has to shift the invocation frame according to 862 # NOTE: the context in use. 863 864 else: 865 max_pos = max(max(employed_positions or [-1]), max_keyword_pos, frame_pos - 1) 866 867 # Only check non-empty frames (using the callable's details). 868 869 if employed_positions or max_pos >= 0: 870 self.new_op(temp) 871 self.new_op(CheckFrame(max_pos + 1)) 872 873 # Set the frame size. 874 875 self._endCallFuncArgs(max_pos + 1) 876 877 def _generateCallFuncDefaultArgs(self, target, temp, nargs_min, nargs_max, employed_positions): 878 879 """ 880 For the given 'target' and 'temp' reference to the target, generate 881 default arguments for those positions in the range 'nargs_min'... 882 'nargs_max' which are not present in the 'employed_positions' 883 collection. 884 """ 885 886 # Where a lambda is involved, construct a dynamic object to hold the 887 # defaults. 888 889 dynamic = target.name is None 890 891 # Here, we use negative index values to visit the right hand end of 892 # the defaults list. 893 894 for pos in range(nargs_min, nargs_max): 895 if pos not in employed_positions: 896 if dynamic: 897 self.new_op(temp) 898 self.new_op(LoadAttr(target.default_attrs[pos - nargs_min])) 899 else: 900 self.new_op(LoadAddress(target.default_attrs[pos - nargs_min])) 901 self.new_op(StoreFrame(pos)) 902 903 def _doCallFunc(self, instruction, target=None): 904 905 "Make the invocation." 906 907 if isinstance(target, Class): 908 self.new_op(LoadConst(target.get_init_method())) 909 else: 910 self.new_op(instruction) 911 self.new_op(LoadCallable()) 912 self.new_op(JumpWithFrame()) 913 914 def _endCallFuncArgs(self, nargs): 915 916 "Set the frame size." 917 918 self.frame_makers[-1].attr = nargs 919 self.frame_makers.pop() 920 921 def _endCallFunc(self, instruction=None, target=None, load_result=1): 922 923 "Finish the invocation and tidy up afterwards." 924 925 if isinstance(target, Class): 926 self.new_op(LoadName(target.get_init_method().all_locals()["self"])) # load the context in the invocation frame 927 self.new_op(StoreResult()) 928 self.new_op(DropFrame()) 929 if load_result: 930 self.new_op(LoadResult()) 931 932 # Discard any temporary storage instructions. 933 934 if instruction is not None: 935 self.discard_temp(instruction) 936 937 def _generateFunctionDefaults(self, function): 938 939 """ 940 Generate the default initialisation code for 'function', returning 941 a temporary storage reference if a dynamic object was created for the 942 function. 943 """ 944 945 attr_to_default = zip(function.default_attrs, function.defaults) 946 if not attr_to_default: 947 return None 948 949 # Where a lambda is involved, construct a dynamic object to hold the 950 # defaults. 951 952 dynamic = function.name is None 953 954 if dynamic: 955 self.make_object(self.get_builtin_class("function", function), len(attr_to_default)) 956 temp = self.get_temp() 957 958 for attr, default in attr_to_default: 959 self.dispatch(default) 960 961 self.record_value() 962 if dynamic: 963 self.new_op(temp) 964 self.new_op(StoreAttr(attr)) 965 else: 966 self.new_op(StoreAddress(attr)) 967 self.set_source() 968 self.discard_value() 969 970 if dynamic: 971 return temp 972 else: 973 return None 974 975 def _visitName(self, node, classes): 976 977 """ 978 Visit the name-related 'node', generating instructions based on the 979 given 'classes'. 980 """ 981 982 name = node.name 983 scope = self.get_scope(name) 984 #print self.module.name, node.lineno, name, scope 985 self._generateName(name, scope, classes, node) 986 987 def _generateName(self, name, scope, classes, node): 988 989 """ 990 Generate code for the access to 'name' in 'scope' using the given 991 'classes', and using the given 'node' as the source of the access. 992 """ 993 994 NameInstruction, AddressInstruction = classes 995 996 if scope == "local": 997 unit = self.unit 998 if isinstance(unit, Function): 999 self.new_op(NameInstruction(unit.all_locals()[name])) 1000 elif isinstance(unit, Class): 1001 self.new_op(AddressInstruction(unit.all_class_attributes()[name])) 1002 elif isinstance(unit, Module): 1003 self.new_op(AddressInstruction(unit.module_attributes()[name])) 1004 else: 1005 raise TranslateError(self.module.full_name(), node, "Program unit %r has no local %r." % (unit, name)) 1006 1007 elif scope == "global": 1008 globals = self.module.module_attributes() 1009 if globals.has_key(name): 1010 self.new_op(AddressInstruction(globals[name])) 1011 else: 1012 raise TranslateError(self.module.full_name(), node, "Module %r has no attribute %r." % (self.module, name)) 1013 1014 else: 1015 self.new_op(AddressInstruction(self.get_builtin(name, node))) 1016 1017 def _visitUnary(self, node, method): 1018 1019 """ 1020 _t = node.expr 1021 try: 1022 _result = _t.__pos__() 1023 except AttributeError: 1024 raise TypeError 1025 """ 1026 1027 type_error_block = self.new_block() 1028 end_block = self.new_block() 1029 1030 # Evaluate and store the operand in temporary storage. 1031 1032 self.dispatch(node.expr) 1033 temp = self.optimiser.optimise_temp_storage() 1034 1035 self.new_op(temp) 1036 1037 # Get the method on temp. 1038 1039 self._generateAttr(node, method, self.attribute_load_instructions) 1040 temp_method = self.optimiser.optimise_temp_storage() 1041 1042 self._handleAttributeError(node, type_error_block) 1043 1044 # Add arguments. 1045 # NOTE: No support for defaults. 1046 1047 self._startCallFunc() 1048 self.new_op(temp) # Explicit context as first argument. 1049 self.new_op(StoreFrame(0)) 1050 self._endCallFuncArgs(1) 1051 self._doCallFunc(temp_method) 1052 self._endCallFunc(temp_method) 1053 self.new_op(Jump(end_block)) 1054 1055 # Store the result. 1056 1057 temp_out = self.get_temp() 1058 1059 # Raise a TypeError. 1060 1061 self.set_block(type_error_block) 1062 self.load_builtin("TypeError", node) 1063 self.new_op(StoreException()) 1064 self.new_op(RaiseException()) 1065 1066 self.set_block(end_block) 1067 1068 # Produce the result. 1069 1070 self.new_op(temp_out) 1071 1072 # Compilation duties... 1073 1074 self.discard_temp(temp) 1075 self.discard_temp(temp_out) 1076 1077 def _visitBinary(self, node, left_method, right_method): 1078 1079 """ 1080 _t1 = node.left 1081 _t2 = node.right 1082 try: 1083 _result = _t1.__add__(_t2) 1084 if _result is NotImplemented: 1085 raise AttributeError 1086 except AttributeError: 1087 try: 1088 _result = _t2.__radd__(_t1) 1089 if _result is NotImplemented: 1090 raise AttributeError 1091 except AttributeError: 1092 raise TypeError 1093 """ 1094 1095 # Evaluate and store the left operand in temporary storage. 1096 1097 self.dispatch(node.left) 1098 temp1 = self.optimiser.optimise_temp_storage() 1099 1100 # Evaluate and store the right operand in temporary storage. 1101 1102 self.dispatch(node.right) 1103 temp2 = self.optimiser.optimise_temp_storage() 1104 1105 temp_out = self._generateBinary(node, temp1, temp2, left_method, right_method) 1106 1107 # Produce the result. 1108 1109 self.new_op(temp_out) 1110 1111 # Compilation duties... 1112 1113 self.discard_temp(temp1) 1114 self.discard_temp(temp2) 1115 self.discard_temp(temp_out) 1116 1117 def _generateBinary(self, node, temp1, temp2, left_method, right_method): 1118 1119 """ 1120 For the given 'node', generate the binary operator pattern for the 1121 operands 'temp1' and 'temp2', employing 'left_method' and 'right_method' 1122 as defined for binary operators, but also used in comparisons (for which 1123 this method is provided). 1124 1125 A temporary storage reference is returned from this method. 1126 """ 1127 1128 right_block = self.new_block() 1129 type_error_block = self.new_block() 1130 end_block = self.new_block() 1131 1132 # Left method. 1133 1134 temp_out = self._generateOpMethod(node, temp1, temp2, left_method, right_block, end_block) 1135 self.discard_temp(temp_out) # NOTE: Will re-use the same storage. 1136 1137 # Right method. 1138 1139 self.set_block(right_block) 1140 temp_out = self._generateOpMethod(node, temp2, temp1, right_method, type_error_block, end_block) 1141 1142 # Raise a TypeError. 1143 1144 self.set_block(type_error_block) 1145 self.load_builtin("TypeError", node) 1146 self.new_op(StoreException()) 1147 self.new_op(RaiseException()) 1148 1149 self.set_block(end_block) 1150 return temp_out 1151 1152 def _generateOpMethod(self, node, temp1, temp2, method_name, next_method_block, end_block): 1153 1154 """ 1155 For the given 'node', generate the operator method invocation using the 1156 operands 'temp1' and 'temp2', employing the given 'method_name', and 1157 jumping appropriately to 'next_method_block' where a NotImplemented 1158 result is returned, or to 'end_block' if the method call was successful. 1159 1160 A temporary storage reference is returned from this method. 1161 """ 1162 1163 end_attempt_block = self.new_block() 1164 1165 self.new_op(temp1) 1166 1167 # Get method on temp1. 1168 1169 self._generateAttr(node, method_name, self.attribute_load_instructions) 1170 temp_method = self.optimiser.optimise_temp_storage() 1171 1172 self._handleAttributeError(node, end_attempt_block) 1173 1174 # Add arguments. 1175 # NOTE: No support for defaults. 1176 1177 self._startCallFunc() 1178 self.new_op(temp1) 1179 self.new_op(StoreFrame(0)) 1180 self.new_op(temp2) 1181 self.new_op(StoreFrame(1)) 1182 self._endCallFuncArgs(2) 1183 self._doCallFunc(temp_method) 1184 self._endCallFunc(temp_method) 1185 1186 # Store the result. 1187 1188 temp_out = self.get_temp() 1189 1190 # Test for NotImplemented. 1191 # Don't actually raise an exception. 1192 1193 self.new_op(TestIdentityAddress(self.importer.get_predefined_constant("NotImplemented"))) 1194 self.new_op(JumpIfTrue(next_method_block)) 1195 self.new_op(Jump(end_block)) 1196 1197 # End method attempt. 1198 1199 self.set_block(end_attempt_block) 1200 return temp_out 1201 1202 def _handleAttributeError(self, node, end_call_block): 1203 1204 """ 1205 Add exception handling to the method acquisition instructions where the 1206 attribute access cannot be resolved at compile-time. 1207 """ 1208 1209 if not self.optimiser.optimise_known_target(): 1210 self.load_builtin("AttributeError", node) 1211 self.new_op(CheckException()) 1212 self.new_op(JumpIfTrue(end_call_block)) 1213 1214 def _generateSequence(self, sequence_type, node): 1215 1216 "Make a sequence of 'sequence_type' for the given program 'node'." 1217 1218 self.make_object(self.get_builtin_class(sequence_type, node), len(node.nodes)) 1219 temp = self.get_temp() 1220 1221 for i, n in enumerate(node.nodes): 1222 self.dispatch(n) 1223 self.record_value() 1224 self.new_op(temp) 1225 self.new_op(StoreAttr(Attr(i, None, None, None))) 1226 self.set_source() 1227 self.discard_value() 1228 1229 self.new_op(temp) 1230 self.discard_temp(temp) 1231 1232 def _generateTestBoolean(self, node, temp): 1233 1234 """ 1235 Generate a test of the boolean status of the current value for the given 1236 program 'node'. 1237 """ 1238 1239 # Get method on temp. 1240 # NOTE: Using __bool__ instead of __nonzero__. 1241 1242 self._generateAttr(node, "__bool__", self.attribute_load_instructions) 1243 temp_method = self.optimiser.optimise_temp_storage() 1244 1245 self._startCallFunc() 1246 self.new_op(temp) 1247 self.new_op(StoreFrame(0)) 1248 self._endCallFuncArgs(1) 1249 self._doCallFunc(temp_method) 1250 self._endCallFunc(temp_method) 1251 1252 self.discard_temp(temp_method) 1253 1254 # Convert result to boolean (a StoreBoolean operation). 1255 1256 self.new_op(TestIdentityAddress(self.get_builtin("True", node))) 1257 1258 def _generateLoadBoolean(self, node): 1259 1260 """ 1261 Generate instructions to load the appropriate value given the current 1262 boolean status. 1263 """ 1264 1265 true_block = self.new_block() 1266 end_block = self.new_block() 1267 1268 self.new_op(JumpIfTrue(true_block)) 1269 self.load_builtin("False", node) 1270 self.new_op(Jump(end_block)) 1271 1272 self.set_block(true_block) 1273 self.load_builtin("True", node) 1274 1275 self.set_block(end_block) 1276 1277 # Concrete visitor methods. 1278 1279 # Binary operators. 1280 1281 def visitAdd(self, node): 1282 self._visitBinary(node, "__add__", "__radd__") 1283 1284 def visitBitand(self, node): 1285 self._visitBinary(node, "__and__", "__rand__") 1286 1287 def visitBitor(self, node): 1288 self._visitBinary(node, "__or__", "__ror__") 1289 1290 def visitBitxor(self, node): 1291 self._visitBinary(node, "__xor__", "__rxor__") 1292 1293 def visitDiv(self, node): 1294 self._visitBinary(node, "__div__", "__rdiv__") 1295 1296 def visitFloorDiv(self, node): 1297 self._visitBinary(node, "__floordiv__", "__rfloordiv__") 1298 1299 def visitLeftShift(self, node): 1300 self._visitBinary(node, "__lshift__", "__rlshift__") 1301 1302 def visitMod(self, node): 1303 self._visitBinary(node, "__mod__", "__rmod__") 1304 1305 def visitMul(self, node): 1306 self._visitBinary(node, "__mul__", "__rmul__") 1307 1308 def visitPower(self, node): 1309 self._visitBinary(node, "__pow__", "__rpow__") 1310 1311 def visitRightShift(self, node): 1312 self._visitBinary(node, "__rshift__", "__rrshift__") 1313 1314 def visitSub(self, node): 1315 self._visitBinary(node, "__sub__", "__rsub__") 1316 1317 # Unary operators. 1318 1319 def visitInvert(self, node): 1320 self._visitUnary(node, "__invert__") 1321 1322 def visitUnaryAdd(self, node): 1323 self._visitUnary(node, "__pos__") 1324 1325 def visitUnarySub(self, node): 1326 self._visitUnary(node, "__neg__") 1327 1328 # Logical operators. 1329 1330 def visitAnd(self, node): 1331 end_block = self.new_block() 1332 temp_pos = self.reserve_temp() 1333 temp = LoadTemp(temp_pos) 1334 1335 for n in node.nodes[:-1]: 1336 self.dispatch(n) 1337 self.new_op(StoreTemp(temp_pos)) 1338 1339 self._generateTestBoolean(n, temp) 1340 self.new_op(JumpIfFalse(end_block)) 1341 1342 self.dispatch(node.nodes[-1]) 1343 self.new_op(StoreTemp(temp_pos)) 1344 1345 self.set_block(end_block) 1346 1347 self.new_op(temp) 1348 self.discard_temp(temp) 1349 1350 def visitNot(self, node): 1351 self.dispatch(node.expr) 1352 1353 temp = self.optimiser.optimise_temp_storage() 1354 self._generateTestBoolean(node.expr, temp) 1355 self.discard_temp(temp) 1356 1357 self.new_op(InvertBoolean()) 1358 self._generateLoadBoolean(node) 1359 1360 def visitOr(self, node): 1361 end_block = self.new_block() 1362 temp_pos = self.reserve_temp() 1363 temp = LoadTemp(temp_pos) 1364 1365 for n in node.nodes[:-1]: 1366 self.dispatch(n) 1367 self.new_op(StoreTemp(temp_pos)) 1368 1369 self._generateTestBoolean(n, temp) 1370 self.new_op(JumpIfTrue(end_block)) 1371 1372 self.dispatch(node.nodes[-1]) 1373 self.new_op(StoreTemp(temp_pos)) 1374 1375 self.set_block(end_block) 1376 1377 self.new_op(temp) 1378 self.discard_temp(temp) 1379 1380 # Comparisons. 1381 1382 def visitCompare(self, node): 1383 1384 """ 1385 _t1 = node.expr 1386 _t1 op1 _t2 and _t2 op2 _t3 and ... 1387 """ 1388 1389 end_block = self.new_block() 1390 1391 self.dispatch(node.expr) 1392 temp2 = self.optimiser.optimise_temp_storage() 1393 1394 last_op = node.ops[-1] 1395 1396 for op in node.ops: 1397 op_name, next_node = op 1398 methods = self.comparison_methods[op_name] 1399 1400 # Propagate the arguments as we traverse the construct. 1401 1402 temp1 = temp2 1403 self.dispatch(next_node) 1404 temp2 = self.optimiser.optimise_temp_storage() 1405 1406 # Use the appropriate mechanism, setting the boolean status for the 1407 # comparison. 1408 1409 if methods is not None: 1410 left_method, right_method = methods 1411 1412 # Generate method call using evaluated argument and next node. 1413 1414 temp_result = self._generateBinary(node, temp1, temp2, left_method, right_method) 1415 self.new_op(temp_result) 1416 self._generateTestBoolean(node, temp_result) 1417 self.discard_temp(temp_result) 1418 1419 else: 1420 # Deal with the special operators. 1421 1422 if op_name.startswith("is"): 1423 self.new_op(temp1) 1424 self.record_value() 1425 self.new_op(temp2) 1426 self.new_op(TestIdentity()) 1427 self.set_source() 1428 self.discard_value() 1429 1430 elif op_name.endswith("in"): 1431 self.new_op(temp2) 1432 1433 # Get method on temp2. 1434 1435 self._generateAttr(node, "__contains__", self.attribute_load_instructions) 1436 temp_method = self.optimiser.optimise_temp_storage() 1437 1438 # Add arguments. 1439 # NOTE: No support for defaults. 1440 1441 self._startCallFunc() 1442 self.new_op(temp2) 1443 self.new_op(StoreFrame(0)) 1444 self.new_op(temp1) 1445 self.new_op(StoreFrame(1)) 1446 self._endCallFuncArgs(2) 1447 self._doCallFunc(temp_method) 1448 self._endCallFunc(temp_method) 1449 1450 temp_result = self.get_temp() 1451 self._generateTestBoolean(node, temp_result) 1452 self.discard_temp(temp_result) 1453 1454 if op_name.find("not") != -1: 1455 self.new_op(InvertBoolean()) 1456 1457 # Test the result and jump to the end block if false. 1458 1459 if op is not last_op: 1460 self.new_op(JumpIfFalse(end_block)) 1461 1462 # Compilation duties... 1463 1464 self.discard_temp(temp1) 1465 1466 self.discard_temp(temp2) 1467 1468 # With the status set above, produce a boolean result. 1469 1470 self.set_block(end_block) 1471 1472 # Yield the appropriate value. 1473 1474 self._generateLoadBoolean(node) 1475 1476 # Expressions. 1477 1478 def visitBackquote(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Backquote") 1479 1480 def visitCallFunc(self, node): 1481 1482 """ 1483 Evaluate positional arguments, evaluate and store keyword arguments in 1484 the correct location, then invoke the function. 1485 """ 1486 1487 # Mark the frame, evaluate the target, generate the call. 1488 1489 self._startCallFunc() 1490 self.dispatch(node.node) 1491 temp, target = self._generateCallFunc(node.args, node) 1492 self._doCallFunc(temp, target) 1493 self._endCallFunc(temp, target) 1494 1495 def visitConst(self, node): 1496 const = self.importer.get_constant(node.value) 1497 self.new_op(LoadConst(const)) 1498 1499 def visitDict(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Dict") 1500 1501 def visitEllipsis(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Ellipsis") 1502 1503 def visitExec(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Exec") 1504 1505 def visitExpression(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Expression") 1506 1507 def visitGenExpr(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "GenExpr") 1508 1509 def visitGenExprFor(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "GenExprFor") 1510 1511 def visitGenExprIf(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "GenExprIf") 1512 1513 def visitGenExprInner(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "GenExprInner") 1514 1515 def visitGetattr(self, node): 1516 self._visitAttr(node, self.attribute_load_instructions) 1517 1518 def visitList(self, node): 1519 self._generateSequence("list", node) 1520 1521 def visitListComp(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "ListComp") 1522 1523 def visitListCompFor(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "ListCompFor") 1524 1525 def visitListCompIf(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "ListCompIf") 1526 1527 def visitName(self, node): 1528 if self.importer.predefined_constants.has_key(node.name): 1529 const = self.importer.get_predefined_constant(node.name) 1530 self.new_op(LoadConst(const)) 1531 else: 1532 self._visitName(node, self.name_load_instructions) 1533 1534 def visitSlice(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Slice") 1535 1536 def visitSubscript(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Subscript") 1537 1538 def visitTuple(self, node): 1539 self._generateSequence("tuple", node) 1540 1541 # Definitions. 1542 1543 def visitAssign(self, node): 1544 1545 """ 1546 Evaluate the expression from the given 'node' and assign it to the 1547 associated recipients. 1548 """ 1549 1550 self.dispatch(node.expr) 1551 1552 # Record the value and then dispatch to the assignment targets. 1553 1554 self.record_value(self.has_immediate_usage(node.nodes)) 1555 1556 for n in node.nodes: 1557 self.dispatch(n) 1558 1559 self.discard_value() 1560 1561 def visitAssAttr(self, node): 1562 1563 "Assign the assignment expression to the recipient 'node'." 1564 1565 self._visitAttr(node, self.attribute_store_instructions) 1566 self.set_source() 1567 1568 def visitAssList(self, node): 1569 1570 """ 1571 Assign items from the assignment expression to each of the recipients 1572 found within the given 'node'. 1573 """ 1574 1575 for i, n in enumerate(node.nodes): 1576 self._startCallFunc() 1577 self.new_op(self.expr_temp[-1]) 1578 self._generateAttr(node, "__getitem__", self.attribute_load_instructions) 1579 temp, target = self._generateCallFunc([compiler.ast.Const(i)], node) 1580 self._doCallFunc(temp, target) 1581 self._endCallFunc(temp, target) 1582 1583 # Provide a different source value. 1584 # NOTE: Permitting immediate usage given that neither name nor 1585 # NOTE: attribute accesses should involve a function call 1586 # NOTE: overwriting the above result. 1587 1588 self.record_value(self.is_immediate_user(n)) 1589 self.dispatch(n) 1590 self.discard_value() 1591 1592 def visitAssName(self, node): 1593 1594 "Assign the assignment expression to the recipient 'node'." 1595 1596 self._visitName(node, self.name_store_instructions) 1597 self.set_source() 1598 1599 visitAssTuple = visitAssList 1600 1601 def visitAugAssign(self, node): 1602 use_binary_block = self.new_block() 1603 end_block = self.new_block() 1604 1605 # Evaluate the expression. 1606 1607 self.dispatch(node.expr) 1608 temp2 = self.optimiser.optimise_temp_storage() 1609 1610 # Evaluate the target. 1611 1612 self.dispatch(node.node) 1613 temp1 = self.optimiser.optimise_temp_storage() 1614 1615 # Find the augmented assignment method and attempt to use it. 1616 1617 aug_method, (left_method, right_method) = self.augassign_methods[node.op] 1618 temp_out = self._generateOpMethod(node, temp1, temp2, aug_method, use_binary_block, end_block) 1619 self.discard_temp(temp_out) # NOTE: Will re-use the same storage. 1620 1621 # Where no such method exists, use the binary operator methods. 1622 1623 self.set_block(use_binary_block) 1624 temp_out = self._generateBinary(node, temp1, temp2, left_method, right_method) 1625 1626 # Assign the result to the name. 1627 1628 self.set_block(end_block) 1629 self.new_op(temp_out) 1630 self.record_value(1) 1631 1632 if isinstance(node.node, compiler.ast.Name): 1633 self.visitAssName(node.node) 1634 elif isinstance(node.node, compiler.ast.Getattr): 1635 self.visitAssAttr(node.node) 1636 else: 1637 raise TranslationNotImplementedError(self.module.full_name(), node, "AugAssign(Slice or Subscript)") 1638 1639 self.discard_value() 1640 1641 # Compilation duties... 1642 1643 self.discard_temp(temp1) 1644 self.discard_temp(temp2) 1645 1646 def visitClass(self, node): 1647 if not node.unit.referenced: 1648 return 1649 1650 # Store the name. 1651 1652 self.new_op(LoadConst(node.unit)) 1653 self.record_value() 1654 self._visitName(node, self.name_store_instructions) 1655 self.set_source() 1656 self.discard_value() 1657 1658 # Visit the code. 1659 1660 unit = self.unit 1661 self.unit = node.unit 1662 self.unit.code_location = self.module.code_location # class body code is not independently addressable 1663 self.dispatch(node.code) 1664 self.unit = unit 1665 1666 def visitDecorators(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Decorators") 1667 1668 def visitFrom(self, node): pass 1669 1670 def visitFunction(self, node): 1671 if not node.unit.referenced and not node.unit.is_method(): 1672 return 1673 1674 # Only store the name when visiting this node from outside. 1675 1676 if self.unit is not node.unit: 1677 self.new_op(LoadConst(node.unit)) 1678 1679 self.record_value() 1680 self._visitName(node, self.name_store_instructions) # AssName equivalent 1681 self.set_source() 1682 self.discard_value() 1683 1684 self._generateFunctionDefaults(node.unit) 1685 1686 # Visiting of the code occurs when get_code is invoked on this node. 1687 1688 else: 1689 extend = ExtendFrame() 1690 self.new_op(extend) 1691 1692 self.dispatch(node.code) 1693 if not isinstance(self.last_op(), Return): 1694 self.dispatch(compiler.ast.Name("None")) 1695 self.new_op(StoreResult()) 1696 1697 self.new_op(Return()) 1698 1699 self.set_frame_usage(node, extend) 1700 1701 def visitGlobal(self, node): pass 1702 1703 def visitImport(self, node): pass 1704 1705 def visitKeyword(self, node): pass 1706 1707 def visitLambda(self, node): 1708 1709 """ 1710 Lambda functions can be represented as globally defined functions 1711 provided they do not define any default parameter values, since these 1712 may defined in a non-global scope. 1713 1714 Where defaults are defined, an object must be created and its content 1715 defined: the callable member of the object's structure must be set to 1716 the lambda function definition; each default must be attached to the 1717 object as an attribute, as is the case with normal functions and 1718 methods. 1719 """ 1720 1721 # Produce the reference to this function when visiting this node from 1722 # outside. 1723 1724 if self.unit is not node.unit: 1725 temp = self._generateFunctionDefaults(node.unit) 1726 self.new_op(LoadConst(node.unit)) 1727 1728 # Populate the new object required for the function. 1729 1730 if temp is not None: 1731 self.new_op(LoadCallable()) 1732 self.new_op(temp) 1733 self.new_op(StoreCallable()) 1734 1735 self.new_op(temp) 1736 #self.discard_temp(temp) 1737 1738 # Visiting of the code occurs when get_code is invoked on this node. 1739 1740 else: 1741 self.dispatch(node.code) 1742 self.new_op(StoreResult()) 1743 self.new_op(Return()) 1744 1745 def visitModule(self, node): 1746 extend = ExtendFrame() 1747 self.new_op(extend) 1748 self.dispatch(node.node) 1749 self.set_frame_usage(node, extend) 1750 1751 # Statements. 1752 1753 def visitStmt(self, node): 1754 1755 "Process the collection of statements provided by 'node'." 1756 1757 for n in node.nodes: 1758 1759 # Process the statement. 1760 1761 self.dispatch(n) 1762 1763 # Discard temporary storage. 1764 1765 if self.temp_positions: 1766 #print "Had temp", self.temp_positions 1767 self.temp_positions = set() 1768 1769 # Prevent incorrect optimisation by resetting the optimiser after 1770 # each statement. 1771 1772 self.optimiser.reset() 1773 1774 def visitAssert(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Assert") 1775 1776 def visitBreak(self, node): 1777 next_block, exit_block = self.get_loop_blocks() 1778 self.new_op(Jump(exit_block)) 1779 1780 def visitContinue(self, node): 1781 next_block, exit_block = self.get_loop_blocks() 1782 self.new_op(Jump(next_block)) 1783 1784 def visitDiscard(self, node): 1785 self.dispatch(node.expr) 1786 self.optimiser.optimise_unused_results() 1787 1788 def visitFor(self, node): 1789 next_handler_block = self.new_block() 1790 end_handler_block = self.new_block() 1791 exit_block = self.new_block() 1792 next_block = self.new_block() 1793 else_block = self.new_block() 1794 1795 # Get the "list" to be iterated over, obtain its iterator. 1796 1797 self._startCallFunc() 1798 self.dispatch(node.list) 1799 self._generateAttr(node, "__iter__", self.attribute_load_instructions) 1800 temp, target = self._generateCallFunc([], node) 1801 self._doCallFunc(temp, target) 1802 self._endCallFunc(temp, target) 1803 1804 temp_iterator = self.optimiser.optimise_temp_storage() 1805 1806 # In the loop... 1807 1808 self.set_block(next_block) 1809 1810 # Handle exceptions when calling "next"... 1811 1812 self.new_op(PushHandler(next_handler_block)) 1813 1814 # Use the iterator to get the next value. 1815 1816 self._startCallFunc() 1817 self.new_op(temp_iterator) 1818 self._generateAttr(node, "next", self.attribute_load_instructions) 1819 temp, target = self._generateCallFunc([], node) 1820 self._doCallFunc(temp, target) 1821 self._endCallFunc(temp, target) 1822 1823 # Record the value to be assigned. 1824 1825 self.record_value() 1826 1827 # Skip the handler where the call was successful. 1828 1829 self.new_op(Jump(end_handler_block)) 1830 1831 # Enter the exception handler. 1832 1833 self.set_block(next_handler_block) 1834 self.new_op(PopHandler()) 1835 1836 # Test for StopIteration. 1837 1838 self.load_builtin("StopIteration", node) 1839 self.new_op(CheckException()) 1840 if node.else_ is not None: 1841 self.new_op(JumpIfTrue(else_block)) 1842 else: 1843 self.new_op(JumpIfTrue(exit_block)) 1844 1845 # Re-raise the exception otherwise. 1846 1847 self.new_op(RaiseException()) 1848 1849 # After the handler. 1850 1851 self.set_block(end_handler_block) 1852 1853 # Assign to the target. 1854 1855 self.dispatch(node.assign) 1856 self.discard_value() 1857 1858 # Process the body with the current next and exit points. 1859 1860 self.add_loop_blocks(next_block, exit_block) 1861 self.dispatch(node.body) 1862 self.drop_loop_blocks() 1863 1864 # Repeat the loop. 1865 1866 self.new_op(Jump(next_block)) 1867 1868 # Produce the "else" section. 1869 1870 if node.else_ is not None: 1871 self.set_block(exit_block) 1872 1873 self.dispatch(node.else_) 1874 1875 # After the loop... 1876 1877 self.set_block(exit_block) 1878 1879 # Compilation duties... 1880 1881 self.discard_temp(temp_iterator) 1882 1883 def visitIf(self, node): 1884 first = 1 1885 exit_block = self.new_block() 1886 1887 clauses = node.tests + [(None, node.else_)] 1888 last_clause = clauses[-1] 1889 1890 for clause in clauses: 1891 test, body = clause 1892 if body is None: 1893 break 1894 if not first: 1895 self.set_block(next_block) 1896 if test is not None: 1897 self.dispatch(test) 1898 next_block = self.new_block() 1899 self.new_op(JumpIfFalse(next_block)) 1900 self.dispatch(body) 1901 if clause is not last_clause: 1902 self.new_op(Jump(exit_block)) 1903 1904 first = 0 1905 1906 self.set_block(exit_block) 1907 1908 def visitPass(self, node): pass 1909 1910 def visitPrint(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Print") 1911 1912 def visitPrintnl(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Printnl") 1913 1914 def visitRaise(self, node): 1915 # NOTE: expr1 only => instance provided 1916 self.dispatch(node.expr1) 1917 1918 if node.expr2 is not None: 1919 temp = self.optimiser.optimise_temp_storage() 1920 1921 self.dispatch(node.expr2) 1922 temp_arg = self.optimiser.optimise_temp_storage() 1923 1924 self._startCallFunc() 1925 self.new_op(temp_arg) 1926 self.new_op(StoreFrame(0)) 1927 self._endCallFuncArgs(1) 1928 self._doCallFunc(temp) 1929 self._endCallFunc(temp) 1930 1931 self.discard_temp(temp_arg) 1932 1933 self.new_op(StoreException()) 1934 self.new_op(RaiseException()) 1935 1936 def visitReturn(self, node): 1937 if node.value is not None: 1938 self.dispatch(node.value) 1939 else: 1940 self.dispatch(compiler.ast.Name("None")) 1941 1942 self.new_op(StoreResult()) 1943 self.new_op(Return()) 1944 1945 def visitTryExcept(self, node): 1946 exit_block = self.new_block() 1947 else_block = self.new_block() 1948 handler_block = self.new_block() 1949 1950 self.add_exception_blocks(handler_block, exit_block) 1951 1952 # Try... 1953 # Produce the code, then jump to the exit. 1954 1955 self.new_op(PushHandler(handler_block)) 1956 self.dispatch(node.body) 1957 self.new_op(PopHandler()) 1958 1959 if node.else_ is not None: 1960 self.new_op(Jump(else_block)) 1961 else: 1962 self.new_op(Jump(exit_block)) 1963 1964 # Start of handlers. 1965 1966 self.set_block(handler_block) 1967 1968 self.new_op(PopHandler()) 1969 1970 for name, assignment, handler in node.handlers: 1971 next_block = self.new_block() 1972 1973 # Test the given exception against the current exception. 1974 1975 if name is not None: 1976 self.dispatch(name) 1977 1978 self.new_op(CheckException()) 1979 self.new_op(JumpIfFalse(next_block)) 1980 1981 # Handle assignment to exception variable. 1982 1983 if assignment is not None: 1984 self.new_op(LoadException()) 1985 1986 # Record the value to be assigned. 1987 1988 self.record_value() 1989 self.dispatch(assignment) 1990 self.discard_value() 1991 1992 # Produce the handler code, then jump to the exit. 1993 1994 self.dispatch(handler) 1995 self.new_op(Jump(exit_block)) 1996 1997 self.set_block(next_block) 1998 1999 # Unhandled exceptions. 2000 2001 self.new_op(RaiseException()) 2002 2003 # Optional else clause. 2004 2005 if node.else_ is not None: 2006 self.set_block(else_block) 2007 2008 self.dispatch(node.else_) 2009 2010 self.set_block(exit_block) 2011 self.drop_exception_blocks() 2012 2013 def visitTryFinally(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "TryFinally") 2014 2015 def visitWhile(self, node): 2016 exit_block = self.new_block() 2017 next_block = self.new_block() 2018 else_block = self.new_block() 2019 2020 self.set_block(next_block) 2021 self.dispatch(node.test) 2022 if node.else_ is not None: 2023 self.new_op(JumpIfFalse(else_block)) 2024 else: 2025 self.new_op(JumpIfFalse(exit_block)) 2026 2027 self.add_loop_blocks(next_block, exit_block) 2028 2029 self.dispatch(node.body) 2030 self.new_op(Jump(next_block)) 2031 2032 if node.else_ is not None: 2033 self.set_block(else_block) 2034 2035 self.dispatch(node.else_) 2036 2037 self.set_block(exit_block) 2038 2039 self.drop_loop_blocks() 2040 2041 def visitWith(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "With") 2042 2043 def visitYield(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Yield") 2044 2045 # Useful data. 2046 2047 comparison_methods = { 2048 "==" : ("__eq__", "__ne__"), 2049 "!=" : ("__ne__", "__eq__"), 2050 "<" : ("__lt__", "__gt__"), 2051 "<=" : ("__le__", "__ge__"), 2052 ">=" : ("__ge__", "__le__"), 2053 ">" : ("__gt__", "__lt__"), 2054 "is" : None, 2055 "is not" : None, 2056 "in" : None, 2057 "not in" : None 2058 } 2059 2060 augassign_methods = { 2061 "+=" : ("__iadd__", ("__add__", "__radd__")), 2062 "-=" : ("__isub__", ("__sub__", "__rsub__")), 2063 "*=" : ("__imul__", ("__mul__", "__rmul__")), 2064 "/=" : ("__idiv__", ("__div__", "__rdiv__")), 2065 "%=" : ("__imod__", ("__mod__", "__rmod__")), 2066 "**=" : ("__ipow__", ("__pow__", "__rpow__")), 2067 "<<=" : ("__ilshift__", ("__lshift__", "__rlshift__")), 2068 ">>=" : ("__irshift__", ("__rshift__", "__rrshift__")), 2069 "&=" : ("__iand__", ("__and__", "__rand__")), 2070 "^=" : ("__ixor__", ("__xor__", "__rxor__")), 2071 "|=" : ("__ior__", ("__or__", "__ror__")) 2072 } 2073 2074 # vim: tabstop=4 expandtab shiftwidth=4