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