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