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