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