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