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