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