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