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).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. 774 775 self.dispatch(arg.expr) 776 self.new_op(StoreFrameIndex(paramindex)) 777 778 # use (callable+0)+paramindex+table 779 # checks embedded offset against (callable+0) 780 # moves the current value to frame+position 781 782 # Record the highest possible frame position for this argument. 783 784 max_keyword_pos = max(max_keyword_pos, max(self.paramtable.all_attribute_positions(arg.name))) 785 786 else: 787 self.dispatch(arg) 788 self.new_op(StoreFrame(frame_pos)) 789 790 employed_positions.add(frame_pos) 791 792 # Check to see if the first argument is appropriate (compatible with 793 # the target where methods are being invoked via classes). 794 795 if first and expect_context: 796 797 # Drop any test if the target and the context are known. 798 799 if not self.optimiser.have_correct_self_for_target(context, self.unit): 800 801 continue_block = self.new_block() 802 803 self.new_op(CheckSelf()) 804 self.optimiser.set_source(temp) 805 self.new_op(JumpIfTrue(continue_block)) 806 807 # Where the context is inappropriate, drop the incomplete frame and 808 # raise an exception. 809 810 self.new_op(DropFrame()) 811 self.new_op(LoadResult()) 812 813 self.load_builtin("TypeError", node) 814 self.new_op(StoreException()) 815 self.new_op(RaiseException()) 816 817 self.set_block(continue_block) 818 819 first = 0 820 frame_pos += 1 821 822 # NOTE: Extra keywords are not supported. 823 # NOTE: Somehow, the above needs to be combined with * arguments. 824 825 if extra_keywords: 826 print "Warning: extra keyword argument(s) %s not handled." % ", ".join([arg.name for arg in extra_keywords]) 827 828 # Either test for a complete set of arguments. 829 830 if target is not None: 831 832 # Make sure that enough arguments have been given. 833 834 nargs_max = len(target.positional_names) 835 ndefaults = len(target.defaults) 836 nargs_min = nargs_max - ndefaults 837 838 for i in range(ncontext, nargs_min): 839 if i not in employed_positions: 840 raise TranslateError(self.module.full_name(), node, 841 "Argument %r not supplied for %r: need at least %d argument(s)." % (i+1, target.name, nargs_min)) 842 843 nargs = frame_pos 844 845 if nargs > nargs_max and not target.has_star and not target.has_dstar: 846 raise TranslateError(self.module.full_name(), node, 847 "Too many arguments for %r: need at most %d argument(s)." % (target.name, nargs_max)) 848 849 # Where defaults are involved, put them into the frame. 850 851 self._generateCallFuncDefaultArgs(target, temp, nargs_min, nargs_max, employed_positions) 852 853 # Set the frame size. 854 855 self._endCallFuncArgs(nargs_max) 856 857 # Or generate instructions to do this at run-time. 858 859 else: 860 max_pos = max(max(employed_positions or [-1]), max_keyword_pos, frame_pos - 1) 861 862 # Only check non-empty frames (using the callable's details). 863 864 if employed_positions or max_pos >= 0: 865 self.new_op(temp) 866 self.new_op(CheckFrame(max_pos + 1)) 867 868 # Set the frame size. 869 870 self._endCallFuncArgs(max_pos + 1) 871 872 def _generateCallFuncDefaultArgs(self, target, temp, nargs_min, nargs_max, employed_positions): 873 874 """ 875 For the given 'target' and 'temp' reference to the target, generate 876 default arguments for those positions in the range 'nargs_min'... 877 'nargs_max' which are not present in the 'employed_positions' 878 collection. 879 """ 880 881 # Where a lambda is involved, construct a dynamic object to hold the 882 # defaults. 883 884 dynamic = target.name is None 885 886 # Here, we use negative index values to visit the right hand end of 887 # the defaults list. 888 889 for pos in range(nargs_min, nargs_max): 890 if pos not in employed_positions: 891 if dynamic: 892 self.new_op(temp) 893 self.new_op(LoadAttr(target.default_attrs[pos - nargs_min])) 894 else: 895 self.new_op(LoadAddress(target.default_attrs[pos - nargs_min])) 896 self.new_op(StoreFrame(pos)) 897 898 def _doCallFunc(self, instruction, target=None): 899 900 "Make the invocation." 901 902 if isinstance(target, Class): 903 self.new_op(LoadConst(target.get_init_method())) 904 else: 905 self.new_op(instruction) 906 self.new_op(LoadCallable()) 907 self.new_op(JumpWithFrame()) 908 909 def _endCallFuncArgs(self, nargs): 910 911 "Set the frame size." 912 913 self.frame_makers[-1].attr = nargs 914 self.frame_makers.pop() 915 916 def _endCallFunc(self, instruction=None, target=None, load_result=1): 917 918 "Finish the invocation and tidy up afterwards." 919 920 if isinstance(target, Class): 921 self.new_op(LoadName(target.get_init_method().all_locals()["self"])) # load the context in the invocation frame 922 self.new_op(StoreResult()) 923 self.new_op(DropFrame()) 924 if load_result: 925 self.new_op(LoadResult()) 926 927 # Discard any temporary storage instructions. 928 929 if instruction is not None: 930 self.discard_temp(instruction) 931 932 def _generateFunctionDefaults(self, function): 933 934 """ 935 Generate the default initialisation code for 'function', returning 936 a temporary storage reference if a dynamic object was created for the 937 function. 938 """ 939 940 attr_to_default = zip(function.default_attrs, function.defaults) 941 if not attr_to_default: 942 return None 943 944 # Where a lambda is involved, construct a dynamic object to hold the 945 # defaults. 946 947 dynamic = function.name is None 948 949 if dynamic: 950 self.make_object(self.get_builtin_class("function", function), len(attr_to_default)) 951 temp = self.get_temp() 952 953 for attr, default in attr_to_default: 954 self.dispatch(default) 955 956 self.record_value() 957 if dynamic: 958 self.new_op(temp) 959 self.new_op(StoreAttr(attr)) 960 else: 961 self.new_op(StoreAddress(attr)) 962 self.set_source() 963 self.discard_value() 964 965 if dynamic: 966 return temp 967 else: 968 return None 969 970 def _visitName(self, node, classes): 971 972 """ 973 Visit the name-related 'node', generating instructions based on the 974 given 'classes'. 975 """ 976 977 name = node.name 978 scope = self.get_scope(name) 979 #print self.module.name, node.lineno, name, scope 980 self._generateName(name, scope, classes, node) 981 982 def _generateName(self, name, scope, classes, node): 983 984 """ 985 Generate code for the access to 'name' in 'scope' using the given 986 'classes', and using the given 'node' as the source of the access. 987 """ 988 989 NameInstruction, AddressInstruction = classes 990 991 if scope == "local": 992 unit = self.unit 993 if isinstance(unit, Function): 994 self.new_op(NameInstruction(unit.all_locals()[name])) 995 elif isinstance(unit, Class): 996 self.new_op(AddressInstruction(unit.all_class_attributes()[name])) 997 elif isinstance(unit, Module): 998 self.new_op(AddressInstruction(unit.module_attributes()[name])) 999 else: 1000 raise TranslateError(self.module.full_name(), node, "Program unit %r has no local %r." % (unit, name)) 1001 1002 elif scope == "global": 1003 globals = self.module.module_attributes() 1004 if globals.has_key(name): 1005 self.new_op(AddressInstruction(globals[name])) 1006 else: 1007 raise TranslateError(self.module.full_name(), node, "Module %r has no attribute %r." % (self.module, name)) 1008 1009 else: 1010 self.new_op(AddressInstruction(self.get_builtin(name, node))) 1011 1012 def _visitUnary(self, node): 1013 1014 """ 1015 _t = node.expr 1016 try: 1017 _result = _t.__pos__() 1018 except AttributeError: 1019 raise TypeError 1020 """ 1021 1022 method = unary_methods[node.__class__.__name__] 1023 1024 type_error_block = self.new_block() 1025 end_block = self.new_block() 1026 1027 # Evaluate and store the operand in temporary storage. 1028 1029 self.dispatch(node.expr) 1030 temp = self.optimiser.optimise_temp_storage() 1031 1032 self.new_op(temp) 1033 1034 # Get the method on temp. 1035 1036 self._generateAttr(node, method, self.attribute_load_instructions) 1037 temp_method = self.optimiser.optimise_temp_storage() 1038 1039 self._handleAttributeError(node, type_error_block) 1040 1041 # Add arguments. 1042 # NOTE: No support for defaults. 1043 1044 self._startCallFunc() 1045 self.new_op(temp) # Explicit context as first argument. 1046 self.new_op(StoreFrame(0)) 1047 self._endCallFuncArgs(1) 1048 self._doCallFunc(temp_method) 1049 self._endCallFunc(temp_method) 1050 self.new_op(Jump(end_block)) 1051 1052 # Store the result. 1053 1054 temp_out = self.get_temp() 1055 1056 # Raise a TypeError. 1057 1058 self.set_block(type_error_block) 1059 self.load_builtin("TypeError", node) 1060 self.new_op(StoreException()) 1061 self.new_op(RaiseException()) 1062 1063 self.set_block(end_block) 1064 1065 # Produce the result. 1066 1067 self.new_op(temp_out) 1068 1069 # Compilation duties... 1070 1071 self.discard_temp(temp) 1072 self.discard_temp(temp_out) 1073 1074 def _visitBinary(self, node): 1075 1076 """ 1077 _t1 = node.left 1078 _t2 = node.right 1079 try: 1080 _result = _t1.__add__(_t2) 1081 if _result is NotImplemented: 1082 raise AttributeError 1083 except AttributeError: 1084 try: 1085 _result = _t2.__radd__(_t1) 1086 if _result is NotImplemented: 1087 raise AttributeError 1088 except AttributeError: 1089 raise TypeError 1090 """ 1091 1092 left_method, right_method = binary_methods[node.__class__.__name__] 1093 1094 # Evaluate and store the left operand in temporary storage. 1095 1096 self.dispatch(node.left) 1097 temp1 = self.optimiser.optimise_temp_storage() 1098 1099 # Evaluate and store the right operand in temporary storage. 1100 1101 self.dispatch(node.right) 1102 temp2 = self.optimiser.optimise_temp_storage() 1103 1104 temp_out = self._generateBinary(node, temp1, temp2, left_method, right_method) 1105 1106 # Produce the result. 1107 1108 self.new_op(temp_out) 1109 1110 # Compilation duties... 1111 1112 self.discard_temp(temp1) 1113 self.discard_temp(temp2) 1114 self.discard_temp(temp_out) 1115 1116 def _generateBinary(self, node, temp1, temp2, left_method, right_method): 1117 1118 """ 1119 For the given 'node', generate the binary operator pattern for the 1120 operands 'temp1' and 'temp2', employing 'left_method' and 'right_method' 1121 as defined for binary operators, but also used in comparisons (for which 1122 this method is provided). 1123 1124 A temporary storage reference is returned from this method. 1125 """ 1126 1127 right_block = self.new_block() 1128 type_error_block = self.new_block() 1129 end_block = self.new_block() 1130 1131 # Left method. 1132 1133 temp_out = self._generateOpMethod(node, temp1, temp2, left_method, right_block, end_block) 1134 self.discard_temp(temp_out) # NOTE: Will re-use the same storage. 1135 1136 # Right method. 1137 1138 self.set_block(right_block) 1139 temp_out = self._generateOpMethod(node, temp2, temp1, right_method, type_error_block, end_block) 1140 1141 # Raise a TypeError. 1142 1143 self.set_block(type_error_block) 1144 self.load_builtin("TypeError", node) 1145 self.new_op(StoreException()) 1146 self.new_op(RaiseException()) 1147 1148 self.set_block(end_block) 1149 return temp_out 1150 1151 def _generateOpMethod(self, node, temp1, temp2, method_name, next_method_block, end_block): 1152 1153 """ 1154 For the given 'node', generate the operator method invocation using the 1155 operands 'temp1' and 'temp2', employing the given 'method_name', and 1156 jumping appropriately to 'next_method_block' where a NotImplemented 1157 result is returned, or to 'end_block' if the method call was successful. 1158 1159 A temporary storage reference is returned from this method. 1160 """ 1161 1162 end_attempt_block = self.new_block() 1163 1164 self.new_op(temp1) 1165 1166 # Get method on temp1. 1167 1168 self._generateAttr(node, method_name, self.attribute_load_instructions) 1169 temp_method = self.optimiser.optimise_temp_storage() 1170 1171 self._handleAttributeError(node, end_attempt_block) 1172 1173 # Add arguments. 1174 # NOTE: No support for defaults. 1175 1176 self._startCallFunc() 1177 self.new_op(temp1) 1178 self.new_op(StoreFrame(0)) 1179 self.new_op(temp2) 1180 self.new_op(StoreFrame(1)) 1181 self._endCallFuncArgs(2) 1182 self._doCallFunc(temp_method) 1183 self._endCallFunc(temp_method) 1184 1185 # Store the result. 1186 1187 temp_out = self.get_temp() 1188 1189 # Test for NotImplemented. 1190 # Don't actually raise an exception. 1191 1192 self.new_op(TestIdentityAddress(self.importer.get_predefined_constant("NotImplemented"))) 1193 self.new_op(JumpIfTrue(next_method_block)) 1194 self.new_op(Jump(end_block)) 1195 1196 # End method attempt. 1197 1198 self.set_block(end_attempt_block) 1199 return temp_out 1200 1201 def _handleAttributeError(self, node, end_call_block): 1202 1203 """ 1204 Add exception handling to the method acquisition instructions where the 1205 attribute access cannot be resolved at compile-time. 1206 """ 1207 1208 if not self.optimiser.optimise_known_target(): 1209 self.load_builtin("AttributeError", node) 1210 self.new_op(CheckException()) 1211 self.new_op(JumpIfTrue(end_call_block)) 1212 1213 def _generateSequence(self, sequence_type, node): 1214 1215 "Make a sequence of 'sequence_type' for the given program 'node'." 1216 1217 self.make_object(self.get_builtin_class(sequence_type, node), len(node.nodes)) 1218 temp = self.get_temp() 1219 1220 for i, n in enumerate(node.nodes): 1221 self.dispatch(n) 1222 self.record_value() 1223 self.new_op(temp) 1224 self.new_op(StoreAttr(Attr(i, None, None, None))) 1225 self.set_source() 1226 self.discard_value() 1227 1228 self.new_op(temp) 1229 self.discard_temp(temp) 1230 1231 def _generateTestBoolean(self, node, temp): 1232 1233 """ 1234 Generate a test of the boolean status of the current value for the given 1235 program 'node'. 1236 """ 1237 1238 # Get method on temp. 1239 # NOTE: Using __bool__ instead of __nonzero__. 1240 1241 self._generateAttr(node, "__bool__", self.attribute_load_instructions) 1242 temp_method = self.optimiser.optimise_temp_storage() 1243 1244 self._startCallFunc() 1245 self.new_op(temp) 1246 self.new_op(StoreFrame(0)) 1247 self._endCallFuncArgs(1) 1248 self._doCallFunc(temp_method) 1249 self._endCallFunc(temp_method) 1250 1251 self.discard_temp(temp_method) 1252 1253 # Convert result to boolean (a StoreBoolean operation). 1254 1255 self.new_op(TestIdentityAddress(self.get_builtin("True", node))) 1256 1257 def _generateLoadBoolean(self, node): 1258 1259 """ 1260 Generate instructions to load the appropriate value given the current 1261 boolean status. 1262 """ 1263 1264 true_block = self.new_block() 1265 end_block = self.new_block() 1266 1267 self.new_op(JumpIfTrue(true_block)) 1268 self.load_builtin("False", node) 1269 self.new_op(Jump(end_block)) 1270 1271 self.set_block(true_block) 1272 self.load_builtin("True", node) 1273 1274 self.set_block(end_block) 1275 1276 # Concrete visitor methods. 1277 1278 # Binary operators. 1279 1280 visitAdd = _visitBinary 1281 visitBitand = _visitBinary 1282 visitBitor = _visitBinary 1283 visitBitxor = _visitBinary 1284 visitDiv = _visitBinary 1285 visitFloorDiv = _visitBinary 1286 visitLeftShift = _visitBinary 1287 visitMod = _visitBinary 1288 visitMul = _visitBinary 1289 visitPower = _visitBinary 1290 visitRightShift = _visitBinary 1291 visitSub = _visitBinary 1292 1293 # Unary operators. 1294 1295 visitInvert = _visitUnary 1296 visitUnaryAdd = _visitUnary 1297 visitUnarySub = _visitUnary 1298 1299 # Logical operators. 1300 1301 def visitAnd(self, node): 1302 end_block = self.new_block() 1303 temp_pos = self.reserve_temp() 1304 temp = LoadTemp(temp_pos) 1305 1306 for n in node.nodes[:-1]: 1307 self.dispatch(n) 1308 self.new_op(StoreTemp(temp_pos)) 1309 1310 self._generateTestBoolean(n, temp) 1311 self.new_op(JumpIfFalse(end_block)) 1312 1313 self.dispatch(node.nodes[-1]) 1314 self.new_op(StoreTemp(temp_pos)) 1315 1316 self.set_block(end_block) 1317 1318 self.new_op(temp) 1319 self.discard_temp(temp) 1320 1321 def visitNot(self, node): 1322 self.dispatch(node.expr) 1323 1324 temp = self.optimiser.optimise_temp_storage() 1325 self._generateTestBoolean(node.expr, temp) 1326 self.discard_temp(temp) 1327 1328 self.new_op(InvertBoolean()) 1329 self._generateLoadBoolean(node) 1330 1331 def visitOr(self, node): 1332 end_block = self.new_block() 1333 temp_pos = self.reserve_temp() 1334 temp = LoadTemp(temp_pos) 1335 1336 for n in node.nodes[:-1]: 1337 self.dispatch(n) 1338 self.new_op(StoreTemp(temp_pos)) 1339 1340 self._generateTestBoolean(n, temp) 1341 self.new_op(JumpIfTrue(end_block)) 1342 1343 self.dispatch(node.nodes[-1]) 1344 self.new_op(StoreTemp(temp_pos)) 1345 1346 self.set_block(end_block) 1347 1348 self.new_op(temp) 1349 self.discard_temp(temp) 1350 1351 # Comparisons. 1352 1353 def visitCompare(self, node): 1354 1355 """ 1356 _t1 = node.expr 1357 _t1 op1 _t2 and _t2 op2 _t3 and ... 1358 """ 1359 1360 end_block = self.new_block() 1361 1362 self.dispatch(node.expr) 1363 temp2 = self.optimiser.optimise_temp_storage() 1364 1365 # NOTE: Replicated by some code in micropython.inspect.visitCompare. 1366 1367 last_op = node.ops[-1] 1368 1369 for op in node.ops: 1370 op_name, next_node = op 1371 methods = comparison_methods[op_name] 1372 1373 # Propagate the arguments as we traverse the construct. 1374 1375 temp1 = temp2 1376 self.dispatch(next_node) 1377 temp2 = self.optimiser.optimise_temp_storage() 1378 1379 # Use the appropriate mechanism, setting the boolean status for the 1380 # comparison. 1381 1382 if methods is not None: 1383 left_method, right_method = methods 1384 1385 # Generate method call using evaluated argument and next node. 1386 1387 temp_result = self._generateBinary(node, temp1, temp2, left_method, right_method) 1388 self.new_op(temp_result) 1389 self._generateTestBoolean(node, temp_result) 1390 self.discard_temp(temp_result) 1391 1392 else: 1393 # Deal with the special operators. 1394 1395 if op_name.startswith("is"): 1396 self.new_op(temp1) 1397 self.record_value() 1398 self.new_op(temp2) 1399 self.new_op(TestIdentity()) 1400 self.set_source() 1401 self.discard_value() 1402 1403 elif op_name.endswith("in"): 1404 self.new_op(temp2) 1405 1406 # Get method on temp2. 1407 1408 self._generateAttr(node, "__contains__", self.attribute_load_instructions) 1409 temp_method = self.optimiser.optimise_temp_storage() 1410 1411 # Add arguments. 1412 # NOTE: No support for defaults. 1413 1414 self._startCallFunc() 1415 self.new_op(temp2) 1416 self.new_op(StoreFrame(0)) 1417 self.new_op(temp1) 1418 self.new_op(StoreFrame(1)) 1419 self._endCallFuncArgs(2) 1420 self._doCallFunc(temp_method) 1421 self._endCallFunc(temp_method) 1422 1423 temp_result = self.get_temp() 1424 self._generateTestBoolean(node, temp_result) 1425 self.discard_temp(temp_result) 1426 1427 if op_name.find("not") != -1: 1428 self.new_op(InvertBoolean()) 1429 1430 # Test the result and jump to the end block if false. 1431 1432 if op is not last_op: 1433 self.new_op(JumpIfFalse(end_block)) 1434 1435 # Compilation duties... 1436 1437 self.discard_temp(temp1) 1438 1439 self.discard_temp(temp2) 1440 1441 # With the status set above, produce a boolean result. 1442 1443 self.set_block(end_block) 1444 1445 # Yield the appropriate value. 1446 1447 self._generateLoadBoolean(node) 1448 1449 # Expressions. 1450 1451 def visitBackquote(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Backquote") 1452 1453 def visitCallFunc(self, node): 1454 1455 """ 1456 Evaluate positional arguments, evaluate and store keyword arguments in 1457 the correct location, then invoke the function. 1458 """ 1459 1460 # Mark the frame, evaluate the target, generate the call. 1461 1462 self._startCallFunc() 1463 self.dispatch(node.node) 1464 temp, target = self._generateCallFunc(node.args, node) 1465 self._doCallFunc(temp, target) 1466 self._endCallFunc(temp, target) 1467 1468 def visitConst(self, node): 1469 const = self.importer.get_constant(node.value) 1470 self.new_op(LoadConst(const)) 1471 1472 def visitDict(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Dict") 1473 1474 def visitEllipsis(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Ellipsis") 1475 1476 def visitExec(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Exec") 1477 1478 def visitExpression(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Expression") 1479 1480 def visitGenExpr(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "GenExpr") 1481 1482 def visitGenExprFor(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "GenExprFor") 1483 1484 def visitGenExprIf(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "GenExprIf") 1485 1486 def visitGenExprInner(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "GenExprInner") 1487 1488 def visitGetattr(self, node): 1489 self._visitAttr(node, self.attribute_load_instructions) 1490 1491 def visitList(self, node): 1492 self._generateSequence("list", node) 1493 1494 def visitListComp(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "ListComp") 1495 1496 def visitListCompFor(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "ListCompFor") 1497 1498 def visitListCompIf(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "ListCompIf") 1499 1500 def visitName(self, node): 1501 if self.importer.predefined_constants.has_key(node.name): 1502 const = self.importer.get_predefined_constant(node.name) 1503 self.new_op(LoadConst(const)) 1504 else: 1505 self._visitName(node, self.name_load_instructions) 1506 1507 def visitSlice(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Slice") 1508 1509 def visitSubscript(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Subscript") 1510 1511 def visitTuple(self, node): 1512 self._generateSequence("tuple", node) 1513 1514 # Definitions. 1515 1516 def visitAssign(self, node): 1517 1518 """ 1519 Evaluate the expression from the given 'node' and assign it to the 1520 associated recipients. 1521 """ 1522 1523 self.dispatch(node.expr) 1524 1525 # Record the value and then dispatch to the assignment targets. 1526 1527 self.record_value(self.has_immediate_usage(node.nodes)) 1528 1529 for n in node.nodes: 1530 self.dispatch(n) 1531 1532 self.discard_value() 1533 1534 def visitAssAttr(self, node): 1535 1536 "Assign the assignment expression to the recipient 'node'." 1537 1538 self._visitAttr(node, self.attribute_store_instructions) 1539 self.set_source() 1540 1541 def visitAssList(self, node): 1542 1543 """ 1544 Assign items from the assignment expression to each of the recipients 1545 found within the given 'node'. 1546 """ 1547 1548 for i, n in enumerate(node.nodes): 1549 self._startCallFunc() 1550 self.new_op(self.expr_temp[-1]) 1551 self._generateAttr(node, "__getitem__", self.attribute_load_instructions) 1552 temp, target = self._generateCallFunc([compiler.ast.Const(i)], node) 1553 self._doCallFunc(temp, target) 1554 self._endCallFunc(temp, target) 1555 1556 # Provide a different source value. 1557 # NOTE: Permitting immediate usage given that neither name nor 1558 # NOTE: attribute accesses should involve a function call 1559 # NOTE: overwriting the above result. 1560 1561 self.record_value(self.is_immediate_user(n)) 1562 self.dispatch(n) 1563 self.discard_value() 1564 1565 def visitAssName(self, node): 1566 1567 "Assign the assignment expression to the recipient 'node'." 1568 1569 self._visitName(node, self.name_store_instructions) 1570 self.set_source() 1571 1572 visitAssTuple = visitAssList 1573 1574 def visitAugAssign(self, node): 1575 use_binary_block = self.new_block() 1576 end_block = self.new_block() 1577 1578 # Evaluate the expression. 1579 1580 self.dispatch(node.expr) 1581 temp2 = self.optimiser.optimise_temp_storage() 1582 1583 # Evaluate the target. 1584 1585 self.dispatch(node.node) 1586 temp1 = self.optimiser.optimise_temp_storage() 1587 1588 # Find the augmented assignment method and attempt to use it. 1589 1590 aug_method, (left_method, right_method) = augassign_methods[node.op] 1591 temp_out = self._generateOpMethod(node, temp1, temp2, aug_method, use_binary_block, end_block) 1592 self.discard_temp(temp_out) # NOTE: Will re-use the same storage. 1593 1594 # Where no such method exists, use the binary operator methods. 1595 1596 self.set_block(use_binary_block) 1597 temp_out = self._generateBinary(node, temp1, temp2, left_method, right_method) 1598 1599 # Assign the result to the name. 1600 1601 self.set_block(end_block) 1602 self.new_op(temp_out) 1603 self.record_value(1) 1604 1605 if isinstance(node.node, compiler.ast.Name): 1606 self.visitAssName(node.node) 1607 elif isinstance(node.node, compiler.ast.Getattr): 1608 self.visitAssAttr(node.node) 1609 else: 1610 raise TranslationNotImplementedError(self.module.full_name(), node, "AugAssign(Slice or Subscript)") 1611 1612 self.discard_value() 1613 1614 # Compilation duties... 1615 1616 self.discard_temp(temp1) 1617 self.discard_temp(temp2) 1618 1619 def visitClass(self, node): 1620 if not node.unit.referenced: 1621 return 1622 1623 # Store the name. 1624 1625 self.new_op(LoadConst(node.unit)) 1626 self.record_value() 1627 self._visitName(node, self.name_store_instructions) 1628 self.set_source() 1629 self.discard_value() 1630 1631 # Visit the code. 1632 1633 unit = self.unit 1634 self.unit = node.unit 1635 self.dispatch(node.code) 1636 self.unit = unit 1637 1638 def visitDecorators(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Decorators") 1639 1640 def visitFrom(self, node): pass 1641 1642 def visitFunction(self, node): 1643 if not node.unit.referenced and (not node.unit.is_method() or not node.unit.parent.has_key(node.unit.name)): 1644 return 1645 1646 # Only store the name when visiting this node from outside. 1647 1648 if self.unit is not node.unit: 1649 self.new_op(LoadConst(node.unit)) 1650 1651 self.record_value() 1652 self._visitName(node, self.name_store_instructions) # AssName equivalent 1653 self.set_source() 1654 self.discard_value() 1655 1656 self._generateFunctionDefaults(node.unit) 1657 1658 # Visiting of the code occurs when get_code is invoked on this node. 1659 1660 else: 1661 extend = ExtendFrame() 1662 self.new_op(extend) 1663 1664 self.dispatch(node.code) 1665 if not isinstance(self.last_op(), Return): 1666 self.dispatch(compiler.ast.Name("None")) 1667 self.new_op(StoreResult()) 1668 1669 self.new_op(Return()) 1670 1671 self.set_frame_usage(node, extend) 1672 1673 def visitGlobal(self, node): pass 1674 1675 def visitImport(self, node): pass 1676 1677 def visitKeyword(self, node): pass 1678 1679 def visitLambda(self, node): 1680 1681 """ 1682 Lambda functions can be represented as globally defined functions 1683 provided they do not define any default parameter values, since these 1684 may defined in a non-global scope. 1685 1686 Where defaults are defined, an object must be created and its content 1687 defined: the callable member of the object's structure must be set to 1688 the lambda function definition; each default must be attached to the 1689 object as an attribute, as is the case with normal functions and 1690 methods. 1691 """ 1692 1693 # Produce the reference to this function when visiting this node from 1694 # outside. 1695 1696 if self.unit is not node.unit: 1697 temp = self._generateFunctionDefaults(node.unit) 1698 self.new_op(LoadConst(node.unit)) 1699 1700 # Populate the new object required for the function. 1701 1702 if temp is not None: 1703 self.new_op(LoadCallable()) 1704 self.new_op(temp) 1705 self.new_op(StoreCallable()) 1706 1707 self.new_op(temp) 1708 #self.discard_temp(temp) 1709 1710 # Visiting of the code occurs when get_code is invoked on this node. 1711 1712 else: 1713 self.dispatch(node.code) 1714 self.new_op(StoreResult()) 1715 self.new_op(Return()) 1716 1717 def visitModule(self, node): 1718 extend = ExtendFrame() 1719 self.new_op(extend) 1720 self.dispatch(node.node) 1721 self.set_frame_usage(node, extend) 1722 1723 # Statements. 1724 1725 def visitStmt(self, node): 1726 1727 "Process the collection of statements provided by 'node'." 1728 1729 for n in node.nodes: 1730 1731 # Process the statement. 1732 1733 self.dispatch(n) 1734 1735 # Discard temporary storage. 1736 1737 if self.temp_positions: 1738 #print "Had temp", self.temp_positions 1739 self.temp_positions = set() 1740 1741 # Prevent incorrect optimisation by resetting the optimiser after 1742 # each statement. 1743 1744 self.optimiser.reset() 1745 1746 def visitAssert(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Assert") 1747 1748 def visitBreak(self, node): 1749 next_block, exit_block = self.get_loop_blocks() 1750 self.new_op(Jump(exit_block)) 1751 1752 def visitContinue(self, node): 1753 next_block, exit_block = self.get_loop_blocks() 1754 self.new_op(Jump(next_block)) 1755 1756 def visitDiscard(self, node): 1757 self.dispatch(node.expr) 1758 self.optimiser.optimise_unused_results() 1759 1760 def visitFor(self, node): 1761 next_handler_block = self.new_block() 1762 end_handler_block = self.new_block() 1763 exit_block = self.new_block() 1764 next_block = self.new_block() 1765 else_block = self.new_block() 1766 1767 # Get the "list" to be iterated over, obtain its iterator. 1768 1769 self._startCallFunc() 1770 self.dispatch(node.list) 1771 self._generateAttr(node, "__iter__", self.attribute_load_instructions) 1772 temp, target = self._generateCallFunc([], node) 1773 self._doCallFunc(temp, target) 1774 self._endCallFunc(temp, target) 1775 1776 temp_iterator = self.optimiser.optimise_temp_storage() 1777 1778 # In the loop... 1779 1780 self.set_block(next_block) 1781 1782 # Handle exceptions when calling "next"... 1783 1784 self.new_op(PushHandler(next_handler_block)) 1785 1786 # Use the iterator to get the next value. 1787 1788 self._startCallFunc() 1789 self.new_op(temp_iterator) 1790 self._generateAttr(node, "next", self.attribute_load_instructions) 1791 temp, target = self._generateCallFunc([], node) 1792 self._doCallFunc(temp, target) 1793 self._endCallFunc(temp, target) 1794 1795 # Record the value to be assigned. 1796 1797 self.record_value() 1798 1799 # Skip the handler where the call was successful. 1800 1801 self.new_op(Jump(end_handler_block)) 1802 1803 # Enter the exception handler. 1804 1805 self.set_block(next_handler_block) 1806 self.new_op(PopHandler()) 1807 1808 # Test for StopIteration. 1809 1810 self.load_builtin("StopIteration", node) 1811 self.new_op(CheckException()) 1812 if node.else_ is not None: 1813 self.new_op(JumpIfTrue(else_block)) 1814 else: 1815 self.new_op(JumpIfTrue(exit_block)) 1816 1817 # Re-raise the exception otherwise. 1818 1819 self.new_op(RaiseException()) 1820 1821 # After the handler. 1822 1823 self.set_block(end_handler_block) 1824 1825 # Assign to the target. 1826 1827 self.dispatch(node.assign) 1828 self.discard_value() 1829 1830 # Process the body with the current next and exit points. 1831 1832 self.add_loop_blocks(next_block, exit_block) 1833 self.dispatch(node.body) 1834 self.drop_loop_blocks() 1835 1836 # Repeat the loop. 1837 1838 self.new_op(Jump(next_block)) 1839 1840 # Produce the "else" section. 1841 1842 if node.else_ is not None: 1843 self.set_block(exit_block) 1844 1845 self.dispatch(node.else_) 1846 1847 # After the loop... 1848 1849 self.set_block(exit_block) 1850 1851 # Compilation duties... 1852 1853 self.discard_temp(temp_iterator) 1854 1855 def visitIf(self, node): 1856 first = 1 1857 exit_block = self.new_block() 1858 1859 clauses = node.tests + [(None, node.else_)] 1860 last_clause = clauses[-1] 1861 1862 for clause in clauses: 1863 test, body = clause 1864 if body is None: 1865 break 1866 if not first: 1867 self.set_block(next_block) 1868 if test is not None: 1869 self.dispatch(test) 1870 next_block = self.new_block() 1871 self.new_op(JumpIfFalse(next_block)) 1872 self.dispatch(body) 1873 if clause is not last_clause: 1874 self.new_op(Jump(exit_block)) 1875 1876 first = 0 1877 1878 self.set_block(exit_block) 1879 1880 def visitPass(self, node): pass 1881 1882 def visitPrint(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Print") 1883 1884 def visitPrintnl(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Printnl") 1885 1886 def visitRaise(self, node): 1887 # NOTE: expr1 only => instance provided 1888 self.dispatch(node.expr1) 1889 1890 if node.expr2 is not None: 1891 temp = self.optimiser.optimise_temp_storage() 1892 1893 self.dispatch(node.expr2) 1894 temp_arg = self.optimiser.optimise_temp_storage() 1895 1896 self._startCallFunc() 1897 self.new_op(temp_arg) 1898 self.new_op(StoreFrame(0)) 1899 self._endCallFuncArgs(1) 1900 self._doCallFunc(temp) 1901 self._endCallFunc(temp) 1902 1903 self.discard_temp(temp_arg) 1904 1905 self.new_op(StoreException()) 1906 self.new_op(RaiseException()) 1907 1908 def visitReturn(self, node): 1909 if node.value is not None: 1910 self.dispatch(node.value) 1911 else: 1912 self.dispatch(compiler.ast.Name("None")) 1913 1914 self.new_op(StoreResult()) 1915 self.new_op(Return()) 1916 1917 def visitTryExcept(self, node): 1918 exit_block = self.new_block() 1919 else_block = self.new_block() 1920 handler_block = self.new_block() 1921 1922 self.add_exception_blocks(handler_block, exit_block) 1923 1924 # Try... 1925 # Produce the code, then jump to the exit. 1926 1927 self.new_op(PushHandler(handler_block)) 1928 self.dispatch(node.body) 1929 self.new_op(PopHandler()) 1930 1931 if node.else_ is not None: 1932 self.new_op(Jump(else_block)) 1933 else: 1934 self.new_op(Jump(exit_block)) 1935 1936 # Start of handlers. 1937 1938 self.set_block(handler_block) 1939 1940 self.new_op(PopHandler()) 1941 1942 for name, assignment, handler in node.handlers: 1943 next_block = self.new_block() 1944 1945 # Test the given exception against the current exception. 1946 1947 if name is not None: 1948 self.dispatch(name) 1949 1950 self.new_op(CheckException()) 1951 self.new_op(JumpIfFalse(next_block)) 1952 1953 # Handle assignment to exception variable. 1954 1955 if assignment is not None: 1956 self.new_op(LoadException()) 1957 1958 # Record the value to be assigned. 1959 1960 self.record_value() 1961 self.dispatch(assignment) 1962 self.discard_value() 1963 1964 # Produce the handler code, then jump to the exit. 1965 1966 self.dispatch(handler) 1967 self.new_op(Jump(exit_block)) 1968 1969 self.set_block(next_block) 1970 1971 # Unhandled exceptions. 1972 1973 self.new_op(RaiseException()) 1974 1975 # Optional else clause. 1976 1977 if node.else_ is not None: 1978 self.set_block(else_block) 1979 1980 self.dispatch(node.else_) 1981 1982 self.set_block(exit_block) 1983 self.drop_exception_blocks() 1984 1985 def visitTryFinally(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "TryFinally") 1986 1987 def visitWhile(self, node): 1988 exit_block = self.new_block() 1989 next_block = self.new_block() 1990 else_block = self.new_block() 1991 1992 self.set_block(next_block) 1993 self.dispatch(node.test) 1994 if node.else_ is not None: 1995 self.new_op(JumpIfFalse(else_block)) 1996 else: 1997 self.new_op(JumpIfFalse(exit_block)) 1998 1999 self.add_loop_blocks(next_block, exit_block) 2000 2001 self.dispatch(node.body) 2002 self.new_op(Jump(next_block)) 2003 2004 if node.else_ is not None: 2005 self.set_block(else_block) 2006 2007 self.dispatch(node.else_) 2008 2009 self.set_block(exit_block) 2010 2011 self.drop_loop_blocks() 2012 2013 def visitWith(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "With") 2014 2015 def visitYield(self, node): raise TranslationNotImplementedError(self.module.full_name(), node, "Yield") 2016 2017 # vim: tabstop=4 expandtab shiftwidth=4