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