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