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