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