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, 2010 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.common import * 23 from micropython.data import * 24 from micropython.rsvp import * 25 import compiler.ast 26 27 class Helper: 28 29 "Internal helper methods for AST visitors." 30 31 # Allocation-related methods. 32 33 def make_instance(self, cls, n): 34 35 """ 36 Request a new instance using the given class 'cls' and with 'n' 37 attributes. 38 """ 39 40 # Load the class in order to locate the instance template. 41 42 self.new_op(LoadConst(cls)) 43 44 # NOTE: Instance headers are one location. 45 46 self.new_op(MakeInstance(n + 1)) 47 48 def make_exception(self, name, node): 49 50 "Make an exception of the given 'name' using 'node'." 51 52 # NOTE: Reserving an attribute. 53 54 self.make_instance(self.get_builtin_class(name, node), 1) 55 56 # Name-related methods. 57 58 def get_scope(self, name): 59 60 "Return the scope for the given 'name'." 61 62 attr, scope, from_name = self.unit._get_with_scope(name) 63 return scope 64 65 def load_builtin(self, name, node): 66 67 "Generate an instruction loading 'name' for the given 'node'." 68 69 self.new_op(LoadAddress(self.get_builtin(name, node))) 70 71 def get_builtin_class(self, name, node): 72 73 "Return the built-in class with the given 'name' for the given 'node'." 74 75 return self.get_builtin(name, node).get_value() 76 77 def get_builtin(self, name, node): 78 79 """ 80 Return the built-in module definition for the given 'name', used by the 81 given 'node'. 82 """ 83 84 if self.builtins is not None: 85 try: 86 return self.builtins[name] 87 except KeyError: 88 raise TranslateError("No __builtins__ definition is available for name %r." % name) 89 else: 90 raise TranslateError("No __builtins__ module is available for name %r." % name) 91 92 # Code feature methods. 93 94 def new_block(self): 95 96 "Return a new code block." 97 98 return Block() 99 100 def set_block(self, block): 101 102 "Add the given 'block' to the unit's list of blocks." 103 104 self.optimiser.reset() 105 self.blocks.append(block) 106 107 def get_loop_blocks(self): 108 return self.loop_blocks[-1] 109 110 def add_loop_blocks(self, next_block, exit_block): 111 self.loop_blocks.append((next_block, exit_block)) 112 113 def drop_loop_blocks(self): 114 self.loop_blocks.pop() 115 116 def add_exception_unit(self): 117 self.exception_blocks.append([]) 118 119 def get_exception_blocks(self): 120 return self.exception_blocks[-1][-1] 121 122 def add_exception_blocks(self, handler_block, exit_block): 123 self.exception_blocks[-1].append((handler_block, exit_block)) 124 125 def drop_exception_blocks(self): 126 self.exception_blocks[-1].pop() 127 128 def drop_exception_unit(self): 129 self.exception_blocks.pop() 130 131 # Assignment expression values. 132 133 def record_value(self, immediate=1): 134 135 """ 136 Record the current active value for an assignment. If the optional 137 'immediate' parameter if set to a false value always allocates new 138 temporary storage to hold the recorded value; otherwise, the 139 value-providing instruction may be replicated in order to provide the 140 active value later on. 141 """ 142 143 if immediate: 144 temp = self.optimiser.optimise_temp_storage() 145 else: 146 temp = self.get_temp() 147 self.expr_temp.append(temp) 148 149 def discard_value(self): 150 151 "Discard any temporary storage in use for the current assignment value." 152 153 self.discard_temp(self.expr_temp.pop()) 154 155 def set_source(self): 156 157 """ 158 Set the source of an assignment using the current assignment value. This 159 sets the source input for the current instruction. 160 """ 161 162 self.optimiser.set_source(self.expr_temp[-1]) 163 164 # Optimise away constant storage if appropriate. 165 166 if self.optimiser.optimise_constant_storage(): 167 self.remove_op() 168 169 def is_immediate_user(self, node): 170 171 """ 172 Return whether 'node' is an immediate user of an assignment expression. 173 """ 174 175 return isinstance(node, (compiler.ast.AssName, compiler.ast.AssAttr)) 176 177 def has_immediate_usage(self, nodes): 178 179 """ 180 Return whether 'nodes' are all immediate users of an assignment expression. 181 """ 182 183 for n in nodes: 184 if not self.is_immediate_user(n): 185 return 0 186 return 1 187 188 # Temporary storage administration. 189 190 def get_temp(self): 191 192 """ 193 Add a temporary storage instruction for the current value and return a 194 sequence of access instructions. 195 """ 196 197 position_in_frame = self.reserve_temp() 198 self.new_op(StoreTemp(position_in_frame)) 199 return LoadTemp(position_in_frame) 200 201 def reserve_temp(self, temp_position=None): 202 203 """ 204 Reserve a new temporary storage position, or if the optional 205 'temp_position' is specified, ensure that this particular position is 206 reserved. 207 """ 208 209 if temp_position is not None: 210 pass 211 elif not self.temp_positions: 212 temp_position = 0 213 else: 214 temp_position = max(self.temp_positions) + 1 215 216 self.temp_positions.add(temp_position) 217 self.max_temp_position = max(self.max_temp_position, temp_position) 218 return self.unit.all_local_usage + temp_position # position in frame 219 220 def ensure_temp(self, instruction=None): 221 222 """ 223 Ensure that the 'instruction' is using a reserved temporary storage 224 position. 225 """ 226 227 if isinstance(instruction, LoadTemp): 228 temp_position = instruction.attr - self.unit.all_local_usage 229 self.reserve_temp(temp_position) 230 231 def discard_temp(self, instruction=None): 232 233 "Discard any temporary storage position used by 'instruction'." 234 235 if isinstance(instruction, LoadTemp): 236 temp_position = instruction.attr - self.unit.all_local_usage 237 self.free_temp(temp_position) 238 239 def free_temp(self, temp_position): 240 241 "Free the temporary storage position specified by 'temp_position'." 242 243 if temp_position in self.temp_positions: 244 self.temp_positions.remove(temp_position) 245 246 def set_frame_usage(self, node, extend): 247 248 """ 249 Ensure that the frame usage for the unit associated with 'node' is set 250 on the 'extend' instruction. 251 """ 252 253 # Remove any ExtendFrame instructions which do nothing. 254 255 if self.last_op() is extend: 256 self.remove_op() 257 return 258 259 ntemp = self.max_temp_position + 1 260 extend.attr = ntemp + node.unit.local_usage # NOTE: See get_code for similar code. 261 262 # Code writing methods. 263 264 def new_op(self, op): 265 266 """ 267 Add 'op' to the generated code, returning a true value if an instruction 268 was added. 269 """ 270 271 # Optimise load operations employed by this instruction. 272 273 self.optimiser.optimise_load_operations(op) 274 if self.optimiser.optimise_away_no_operations(op) or self.optimiser.optimise_unused_handlers(op): 275 return 0 276 277 # Add the operation to the current block. 278 279 self.blocks[-1].code.append(op) 280 self.optimiser.set_new(op) 281 return 1 282 283 def remove_op(self): 284 285 "Remove the last instruction." 286 287 op = self.blocks[-1].code.pop() 288 self.optimiser.clear_active() 289 290 def replace_op(self, op): 291 292 "Replace the last added instruction with 'op'." 293 294 self.remove_op() 295 self.new_op(op) 296 297 def replace_active_value(self, op): 298 299 """ 300 Replace the value-providing active instruction with 'op' if appropriate. 301 """ 302 303 self.optimiser.remove_active_value() 304 self.new_op(op) 305 306 def last_op(self): 307 308 "Return the last added instruction." 309 310 try: 311 return self.blocks[-1].code[-1] 312 except IndexError: 313 return None 314 315 # Common methods. 316 317 def _generateGuards(self, node): 318 319 if not (self.optimiser.should_optimise_accesses_by_attribute_usage() and hasattr(node, "_attrtypes")): 320 return 321 322 # For each name, attempt to restrict the type employed. 323 324 for name, targets in node._attrtypes.items(): 325 326 # NOTE: Need to merge targets using the same type but suggesting 327 # NOTE: different kinds of attributes (instance vs. class). 328 329 # Where only one object type is suggested, produce a guard. 330 # NOTE: This only supports classes as types, not modules. 331 332 if len(targets) == 1: 333 target_name, is_static = list(targets)[0] 334 335 # Access the object table to get the attribute. 336 # NOTE: This depends on the special entry in the table 337 # NOTE: for class equivalence tests. 338 339 try: 340 obj = self.objtable.access(target_name, target_name) 341 342 # Where no attribute entry exists, the target could be a module. 343 344 except TableError, exc: 345 print "Possible guard for", target_name, "not enforceable." 346 continue 347 348 # NOTE: Could test the correctness of the guard where the nature 349 # NOTE: of the name is known. 350 # NOTE: The known value would be retrieved from the unit's 351 # NOTE: locals and tested as being a class or an instance of a 352 # NOTE: particular class. 353 354 # Generate the guard by loading a reference to the class. 355 356 after_test_block = self.new_block() 357 358 self.new_op(LoadClass(obj)) 359 temp_target = self.optimiser.optimise_temp_storage() 360 361 # For only static attributes, classes are acceptable. 362 363 if is_static: 364 365 # Generate name is target (for classes). 366 367 self.dispatch(compiler.ast.Name(name)) 368 self.new_op(TestIdentity()) 369 self.optimiser.set_source(temp_target) 370 371 # Jump to the next guard or the code if successful. 372 373 self.new_op(JumpIfTrue(after_test_block)) 374 375 # Where instance attributes are involved, only instances are 376 # acceptable. 377 378 # Generate isinstance(name, target). 379 380 self.dispatch(compiler.ast.Name(name)) 381 self.new_op(CheckInstance()) 382 self.optimiser.set_source(temp_target) 383 384 # Jump to the next guard or the code if successful. 385 386 self.new_op(JumpIfTrue(after_test_block)) 387 388 # Where the type is inappropriate, raise an exception. 389 390 self.make_exception("TypeError", node) 391 self.new_op(StoreException()) 392 self.new_op(RaiseException()) 393 394 self.set_block(after_test_block) 395 396 def _visitAttr(self, node, classes): 397 398 """ 399 Visit the attribute-related 'node', generating instructions based on the 400 given 'classes'. 401 """ 402 403 self.dispatch(node.expr) 404 self._generateAttr(node, node.attrname, classes) 405 406 def _generateAttr(self, node, attrname, classes): 407 408 """ 409 Generate code for the access to 'attrname' using the given 'classes'. 410 """ 411 412 AddressInstruction, AddressContextInstruction, AddressContextCondInstruction, \ 413 AttrInstruction, AttrIndexInstruction, AttrIndexContextCondInstruction = classes 414 415 # Where the last operation (defining the attribute owner) yields a 416 # constant... 417 418 target_plus_name = self.optimiser.optimise_constant_accessor() 419 420 # Only try and discover the position if the target can be resolved. 421 # Since instances cannot be constants, this involves classes and 422 # modules. 423 # It is acceptable to replace the instruction providing the constant 424 # input because doing so does not lose any input information required by 425 # the replacement instructions. 426 427 if target_plus_name is not None: 428 target, target_name = target_plus_name 429 430 # Check for class.__class__. 431 432 if attrname == "__class__": 433 if isinstance(target, Class): 434 if AddressInstruction is LoadAddress: 435 self.replace_active_value(LoadAddress(self.get_builtin("type", node))) 436 return 437 else: 438 raise TranslateError("Assigning to __class__ is not permitted.") 439 440 # Access the object table to get the attribute. 441 442 try: 443 attr = self.objtable.access(target_name, attrname) 444 except TableError, exc: 445 raise TranslateError(exc.args[0]) 446 447 # Produce a suitable instruction. 448 449 if AddressInstruction is not None: 450 self.replace_active_value(AddressInstruction(attr)) 451 else: 452 raise TranslateError("Storing of class or module attribute %r via an object is not permitted." % attrname) 453 454 return 455 456 # Where the last operation involves the special 'self' name, check to 457 # see if the attribute is acceptably positioned and produce a direct 458 # access to the attribute. 459 460 # This is the only reliable way of detecting instance accesses at 461 # compile-time since in general, objects could be classes or modules, 462 # but 'self' should only refer to instances. 463 464 elif self.optimiser.optimise_self_access(self.unit, attrname): 465 466 # Either generate an instruction operating on an instance attribute. 467 468 try: 469 attr = self.unit.parent.instance_attributes()[attrname] 470 self.new_op(AttrInstruction(attr)) 471 return 472 473 # Or generate an instruction operating on a class attribute. 474 # NOTE: Any simple instruction providing self is not removed. 475 476 except KeyError: 477 478 try: 479 attr = self.unit.parent.all_attributes()[attrname] 480 481 # Switch the context if the class attribute is compatible with 482 # the instance. 483 484 if attr.defined_within_hierarchy(): 485 486 # Only permit loading (not storing) of class attributes via self. 487 488 if AddressContextInstruction is not None: 489 self.new_op(AddressContextInstruction(attr)) 490 else: 491 raise TranslateError("Storing of class attribute %r via self not permitted." % attrname) 492 493 # Preserve the context if the class attribute comes from an 494 # incompatible class. 495 496 elif attr.defined_outside_hierarchy(): 497 498 # Only permit loading (not storing) of class attributes via self. 499 500 if AddressInstruction is not None: 501 self.new_op(AddressInstruction(attr)) 502 else: 503 raise TranslateError("Storing of class attribute %r via self not permitted." % attrname) 504 505 # Otherwise, test for a suitable context at run-time. 506 507 else: 508 509 # Only permit loading (not storing) of class attributes via self. 510 511 if AddressContextCondInstruction is not None: 512 self.new_op(AddressContextCondInstruction(attr)) 513 else: 514 raise TranslateError("Storing of class attribute %r via self not permitted." % attrname) 515 516 return 517 518 # Or delegate the attribute access to a general instruction 519 # since the kind of attribute cannot be deduced. 520 521 except KeyError: 522 pass 523 524 # Attempt to deduce the target of an attribute access by searching for a 525 # unique type providing the names associated with the accessed object. 526 527 elif self.optimiser.should_optimise_accesses_by_attribute_usage(): 528 529 target_names = self.possible_accessor_types(node) 530 531 if target_names is not None and len(target_names) == 1: 532 target_name, is_static = list(target_names)[0] 533 534 # Check for class.__class__. 535 536 if attrname == "__class__": 537 if is_static: 538 self.load_builtin("type", node) 539 return 540 541 # Access the object table to get the attribute. 542 543 try: 544 attr = self.objtable.access(target_name, attrname) 545 546 # Disallow non-class/instance optimisations. 547 548 except TableError, exc: 549 print "Possible optimisation for", target_name, "not permissable." 550 551 # Produce a suitable instruction. 552 553 else: 554 if AddressContextCondInstruction is not None and attr.is_static_attribute(): 555 self.new_op(AddressContextCondInstruction(attr)) 556 elif AttrInstruction is not None and not attr.is_static_attribute(): 557 self.new_op(AttrInstruction(attr)) 558 else: 559 raise TranslateError("Storing of class or module attribute %r via an object is not permitted." % attrname) 560 561 return 562 563 # Check for class.__class__. 564 565 if attrname == "__class__": 566 567 # Remember the accessor. 568 569 temp_accessor = self.optimiser.optimise_temp_storage() 570 571 attr_block = self.new_block() 572 end_block = self.new_block() 573 574 self.new_op(CheckClass()) 575 self.new_op(JumpIfFalse(attr_block)) 576 self.load_builtin("type", node) 577 self.new_op(Jump(end_block)) 578 self.set_block(attr_block) 579 580 # Recall the accessor. 581 582 self.new_op(temp_accessor) 583 584 # Otherwise, perform a normal operation. 585 586 try: 587 index = self.objtable.get_index(attrname) 588 589 except self.objtable.TableError: 590 591 # If this error arises on generated code, check the names_used 592 # attribute on the Importer. 593 594 raise TranslateError("No attribute entry exists for name %r." % attrname) 595 596 # NOTE: Test for class vs. instance attributes, generating 597 # NOTE: context-related instructions. 598 599 if AttrIndexContextCondInstruction is not None: 600 self.new_op(AttrIndexContextCondInstruction(index)) 601 602 # Store instructions do not need to consider context modifications. 603 604 else: 605 self.new_op(AttrIndexInstruction(index)) 606 607 # Where __class__ was involved, define the start of the following code. 608 609 if attrname == "__class__": 610 self.set_block(end_block) 611 612 # Invocations involve the following: 613 # 614 # 1. Reservation of a frame for the arguments 615 # 2. Identification of the target which is then held in temporary storage 616 # 3. Optional inclusion of a context (important for methods) 617 # 4. Preparation of the argument frame 618 # 5. Invocation of the target 619 # 6. Discarding of the frame 620 # 621 # In order to support nested invocations - such as a(b(c)) - use of the 622 # temporary storage is essential. 623 624 def _startCallFunc(self): 625 626 "Record the location of the invocation." 627 628 op = MakeFrame() 629 self.new_op(op) # records the start of the frame 630 self.frame_makers.append(op) 631 632 def _generateCallFunc(self, args, node): 633 634 """ 635 Support a generic function invocation using the given 'args', occurring 636 on the given 'node', where the expression providing the invocation 637 target has just been generated. 638 639 In other situations, the invocation is much simpler and does not need to 640 handle the full flexibility of a typical Python invocation. Internal 641 invocations, such as those employed by operators and certain 642 control-flow mechanisms, use predetermined arguments and arguably do not 643 need to support the same things as the more general invocations. 644 """ 645 646 target, context, temp_target, temp_context = self._generateCallFuncContext() 647 self._generateCallFuncArgs(target, context, temp_target, temp_context, args, node) 648 return temp_target, target, temp_context 649 650 def _generateCallFuncContext(self): 651 652 """ 653 Produce code which loads and checks the context of the current 654 invocation, the instructions for whose target have already been 655 produced, returning a list of instructions which reference the 656 invocation target. 657 """ 658 659 t = self.optimiser.optimise_known_target() 660 if t: 661 target, context = t 662 663 # Detect dynamic functions acting like instances. 664 665 if isinstance(target, Function) and target.is_dynamic(): 666 target, context = None, None 667 else: 668 target, context = None, None 669 670 # Store the target in temporary storage for subsequent referencing. 671 672 temp_target = 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_target) 679 self.new_op(LoadContext()) 680 temp_context = self.optimiser.optimise_temp_storage() 681 self.new_op(StoreFrame(0)) 682 683 # Class contexts should be made available for testing of the first 684 # argument. 685 # NOTE: Class methods should eventually be supported. 686 687 elif isinstance(context, Class): 688 self.new_op(temp_target) 689 self.new_op(LoadContext()) 690 temp_context = self.optimiser.optimise_temp_storage() 691 692 # Otherwise omit the context. 693 694 else: 695 temp_context = None 696 697 return target, context, temp_target, temp_context 698 699 def _generateCallFuncArgs(self, target, context, temp_target, temp_context, args, node): 700 701 """ 702 Given invocation 'target' and 'context' information, the 'temp_target' 703 reference to the target, the 'temp_context' reference to the context, a 704 list of nodes representing the 'args' (arguments), generate instructions 705 which load the arguments for the invocation defined by the given 'node'. 706 """ 707 708 # Evaluate the arguments. 709 710 employed_positions = set() 711 employed_keywords = set() 712 extra_keywords = [] 713 positional_args = [] 714 keyword_args = [] 715 716 # Find keyword arguments in advance in order to help resolve targets. 717 718 have_keywords = 0 719 720 for arg in args: 721 if isinstance(arg, compiler.ast.Keyword): 722 employed_keywords.add(arg.name) 723 keyword_args.append(arg) 724 have_keywords = 1 725 elif not have_keywords: 726 positional_args.append(arg) 727 728 possible_targets = self.paramtable.all_possible_objects(employed_keywords) 729 730 # Note the presence of the context in the frame where appropriate. 731 732 # For unknown invocations and method invocations. 733 734 if target is None or isinstance(context, Instance): 735 ncontext = 1 736 expect_testable_self = 0 737 738 # Handle calls to classes by obtaining the instantiator function. 739 # A context is reserved for the new instance, but this is not provided 740 # in the invocation (since the instantiator will fill the locals slot 741 # concerned). 742 743 elif isinstance(target, Class): 744 ncontext = 1 745 expect_testable_self = 0 746 target = target.get_instantiator() 747 748 # Method calls via classes. 749 750 elif isinstance(context, Class): 751 ncontext = 0 752 expect_testable_self = 1 753 754 # Function calls. 755 756 else: 757 ncontext = 0 758 expect_testable_self = 0 759 760 # Traverse the positional arguments adding them using the incrementing 761 # frame position. 762 763 first = 1 764 frame_pos = ncontext 765 temp_first_argument = None 766 767 for arg in positional_args: 768 self.dispatch(arg) 769 self.new_op(StoreFrame(frame_pos)) 770 employed_positions.add(frame_pos) 771 772 # Check to see if the first argument is appropriate (compatible with 773 # the target where methods are being invoked via classes). 774 775 if first and (expect_testable_self or target is None): 776 777 # Drop any test if the target and the context are known. 778 779 if not self.optimiser.have_correct_self_for_target(context, self.unit): 780 781 # Otherwise, remember the first argument for a subsequent 782 # test. 783 784 temp_first_argument = self.optimiser.optimise_temp_storage() 785 786 first = 0 787 frame_pos += 1 788 789 # Adjust the invocation frame for unknown invocations. 790 # Test the first argument if appropriate. 791 792 self._generateCallFuncContextTest(temp_target, target, temp_context, temp_first_argument, node) 793 794 # Traverse the keyword arguments adding them at the appropriate frame 795 # positions. 796 797 max_keyword_pos = -1 798 799 for arg in keyword_args: 800 801 # Optimise where the target is known now. 802 803 if target is not None: 804 805 # Find the parameter table entry for the target. 806 807 target_name = target.full_name() 808 809 # Look for a callable with the precise target name. 810 811 table_entry = self.paramtable.table[target_name] 812 813 # Look the name up in the parameter table entry. 814 815 try: 816 pos = table_entry[arg.name] 817 818 # Where no position is found, this could be an extra keyword 819 # argument. 820 821 except KeyError: 822 extra_keywords.append(arg) 823 continue 824 825 # Test for illegal conditions. 826 827 if pos in employed_positions: 828 raise TranslateError("Keyword argument %r overwrites parameter %r." % (arg.name, pos)) 829 830 employed_positions.add(pos) 831 832 # Generate code for the keyword and the positioning 833 # operation. 834 835 self.dispatch(arg.expr) 836 self.new_op(StoreFrame(pos)) 837 838 # Otherwise, generate the code needed to obtain the details of 839 # the parameter location. 840 841 else: 842 843 # Combine the target details with the name to get the location. 844 # See the access method on the List class. 845 846 try: 847 paramindex = self.paramtable.get_index(arg.name) 848 849 # Where no position is found, this could be an extra keyword 850 # argument. 851 852 except self.paramtable.TableError: 853 extra_keywords.append(arg) 854 continue 855 856 # Generate code for the keyword and the positioning 857 # operation. Get the value as the source of the assignment. 858 859 self.dispatch(arg.expr) 860 self.record_value() 861 862 # Store the source value using the callable's parameter 863 # table information. 864 865 self.new_op(temp_target) 866 self.new_op(StoreFrameIndex(paramindex)) 867 868 self.set_source() 869 self.discard_value() 870 871 # Record the highest possible frame position for this argument. 872 873 max_keyword_pos = max(max_keyword_pos, max(self.paramtable.all_attribute_positions(arg.name))) 874 875 # Use the frame position counter as a general argument counter. 876 877 frame_pos += 1 878 879 # NOTE: Extra keywords are not supported. 880 # NOTE: Somehow, the above needs to be combined with * arguments. 881 882 if extra_keywords: 883 print "Warning: extra keyword argument(s) %s not handled." % ", ".join([arg.name for arg in extra_keywords]) 884 885 # Either test for a complete set of arguments. 886 887 if target is not None: 888 889 # Make sure that enough arguments have been given. 890 891 nargs_max = len(target.positional_names) 892 ndefaults = len(target.defaults) 893 nargs_min = nargs_max - ndefaults 894 895 # Visit each argument position and look for a supplied argument. 896 897 for i in range(ncontext, nargs_min): 898 if i not in employed_positions: 899 raise TranslateError( 900 "Argument %r not supplied for %r: need at least %d argument(s)." % (i+1, target.name, nargs_min)) 901 902 nargs = frame_pos 903 904 # Determine whether too many arguments have been given and how big 905 # the frame should be. 906 907 # For parameter lists with * or ** parameters, accept as many 908 # arguments as are allowed or as many as we have. 909 910 if target.has_star or target.has_dstar: 911 frame_size = max(nargs, nargs_max) 912 913 # NOTE: We now need to pack these arguments into a suitable 914 # NOTE: structure for the * parameter. 915 916 # For other parameter lists, only accept as many arguments as we are 917 # allowed. 918 919 elif nargs > nargs_max: 920 raise TranslateError( 921 "Too many arguments for %r: need at most %d argument(s)." % (target.name, nargs_max)) 922 923 else: 924 frame_size = nargs_max 925 926 # Where defaults are involved, put them into the frame. 927 928 self._generateCallFuncDefaultArgs(target, temp_target, nargs_min, nargs_max, employed_positions) 929 930 # Set the frame size. 931 932 self._endCallFuncArgs(frame_size) 933 934 # Or just set the frame size and have the function check the arguments. 935 936 else: 937 max_pos = max(max(employed_positions or [-1]), max_keyword_pos, frame_pos - 1) 938 self._endCallFuncArgs(max_pos + 1) 939 940 def _generateCallFuncDefaultArgs(self, target, temp_target, nargs_min, nargs_max, employed_positions): 941 942 """ 943 For the given 'target' and 'temp_target' reference to the target, 944 generate default arguments for those positions in the range 945 'nargs_min'...'nargs_max' which are not present in the 946 'employed_positions' collection. 947 """ 948 949 # Where appropriate, construct a dynamic object to hold the defaults. 950 951 dynamic = target.is_dynamic() 952 953 # Here, we use negative index values to visit the right hand end of 954 # the defaults list. 955 956 for pos in range(nargs_min, nargs_max): 957 if pos not in employed_positions: 958 if dynamic: 959 self.new_op(temp_target) 960 self.new_op(LoadAttr(target.default_attrs[pos - nargs_min])) 961 else: 962 self.new_op(LoadAddress(target.default_attrs[pos - nargs_min])) 963 self.new_op(StoreFrame(pos)) 964 965 def _generateCallFuncContextTest(self, temp_target, target, temp_context, temp_first_argument, node): 966 967 """ 968 Generate code to test for 'temp_target', representing the given 969 'target', the context provided by 'temp_context' against 970 'temp_first_argument', and to signal an exception (using 'node') if the 971 context is incompatible with the first frame argument. 972 973 In addition, the invocation frame will be shifted if 'temp_context' 974 indicates a function or a class. 975 """ 976 977 adjust_block = self.new_block() 978 continue_block = self.new_block() 979 980 # Add some preliminary tests where the target is not known. 981 982 if target is None: 983 984 # Adjust the frame if a replaceable context is provided. 985 986 self.new_op(temp_context) 987 self.new_op(CheckContext()) 988 self.new_op(JumpIfFalse(adjust_block)) 989 990 # Skip adjustment and tests if the context is not a class. 991 # Classes themselves employ a placeholder context so that 992 # instantiators can be callable with a context which will be 993 # overwritten in the frame. 994 995 self.new_op(temp_context) 996 self.new_op(CheckClass()) 997 self.new_op(JumpIfFalse(continue_block)) 998 999 if temp_first_argument is not None: 1000 self.new_op(temp_first_argument) 1001 1002 # Check the current value (the argument) against the known context 1003 # (given as the source). 1004 1005 self.new_op(CheckInstance()) 1006 self.optimiser.set_source(temp_context) 1007 1008 self.new_op(JumpIfTrue(adjust_block)) 1009 1010 # Where the context is inappropriate, drop the incomplete frame and 1011 # raise an exception. 1012 1013 self.new_op(DropFrame()) 1014 self.new_op(LoadResult()) 1015 1016 self.make_exception("TypeError", node) 1017 self.new_op(StoreException()) 1018 self.new_op(RaiseException()) 1019 1020 if target is None or temp_first_argument is not None: 1021 self.set_block(adjust_block) 1022 self.new_op(AdjustFrame(1)) 1023 1024 self.set_block(continue_block) 1025 1026 def _doCallFunc(self, temp_target, target=None): 1027 1028 "Make the invocation." 1029 1030 # For classes, the target itself is used, since the instantiator will be 1031 # obtained via the class. 1032 1033 if isinstance(target, (Class, Function)): 1034 self.new_op(JumpWithFrameDirect(target)) 1035 else: 1036 self.new_op(temp_target) 1037 self.new_op(LoadCallable()) 1038 self.new_op(JumpWithFrame()) 1039 1040 def _endCallFuncArgs(self, nargs): 1041 1042 "Set the frame size." 1043 1044 self.frame_makers[-1].attr = nargs 1045 self.frame_makers.pop() 1046 1047 def _endCallFunc(self, temp_target=None, temp_context=None, load_result=1): 1048 1049 "Finish the invocation and tidy up afterwards." 1050 1051 self.new_op(DropFrame()) 1052 if load_result: 1053 self.new_op(LoadResult()) 1054 1055 # Discard any temporary storage instructions. 1056 1057 if temp_target is not None: 1058 self.discard_temp(temp_target) 1059 1060 if temp_context is not None: 1061 self.discard_temp(temp_context) 1062 1063 def _visitFunctionDeclaration(self, node): 1064 1065 """ 1066 Visit the function declaration at 'node', which can be a lambda or a 1067 named function. As a consequence an instruction will be generated which 1068 provides a reference to the function. 1069 """ 1070 1071 fn = node.unit 1072 ndefaults = len(fn.defaults) 1073 temp = self._generateFunctionDefaults(fn) 1074 1075 # Populate the new object required for the function. 1076 1077 if temp is not None: 1078 self.new_op(LoadConst(fn)) 1079 self.new_op(LoadCallable()) 1080 self.new_op(temp) 1081 self.new_op(StoreCallable()) 1082 1083 self.new_op(temp) 1084 #self.discard_temp(temp) 1085 else: 1086 self.new_op(LoadFunction(fn)) 1087 1088 def _visitFunctionDefinition(self, node): 1089 1090 """ 1091 Visit the function definition at 'node', which can be a lambda or a 1092 named function, generating the prelude with argument and default 1093 checking, plus the body of the function itself. 1094 """ 1095 1096 # Check frames using the function's details. 1097 1098 fn = node.unit 1099 nparams = len(fn.positional_names) 1100 ndefaults = len(fn.defaults) 1101 1102 fn.body_block = self.new_block() 1103 1104 # Check the number of parameters and defaults. 1105 1106 self.new_op(CheckFrame((nparams, ndefaults))) 1107 1108 if ndefaults > 0: 1109 if fn.is_dynamic(): 1110 self.new_op(LoadTemp(0)) # context provides storage 1111 else: 1112 self.new_op(LoadFunction(fn)) 1113 1114 self.new_op(FillDefaults((nparams, ndefaults))) 1115 1116 # Produce the body. 1117 1118 self.set_block(fn.body_block) 1119 1120 extend = ExtendFrame() 1121 self.new_op(extend) 1122 1123 # Perform tuple assignment for any tuple parameters. 1124 1125 self._visitFunctionTupleParameters(fn, node) 1126 1127 # For functions with star parameters, make a special list for the 1128 # extra arguments and re-map the parameter. 1129 1130 if fn.has_star: 1131 self.new_op(CopyExtra(nparams)) 1132 1133 # Ensure that the star parameter has a slot in the frame. 1134 1135 self.new_op(CheckExtra(nparams)) 1136 self.new_op(StoreTemp(nparams)) 1137 1138 # Add any attribute usage guards. 1139 1140 self._generateGuards(node) 1141 1142 # Visit the actual code. 1143 1144 self.dispatch(node.code) 1145 1146 # Add a return statement where one is not already produced. 1147 1148 if not isinstance(self.last_op(), Return): 1149 1150 # Return None for normal functions without explicit return 1151 # statements. 1152 1153 if not fn.is_lambda(): 1154 self.dispatch(compiler.ast.Name("None")) 1155 1156 self.new_op(StoreResult()) 1157 self.new_op(Return()) 1158 1159 # Make sure that enough frame space is reserved from the start. 1160 1161 self.set_frame_usage(node, extend) 1162 1163 def _visitFunctionTupleParameters(self, fn, node, parameters=None): 1164 1165 """ 1166 Visit the tuple parameters for function 'fn', obtaining the appropriate 1167 elements from each supplied argument and assigning them to the specified 1168 names for each parameter. 1169 """ 1170 1171 if parameters is not None: 1172 self._generateAttr(node, "__getitem__", self.attribute_load_instructions) 1173 temp_getitem = self.optimiser.optimise_temp_storage() 1174 1175 for i, parameter in parameters or fn.tuple_parameters(): 1176 1177 # Either load the parameter from the frame. 1178 1179 if parameters is None: 1180 self.new_op(LoadName(Attr(i, None, None))) 1181 1182 # Or load a value from the current collection. 1183 1184 else: 1185 self._startCallFunc() 1186 self.new_op(temp_getitem) 1187 temp_target, target, temp_context = self._generateCallFunc([compiler.ast.Const(i)], node) 1188 self._doCallFunc(temp_target, target) 1189 self._endCallFunc() 1190 1191 # Where a tuple is the target, attempt to descend into the value 1192 # obtained. 1193 1194 if isinstance(parameter, list): 1195 self._visitFunctionTupleParameters(fn, node, parameter) 1196 1197 # Store the item in the namespace entry for the given name. 1198 1199 else: 1200 self.record_value() 1201 self.new_op(StoreName(fn[parameter])) 1202 self.set_source() 1203 self.discard_value() 1204 1205 if parameters is not None: 1206 self.discard_temp(temp_getitem) 1207 1208 def _generateFunctionDefaults(self, function): 1209 1210 """ 1211 Generate the default initialisation code for 'function', returning 1212 a temporary storage reference if a dynamic object was created for the 1213 function. 1214 """ 1215 1216 attr_to_default = zip(function.default_attrs, function.defaults) 1217 if not attr_to_default: 1218 return None 1219 1220 # Where non-constant defaults are involved, construct a dynamic object 1221 # to hold the defaults. 1222 1223 dynamic = function.is_dynamic() 1224 1225 if dynamic: 1226 self.make_instance(self.get_builtin_class("function", function), len(attr_to_default)) 1227 temp = self.get_temp() 1228 1229 for attr, default in attr_to_default: 1230 self.dispatch(default) 1231 1232 self.record_value() 1233 if dynamic: 1234 self.new_op(temp) 1235 self.new_op(StoreAttr(attr)) 1236 else: 1237 self.new_op(StoreAddress(attr)) 1238 self.set_source() 1239 self.discard_value() 1240 1241 if dynamic: 1242 return temp 1243 else: 1244 return None 1245 1246 def _visitName(self, node, classes): 1247 1248 """ 1249 Visit the name-related 'node', generating instructions based on the 1250 given 'classes'. 1251 """ 1252 1253 name = node.name 1254 1255 # Get the expected scope of the name. 1256 1257 scope = getattr(node, "_scope", None) or self.get_scope(name) 1258 self._generateName(name, scope, classes, node) 1259 1260 def _generateName(self, name, scope, classes, node): 1261 1262 """ 1263 Generate code for the access to 'name' in 'scope' using the given 1264 'classes', and using the given 'node' as the source of the access. 1265 """ 1266 1267 NameInstruction, AddressInstruction, AddressContextInstruction = classes 1268 1269 # Handle names referring to constants. 1270 1271 if scope == "constant": 1272 const = self.importer.get_predefined_constant(name) 1273 self.new_op(LoadConst(const)) 1274 1275 # Handle all other names. 1276 1277 elif scope == "local": 1278 unit = self.unit 1279 if isinstance(unit, Function): 1280 self.new_op(NameInstruction(unit.all_locals()[name])) 1281 elif isinstance(unit, Class): 1282 if AddressContextInstruction is not None: 1283 self.new_op(LoadConst(unit)) 1284 self.new_op(AddressContextInstruction(unit.all_class_attributes()[name])) 1285 else: 1286 self.new_op(AddressInstruction(unit.all_class_attributes()[name])) 1287 elif isinstance(unit, Module): 1288 self.new_op(AddressInstruction(unit.module_attributes()[name])) 1289 else: 1290 raise TranslateError("Program unit has no local %r." % name) 1291 1292 elif scope == "global": 1293 globals = self.module.module_attributes() 1294 if globals.has_key(name): 1295 self.new_op(AddressInstruction(globals[name])) 1296 else: 1297 raise TranslateError("Module has no attribute %r." % name) 1298 1299 elif scope == "builtins": 1300 self.new_op(AddressInstruction(self.get_builtin(name, node))) 1301 1302 else: 1303 # NOTE: This may happen because a class attribute is optimised away. 1304 print "Program unit uses unknown name %r." % name 1305 1306 def _visitUnary(self, node): 1307 1308 """ 1309 Invoke the appropriate operator module function for the operation 1310 represented by 'node'. 1311 """ 1312 1313 temp_fn = self._getOperatorFunction(node) 1314 self._visitCall(node, temp_fn, (node.expr,)) 1315 self.discard_temp(temp_fn) 1316 1317 def _visitBinaryBit(self, node): 1318 1319 """ 1320 Need to impose binary rules over a sequence of nodes. The 1321 short-circuiting of the similar logical operators is not imposed by the 1322 bitwise operators. 1323 """ 1324 1325 temp_fn = self._getOperatorFunction(node) 1326 left = None 1327 1328 for right in node.nodes: 1329 if left is not None: 1330 self._visitCall(node, temp_fn, (left, right)) 1331 left = right 1332 1333 self.discard_temp(temp_fn) 1334 1335 def _visitBinary(self, node): 1336 1337 """ 1338 Invoke the appropriate operator module function for the operation 1339 represented by 'node'. 1340 """ 1341 1342 temp_fn = self._getOperatorFunction(node) 1343 self._visitCall(node, temp_fn, (node.left, node.right)) 1344 self.discard_temp(temp_fn) 1345 1346 def _visitCall(self, node, temp_fn, args): 1347 1348 """ 1349 Invoke the appropriate operator module function for the operation 1350 represented by 'node', given a 'temp_fn' reference to a function, along 1351 with the 'args' (the operand nodes). 1352 """ 1353 1354 # Evaluate and store the operands in temporary storage. 1355 1356 temp_list = [] 1357 1358 for arg in args: 1359 self.dispatch(arg) 1360 temp_list.append(self.optimiser.optimise_temp_storage()) 1361 1362 self._generateInvocation(temp_fn, temp_list) 1363 1364 # Compilation duties... 1365 1366 for temp in temp_list: 1367 self.discard_temp(temp) 1368 1369 def _generateInvocation(self, temp_fn, temp_list): 1370 1371 """ 1372 Invoke the function 'temp_fn' using the operands from 'temp_list' as 1373 arguments. 1374 """ 1375 1376 self._startCallFunc() 1377 1378 for i, temp in enumerate(temp_list): 1379 self.new_op(temp) 1380 self.new_op(StoreFrame(i)) 1381 1382 self._endCallFuncArgs(len(temp_list)) 1383 self._doCallFunc(temp_fn) 1384 self._endCallFunc(temp_fn) 1385 1386 def _getOperatorFunction(self, node, operator_name=None): 1387 1388 "Return an operator function reference for the given 'node'." 1389 1390 return self._generateOperatorFunction(operator_name or node.__class__.__name__) 1391 1392 def _getOperatorAugAssignFunction(self, node): 1393 1394 """ 1395 Return an operator augmented assignment function reference for the given 1396 'node'. 1397 """ 1398 1399 return self._generateOperatorFunction(node.op) 1400 1401 def _generateOperatorFunction(self, opname): 1402 1403 "Return an operator function reference for the given 'opname'." 1404 1405 operator_fn = operator_functions[opname] 1406 1407 # Get the operator module. 1408 1409 operator_module = self.importer.get_module("operator") 1410 1411 # Get the appropriate function from the operator module. 1412 1413 self.new_op(LoadAddress(operator_module[operator_fn])) 1414 return self.optimiser.optimise_temp_storage() 1415 1416 def _handleAttributeError(self, node, temp_method, handled_block): 1417 1418 """ 1419 Add exception handling to the method acquisition instructions where the 1420 attribute access cannot be resolved at compile-time. 1421 """ 1422 1423 if not (self.optimiser.should_optimise_known_target() and self.optimiser.is_constant_input(temp_method)): 1424 self.load_builtin("AttributeError", node) 1425 self.new_op(CheckException()) 1426 self.new_op(JumpIfTrue(handled_block)) 1427 self.new_op(RaiseException()) 1428 1429 def _generateTuple(self, node): 1430 1431 "Make a tuple using the given program 'node'." 1432 1433 # Reserve space for the elements themselves. 1434 1435 self.make_instance(self.get_builtin_class("tuple", node), len(node.nodes)) 1436 temp = self.get_temp() 1437 1438 # Store using 0-based index values. 1439 1440 self._populateSequence(temp, node) 1441 1442 self.new_op(temp) 1443 self.discard_temp(temp) 1444 1445 def _generateList(self, node): 1446 1447 "Make a list using the given program 'node'." 1448 1449 # Make a fragment containing the list elements. 1450 1451 self.new_op(MakeFragment(len(node.nodes) + 1)) 1452 temp = self.get_temp() 1453 self._populateSequence(temp, node) 1454 self.new_op(temp) 1455 self.record_value() 1456 1457 # Reserve space for _elements (the fragment reference). 1458 1459 self.make_instance(self.get_builtin_class("list", node), 1) 1460 list_temp = self.get_temp() 1461 self.new_op(list_temp) 1462 self.new_op(StoreAttr(Attr(0, None, None))) # _elements is at position 0 1463 self.set_source() 1464 self.discard_value() 1465 1466 self.new_op(list_temp) 1467 self.discard_temp(temp) 1468 self.discard_temp(list_temp) 1469 1470 def _populateSequence(self, temp, node, offset=0): 1471 1472 """ 1473 Populate a sequence using the given 'temp' reference and program 'node'. 1474 """ 1475 1476 for i, n in enumerate(node.nodes): 1477 self.dispatch(n) 1478 self.record_value() 1479 self.new_op(temp) 1480 self.new_op(StoreAttr(Attr(i + offset, None, None))) 1481 self.set_source() 1482 self.discard_value() 1483 1484 def _generateTestBoolean(self, node, temp): 1485 1486 """ 1487 Generate a test of the boolean status of the current value for the given 1488 program 'node'. 1489 """ 1490 1491 # Get method on temp. 1492 # NOTE: Using __bool__ instead of __nonzero__. 1493 1494 self._generateAttr(node, "__bool__", self.attribute_load_instructions) 1495 temp_method = self.optimiser.optimise_temp_storage() 1496 1497 self._generateInvocation(temp_method, (temp,)) 1498 1499 self.discard_temp(temp_method) 1500 1501 # Convert result to boolean (a StoreBoolean operation). 1502 1503 self.new_op(TestIdentityAddress(self.importer.get_predefined_constant("True"))) 1504 1505 def _generateLoadBoolean(self, node): 1506 1507 """ 1508 Generate instructions to load the appropriate value given the current 1509 boolean status. 1510 """ 1511 1512 true_block = self.new_block() 1513 end_block = self.new_block() 1514 1515 self.new_op(JumpIfTrue(true_block)) 1516 self.new_op(LoadConst(self.importer.get_predefined_constant("False"))) 1517 self.new_op(Jump(end_block)) 1518 1519 self.set_block(true_block) 1520 self.new_op(LoadConst(self.importer.get_predefined_constant("True"))) 1521 1522 self.set_block(end_block) 1523 1524 def _visitPrint(self, node, function_name): 1525 self._startCallFunc() 1526 self.load_builtin(function_name, node) 1527 1528 args = [node.dest or compiler.ast.Name("None")] + node.nodes 1529 1530 temp_target, target, temp_context = self._generateCallFunc(args, node) 1531 self._doCallFunc(temp_target, target) 1532 self._endCallFunc(temp_target, temp_context) 1533 1534 # vim: tabstop=4 expandtab shiftwidth=4