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