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