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