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