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