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