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