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