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