1 #!/usr/bin/env python 2 3 """ 4 Translate the AST of a Python program into a more interpretable representation. 5 6 Copyright (C) 2007, 2008, 2009, 2010 Paul Boddie <paul@boddie.org.uk> 7 8 This program is free software; you can redistribute it and/or modify it under 9 the terms of the GNU General Public License as published by the Free Software 10 Foundation; either version 3 of the License, or (at your option) any later 11 version. 12 13 This program is distributed in the hope that it will be useful, but WITHOUT 14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 16 details. 17 18 You should have received a copy of the GNU General Public License along with 19 this program. If not, see <http://www.gnu.org/licenses/>. 20 """ 21 22 from micropython.common import * 23 from micropython.data import * 24 from micropython.rsvp import * 25 import compiler.ast 26 27 class Helper: 28 29 "Internal helper methods for AST visitors." 30 31 # Allocation-related methods. 32 33 def make_instance(self, cls, n): 34 35 """ 36 Request a new instance using the given class 'cls' and with 'n' 37 attributes. 38 """ 39 40 # Load the class in order to locate the instance template. 41 42 self.new_op(LoadConst(cls)) 43 44 # NOTE: Instance headers are one location. 45 46 self.new_op(MakeInstance(n + 1)) 47 48 def make_exception(self, name, node): 49 50 "Make an exception of the given 'name' using 'node'." 51 52 # NOTE: Reserving only one attribute. 53 54 self.make_instance(self.get_builtin_class(name, node), 1) 55 56 # Name-related methods. 57 58 def get_scope(self, name): 59 60 "Return the scope for the given 'name'." 61 62 if self.unit.has_key(name): 63 return "local" 64 elif self.module.has_key(name): 65 return "global" 66 else: 67 return "builtins" 68 69 def load_builtin(self, name, node): 70 71 "Generate an instruction loading 'name' for the given 'node'." 72 73 self.new_op(LoadAddress(self.get_builtin(name, node))) 74 75 def get_builtin_class(self, name, node): 76 77 "Return the built-in class with the given 'name' for the given 'node'." 78 79 return self.get_builtin(name, node).get_value() 80 81 def get_builtin(self, name, node): 82 83 """ 84 Return the built-in module definition for the given 'name', used by the 85 given 'node'. 86 """ 87 88 if self.builtins is not None: 89 try: 90 return self.builtins[name] 91 except KeyError: 92 raise TranslateError(self.module.full_name(), node, "No __builtins__ definition is available for name %r." % name) 93 else: 94 raise TranslateError(self.module.full_name(), node, "No __builtins__ module is available for name %r." % name) 95 96 # Code feature methods. 97 98 def new_block(self): 99 100 "Return a new code block." 101 102 return Block() 103 104 def set_block(self, block): 105 106 "Add the given 'block' to the unit's list of blocks." 107 108 self.optimiser.reset() 109 self.blocks.append(block) 110 111 def get_loop_blocks(self): 112 return self.loop_blocks[-1] 113 114 def add_loop_blocks(self, next_block, exit_block): 115 self.loop_blocks.append((next_block, exit_block)) 116 117 def drop_loop_blocks(self): 118 self.loop_blocks.pop() 119 120 def get_exception_blocks(self): 121 return self.exception_blocks[-1] 122 123 def add_exception_blocks(self, handler_block, exit_block): 124 self.exception_blocks.append((handler_block, exit_block)) 125 126 def drop_exception_blocks(self): 127 self.exception_blocks.pop() 128 129 # Assignment expression values. 130 131 def record_value(self, immediate=1): 132 133 """ 134 Record the current active value for an assignment. If the optional 135 'immediate' parameter if set to a false value always allocates new 136 temporary storage to hold the recorded value; otherwise, the 137 value-providing instruction may be replicated in order to provide the 138 active value later on. 139 """ 140 141 if immediate: 142 temp = self.optimiser.optimise_temp_storage() 143 else: 144 temp = self.get_temp() 145 self.expr_temp.append(temp) 146 147 def discard_value(self): 148 149 "Discard any temporary storage in use for the current assignment value." 150 151 self.discard_temp(self.expr_temp.pop()) 152 153 def set_source(self): 154 155 """ 156 Set the source of an assignment using the current assignment value. This 157 sets the source input for the current instruction. 158 """ 159 160 self.optimiser.set_source(self.expr_temp[-1]) 161 162 # Optimise away constant storage if appropriate. 163 164 if self.optimiser.optimise_constant_storage(): 165 self.remove_op() 166 167 def is_immediate_user(self, node): 168 169 """ 170 Return whether 'node' is an immediate user of an assignment expression. 171 """ 172 173 return isinstance(node, (compiler.ast.AssName, compiler.ast.AssAttr)) 174 175 def has_immediate_usage(self, nodes): 176 177 """ 178 Return whether 'nodes' are all immediate users of an assignment expression. 179 """ 180 181 for n in nodes: 182 if not self.is_immediate_user(n): 183 return 0 184 return 1 185 186 # Temporary storage administration. 187 188 def get_temp(self): 189 190 """ 191 Add a temporary storage instruction for the current value and return a 192 sequence of access instructions. 193 """ 194 195 position_in_frame = self.reserve_temp() 196 self.new_op(StoreTemp(position_in_frame)) 197 return LoadTemp(position_in_frame) 198 199 def reserve_temp(self, temp_position=None): 200 201 """ 202 Reserve a new temporary storage position, or if the optional 203 'temp_position' is specified, ensure that this particular position is 204 reserved. 205 """ 206 207 if temp_position is not None: 208 pass 209 elif not self.temp_positions: 210 temp_position = 0 211 else: 212 temp_position = max(self.temp_positions) + 1 213 214 self.temp_positions.add(temp_position) 215 self.max_temp_position = max(self.max_temp_position, temp_position) 216 return self.unit.all_local_usage + temp_position # position in frame 217 218 def ensure_temp(self, instruction=None): 219 220 """ 221 Ensure that the 'instruction' is using a reserved temporary storage 222 position. 223 """ 224 225 if isinstance(instruction, LoadTemp): 226 temp_position = instruction.attr - self.unit.all_local_usage 227 self.reserve_temp(temp_position) 228 229 def discard_temp(self, instruction=None): 230 231 "Discard any temporary storage position used by 'instruction'." 232 233 if isinstance(instruction, LoadTemp): 234 temp_position = instruction.attr - self.unit.all_local_usage 235 self.free_temp(temp_position) 236 237 def free_temp(self, temp_position): 238 239 "Free the temporary storage position specified by 'temp_position'." 240 241 if temp_position in self.temp_positions: 242 self.temp_positions.remove(temp_position) 243 244 def set_frame_usage(self, node, extend): 245 246 """ 247 Ensure that the frame usage for the unit associated with 'node' is set 248 on the 'extend' instruction. 249 """ 250 251 ntemp = self.max_temp_position + 1 252 extend.attr = ntemp + node.unit.local_usage # NOTE: See get_code for similar code. 253 254 # Code writing methods. 255 256 def new_op(self, op): 257 258 """ 259 Add 'op' to the generated code, returning a true value if an instruction 260 was added. 261 """ 262 263 # Optimise load operations employed by this instruction. 264 265 self.optimiser.optimise_load_operations(op) 266 if self.optimiser.optimise_away_no_operations(op) or self.optimiser.optimise_unused_handlers(op): 267 return 0 268 269 # Add the operation to the current block. 270 271 self.blocks[-1].code.append(op) 272 self.optimiser.set_new(op) 273 return 1 274 275 def remove_op(self): 276 277 "Remove the last instruction." 278 279 op = self.blocks[-1].code.pop() 280 self.optimiser.clear_active() 281 282 def replace_op(self, op): 283 284 "Replace the last added instruction with 'op'." 285 286 self.remove_op() 287 self.new_op(op) 288 289 def replace_active_value(self, op): 290 291 """ 292 Replace the value-providing active instruction with 'op' if appropriate. 293 """ 294 295 self.optimiser.remove_active_value() 296 self.new_op(op) 297 298 def last_op(self): 299 300 "Return the last added instruction." 301 302 try: 303 return self.blocks[-1].code[-1] 304 except IndexError: 305 return None 306 307 # Common methods. 308 309 def _generateGuards(self, node): 310 311 if not (self.optimiser.should_optimise_accesses_by_attribute_usage() and hasattr(node, "_attrnames")): 312 return 313 314 # For each name, attempt to restrict the type employed. 315 316 for name, names_used in node._attrnames.items(): 317 318 # Consider alternatives. 319 320 if node._alternative_attrnames.has_key(name): 321 all_names_used = set() 322 all_names_used.update(node._alternative_attrnames[name]) 323 all_names_used.add(tuple(names_used)) 324 else: 325 all_names_used = [names_used] 326 327 # Get the names of all object types supporting these names. 328 329 targets = set() 330 common_targets = None 331 332 for names_used in all_names_used: 333 found_targets = self.objtable.all_possible_objects_plus_status(names_used) 334 found_target_names = [target_name for (target_name, is_static) in found_targets] 335 targets.update(found_targets) 336 337 if common_targets is None: 338 common_targets = set(found_target_names) 339 else: 340 common_targets.intersection_update(found_target_names) 341 342 # Report cases where no common targets can be found. 343 344 if not common_targets: 345 raise TranslateError(self.module.full_name(), node, "No common types found for expected attribute usage.") 346 347 # NOTE: Need to merge targets using the same type but suggesting 348 # NOTE: different kinds of attributes. 349 350 # Where only one object type is suggested, produce a guard. 351 # NOTE: This only supports classes as types, not modules. 352 353 if len(targets) == 1: 354 target_name, is_static = list(targets)[0] 355 356 # Access the object table to get the attribute. 357 # NOTE: This depends on the special entry in the table 358 # NOTE: for class equivalence tests. 359 360 try: 361 obj = self.objtable.access(target_name, target_name) 362 363 # Where no attribute entry exists, the target could be a module. 364 365 except TableError, exc: 366 print "Possible guard for", target_name, "not enforceable." 367 continue 368 369 # NOTE: Could test the correctness of the guard where the nature 370 # NOTE: of the name is known. 371 # NOTE: The known value would be retrieved from the unit's 372 # NOTE: locals and tested as being a class or an instance of a 373 # NOTE: particular class. 374 375 # Generate the guard by loading a reference to the class. 376 377 after_test_block = self.new_block() 378 379 self.new_op(LoadClass(obj)) 380 temp_target = self.optimiser.optimise_temp_storage() 381 382 # For only static attributes, classes are acceptable. 383 384 if is_static: 385 386 # Generate name is target (for classes). 387 388 self.dispatch(compiler.ast.Name(name)) 389 self.new_op(TestIdentity()) 390 self.optimiser.set_source(temp_target) 391 392 # Jump to the next guard or the code if successful. 393 394 self.new_op(JumpIfTrue(after_test_block)) 395 396 # Where instance attributes are involved, only instances are 397 # acceptable. 398 399 # Generate isinstance(name, target). 400 401 self.dispatch(compiler.ast.Name(name)) 402 self.new_op(CheckInstance()) 403 self.optimiser.set_source(temp_target) 404 405 # Jump to the next guard or the code if successful. 406 407 self.new_op(JumpIfTrue(after_test_block)) 408 409 # Where the type is inappropriate, raise an exception. 410 411 self.make_exception("TypeError", node) 412 self.new_op(StoreException()) 413 self.new_op(RaiseException()) 414 415 self.set_block(after_test_block) 416 417 def _visitAttr(self, node, classes): 418 419 """ 420 Visit the attribute-related 'node', generating instructions based on the 421 given 'classes'. 422 """ 423 424 self.dispatch(node.expr) 425 self._generateAttr(node, node.attrname, classes) 426 427 def _generateAttr(self, node, attrname, classes): 428 429 """ 430 Generate code for the access to 'attrname' using the given 'classes'. 431 """ 432 433 AddressInstruction, AddressContextInstruction, AddressContextCondInstruction, \ 434 AttrInstruction, AttrIndexInstruction, AttrIndexContextCondInstruction = classes 435 436 # Where the last operation (defining the attribute owner) yields a 437 # constant... 438 439 target_name = self.optimiser.optimise_constant_accessor() 440 441 # Only try and discover the position if the target can be resolved. 442 # Since instances cannot be constants, this involves classes and 443 # modules. 444 445 if target_name is not None: 446 447 # Access the object table to get the attribute. 448 449 try: 450 attr = self.objtable.access(target_name, attrname) 451 except TableError, exc: 452 raise TranslateError(self.module.full_name(), node, exc.args[0]) 453 454 # Produce a suitable instruction. 455 456 if AddressInstruction is not None: 457 self.replace_active_value(AddressInstruction(attr)) 458 else: 459 raise TranslateError(self.module.full_name(), node, 460 "Storing of class or module attribute %r via an object is not permitted." % attrname) 461 462 return 463 464 # Where the last operation involves the special 'self' name, check to 465 # see if the attribute is acceptably positioned and produce a direct 466 # access to the attribute. 467 468 # This is the only reliable way of detecting instance accesses at 469 # compile-time since in general, objects could be classes or modules, 470 # but 'self' should only refer to instances. 471 472 elif self.optimiser.optimise_self_access(self.unit, attrname): 473 474 # Either generate an instruction operating on an instance attribute. 475 476 try: 477 attr = self.unit.parent.instance_attributes()[attrname] 478 self.new_op(AttrInstruction(attr)) 479 return 480 481 # Or generate an instruction operating on a class attribute. 482 # NOTE: Any simple instruction providing self is not removed. 483 484 except KeyError: 485 486 try: 487 attr = self.unit.parent.all_attributes()[attrname] 488 489 # Switch the context if the class attribute is compatible with 490 # the instance. 491 492 if attr.defined_within_hierarchy(): 493 494 # Only permit loading (not storing) of class attributes via self. 495 496 if AddressContextInstruction is not None: 497 self.new_op(AddressContextInstruction(attr)) 498 else: 499 raise TranslateError(self.module.full_name(), node, 500 "Storing of class attribute %r via self not permitted." % attrname) 501 502 # Preserve the context if the class attribute comes from an 503 # incompatible class. 504 505 elif attr.defined_outside_hierarchy(): 506 507 # Only permit loading (not storing) of class attributes via self. 508 509 if AddressInstruction is not None: 510 self.new_op(AddressInstruction(attr)) 511 else: 512 raise TranslateError(self.module.full_name(), node, 513 "Storing of class attribute %r via self not permitted." % attrname) 514 515 # Otherwise, test for a suitable context at run-time. 516 517 else: 518 519 # Only permit loading (not storing) of class attributes via self. 520 521 if AddressContextCondInstruction is not None: 522 self.new_op(AddressContextCondInstruction(attr)) 523 else: 524 raise TranslateError(self.module.full_name(), node, 525 "Storing of class attribute %r via self not permitted." % attrname) 526 527 return 528 529 # Or delegate the attribute access to a general instruction 530 # since the kind of attribute cannot be deduced. 531 532 except KeyError: 533 pass 534 535 # Attempt to deduce the target of an attribute access by searching for a 536 # unique type providing the names associated with the accessed object. 537 # NOTE: This should re-use type information defined at assignment 538 # NOTE: locations. 539 540 elif self.optimiser.should_optimise_accesses_by_attribute_usage(): 541 542 if hasattr(node, "_attrnames"): 543 target_names = self.objtable.all_possible_objects(node._attrnames) 544 545 if len(target_names) == 1: 546 target_name = target_names[0] 547 548 # Access the object table to get the attribute. 549 550 try: 551 attr = self.objtable.access(target_name, attrname) 552 553 # Disallow non-class/instance optimisations. 554 555 except TableError, exc: 556 print "Possible optimisation for", target_name, "not permissable." 557 558 # Produce a suitable instruction. 559 560 else: 561 if AddressContextCondInstruction is not None and attr.is_static_attribute(): 562 self.new_op(AddressContextCondInstruction(attr)) 563 elif AttrInstruction is not None and not attr.is_static_attribute(): 564 self.new_op(AttrInstruction(attr)) 565 else: 566 raise TranslateError(self.module.full_name(), node, 567 "Storing of class or module attribute %r via an object is not permitted." % attrname) 568 569 return 570 571 # Otherwise, perform a normal operation. 572 573 try: 574 index = self.objtable.get_index(attrname) 575 576 except self.objtable.TableError: 577 578 # If this error arises on generated code, check the names_used 579 # attribute on the Importer. 580 581 raise TranslateError(self.module.full_name(), node, 582 "No attribute entry exists for name %r." % attrname) 583 584 # NOTE: Test for class vs. instance attributes, generating 585 # NOTE: context-related instructions. 586 587 if AttrIndexContextCondInstruction is not None: 588 self.new_op(AttrIndexContextCondInstruction(index)) 589 590 # Store instructions do not need to consider context modifications. 591 592 else: 593 self.new_op(AttrIndexInstruction(index)) 594 595 # Invocations involve the following: 596 # 597 # 1. Reservation of a frame for the arguments 598 # 2. Identification of the target which is then held in temporary storage 599 # 3. Optional inclusion of a context (important for methods) 600 # 4. Preparation of the argument frame 601 # 5. Invocation of the target 602 # 6. Discarding of the frame 603 # 604 # In order to support nested invocations - such as a(b(c)) - use of the 605 # temporary storage is essential. 606 607 def _startCallFunc(self): 608 609 "Record the location of the invocation." 610 611 op = MakeFrame() 612 self.new_op(op) # records the start of the frame 613 self.frame_makers.append(op) 614 615 def _generateCallFunc(self, args, node): 616 617 """ 618 Support a generic function invocation using the given 'args', occurring 619 on the given 'node', where the expression providing the invocation 620 target has just been generated. 621 622 In other situations, the invocation is much simpler and does not need to 623 handle the full flexibility of a typical Python invocation. Internal 624 invocations, such as those employed by operators and certain 625 control-flow mechanisms, use predetermined arguments and arguably do not 626 need to support the same things as the more general invocations. 627 """ 628 629 target, context, temp_target, temp_context = self._generateCallFuncContext() 630 self._generateCallFuncArgs(target, context, temp_target, temp_context, args, node) 631 return temp_target, target, temp_context 632 633 def _generateCallFuncContext(self): 634 635 """ 636 Produce code which loads and checks the context of the current 637 invocation, the instructions for whose target have already been 638 produced, returning a list of instructions which reference the 639 invocation target. 640 """ 641 642 t = self.optimiser.optimise_known_target() 643 if t: 644 target, context = t 645 if isinstance(target, Instance): # lambda object 646 target, context = None, None 647 else: 648 target, context = None, None 649 650 # Store the target in temporary storage for subsequent referencing. 651 652 temp_target = self.optimiser.optimise_temp_storage() 653 654 # Where a target or context are not known or where an instance is known 655 # to be the context, load the context. 656 657 if target is None or isinstance(context, Instance): 658 self.new_op(temp_target) 659 self.new_op(LoadContext()) 660 temp_context = self.optimiser.optimise_temp_storage() 661 self.new_op(StoreFrame(0)) 662 663 # Class contexts should be made available for testing of the first 664 # argument. 665 # NOTE: Class methods should eventually be supported. 666 667 elif isinstance(context, Class): 668 self.new_op(temp_target) 669 self.new_op(LoadContext()) 670 temp_context = self.optimiser.optimise_temp_storage() 671 672 # Otherwise omit the context. 673 674 else: 675 temp_context = None 676 677 return target, context, temp_target, temp_context 678 679 def _generateCallFuncArgs(self, target, context, temp_target, temp_context, args, node): 680 681 """ 682 Given invocation 'target' and 'context' information, the 'temp_target' 683 reference to the target, the 'temp_context' reference to the context, a 684 list of nodes representing the 'args' (arguments), generate instructions 685 which load the arguments for the invocation defined by the given 'node'. 686 """ 687 688 # Evaluate the arguments. 689 690 employed_positions = set() 691 employed_keywords = set() 692 extra_keywords = [] 693 positional_args = [] 694 keyword_args = [] 695 696 # Find keyword arguments in advance in order to help resolve targets. 697 698 have_keywords = 0 699 700 for arg in args: 701 if isinstance(arg, compiler.ast.Keyword): 702 employed_keywords.add(arg.name) 703 keyword_args.append(arg) 704 have_keywords = 1 705 elif not have_keywords: 706 positional_args.append(arg) 707 708 possible_targets = self.paramtable.all_possible_objects(employed_keywords) 709 710 # Note the presence of the context in the frame where appropriate. 711 712 # For unknown invocations and method invocations. 713 714 if target is None or isinstance(context, Instance): 715 ncontext = 1 716 expect_testable_self = 0 717 718 # Handle calls to classes by obtaining the instantiator function. 719 # A context is reserved for the new instance, but this is not provided 720 # in the invocation (since the instantiator will fill the locals slot 721 # concerned). 722 723 elif isinstance(target, Class): 724 ncontext = 1 725 expect_testable_self = 0 726 target = target.get_instantiator() 727 728 # Method calls via classes. 729 730 elif isinstance(context, Class): 731 ncontext = 0 732 expect_testable_self = 1 733 734 # Function calls. 735 736 else: 737 ncontext = 0 738 expect_testable_self = 0 739 740 # Traverse the positional arguments adding them using the incrementing 741 # frame position. 742 743 first = 1 744 frame_pos = ncontext 745 temp_first_argument = None 746 747 for arg in positional_args: 748 self.dispatch(arg) 749 self.new_op(StoreFrame(frame_pos)) 750 employed_positions.add(frame_pos) 751 752 # Check to see if the first argument is appropriate (compatible with 753 # the target where methods are being invoked via classes). 754 755 if first and (expect_testable_self or target is None): 756 757 # Drop any test if the target and the context are known. 758 759 if not self.optimiser.have_correct_self_for_target(context, self.unit): 760 761 # Otherwise, remember the first argument for a subsequent 762 # test. 763 764 temp_first_argument = self.optimiser.optimise_temp_storage() 765 766 first = 0 767 frame_pos += 1 768 769 # Adjust the invocation frame for unknown invocations. 770 # Test the first argument if appropriate. 771 772 self._generateCallFuncContextTest(temp_target, target, temp_context, temp_first_argument, node) 773 774 # Traverse the keyword arguments adding them at the appropriate frame 775 # positions. 776 777 max_keyword_pos = -1 778 779 for arg in keyword_args: 780 781 # Optimise where the target is known now. 782 783 if target is not None: 784 785 # Find the parameter table entry for the target. 786 787 target_name = target.full_name() 788 789 # Look for a callable with the precise target name. 790 791 table_entry = self.paramtable.table[target_name] 792 793 # Look the name up in the parameter table entry. 794 795 try: 796 pos = table_entry[arg.name] 797 798 # Where no position is found, this could be an extra keyword 799 # argument. 800 801 except KeyError: 802 extra_keywords.append(arg) 803 continue 804 805 # Test for illegal conditions. 806 807 if pos in employed_positions: 808 raise TranslateError(self.module.full_name(), node, 809 "Keyword argument %r overwrites parameter %r." % (arg.name, pos)) 810 811 employed_positions.add(pos) 812 813 # Generate code for the keyword and the positioning 814 # operation. 815 816 self.dispatch(arg.expr) 817 self.new_op(StoreFrame(pos)) 818 819 # Otherwise, generate the code needed to obtain the details of 820 # the parameter location. 821 822 else: 823 824 # Combine the target details with the name to get the location. 825 # See the access method on the List class. 826 827 try: 828 paramindex = self.paramtable.get_index(arg.name) 829 830 # Where no position is found, this could be an extra keyword 831 # argument. 832 833 except self.paramtable.TableError: 834 extra_keywords.append(arg) 835 continue 836 837 # Generate code for the keyword and the positioning 838 # operation. Get the value as the source of the assignment. 839 840 self.dispatch(arg.expr) 841 self.record_value() 842 843 # Store the source value using the callable's parameter 844 # table information. 845 846 self.new_op(temp_target) 847 self.new_op(StoreFrameIndex(paramindex)) 848 849 self.set_source() 850 self.discard_value() 851 852 # Record the highest possible frame position for this argument. 853 854 max_keyword_pos = max(max_keyword_pos, max(self.paramtable.all_attribute_positions(arg.name))) 855 856 # Use the frame position counter as a general argument counter. 857 858 frame_pos += 1 859 860 # NOTE: Extra keywords are not supported. 861 # NOTE: Somehow, the above needs to be combined with * arguments. 862 863 if extra_keywords: 864 print "Warning: extra keyword argument(s) %s not handled." % ", ".join([arg.name for arg in extra_keywords]) 865 866 # Either test for a complete set of arguments. 867 868 if target is not None: 869 870 # Make sure that enough arguments have been given. 871 872 nargs_max = len(target.positional_names) 873 ndefaults = len(target.defaults) 874 nargs_min = nargs_max - ndefaults 875 876 # Visit each argument position and look for a supplied argument. 877 878 for i in range(ncontext, nargs_min): 879 if i not in employed_positions: 880 raise TranslateError(self.module.full_name(), node, 881 "Argument %r not supplied for %r: need at least %d argument(s)." % (i+1, target.name, nargs_min)) 882 883 nargs = frame_pos 884 885 # Determine whether too many arguments have been given and how big 886 # the frame should be. 887 888 # For parameter lists with * or ** parameters, accept as many 889 # arguments as are allowed or as many as we have. 890 891 if target.has_star or target.has_dstar: 892 frame_size = max(nargs, nargs_max) 893 894 # NOTE: We now need to pack these arguments into a suitable 895 # NOTE: structure for the * parameter. 896 897 # For other parameter lists, only accept as many arguments as we are 898 # allowed. 899 900 elif nargs > nargs_max: 901 raise TranslateError(self.module.full_name(), node, 902 "Too many arguments for %r: need at most %d argument(s)." % (target.name, nargs_max)) 903 904 else: 905 frame_size = nargs_max 906 907 # Where defaults are involved, put them into the frame. 908 909 self._generateCallFuncDefaultArgs(target, temp_target, nargs_min, nargs_max, employed_positions) 910 911 # Set the frame size. 912 913 self._endCallFuncArgs(frame_size) 914 915 # Or just set the frame size and have the function check the arguments. 916 917 else: 918 max_pos = max(max(employed_positions or [-1]), max_keyword_pos, frame_pos - 1) 919 self._endCallFuncArgs(max_pos + 1) 920 921 def _generateCallFuncDefaultArgs(self, target, temp_target, nargs_min, nargs_max, employed_positions): 922 923 """ 924 For the given 'target' and 'temp_target' reference to the target, 925 generate default arguments for those positions in the range 926 'nargs_min'...'nargs_max' which are not present in the 927 'employed_positions' collection. 928 """ 929 930 # Where a lambda is involved, construct a dynamic object to hold the 931 # defaults. 932 933 dynamic = target.name is None 934 935 # Here, we use negative index values to visit the right hand end of 936 # the defaults list. 937 938 for pos in range(nargs_min, nargs_max): 939 if pos not in employed_positions: 940 if dynamic: 941 self.new_op(temp_target) 942 self.new_op(LoadAttr(target.default_attrs[pos - nargs_min])) 943 else: 944 self.new_op(LoadAddress(target.default_attrs[pos - nargs_min])) 945 self.new_op(StoreFrame(pos)) 946 947 def _generateCallFuncContextTest(self, temp_target, target, temp_context, temp_first_argument, node): 948 949 """ 950 Generate code to test for 'temp_target', representing the given 951 'target', the context provided by 'temp_context' against 952 'temp_first_argument', and to signal an exception (using 'node') if the 953 context is incompatible with the first frame argument. 954 955 In addition, the invocation frame will be shifted if 'temp_context' 956 indicates a function or a class. 957 """ 958 959 adjust_block = self.new_block() 960 continue_block = self.new_block() 961 962 # Add some preliminary tests where the target is not known. 963 964 if target is None: 965 966 # Adjust the frame if a replaceable context is provided. 967 968 self.new_op(temp_context) 969 self.new_op(CheckContext()) 970 self.new_op(JumpIfFalse(adjust_block)) 971 972 # Skip adjustment and tests if the context is not a class. 973 # Classes themselves employ a placeholder context so that 974 # instantiators can be callable with a context which will be 975 # overwritten in the frame. 976 977 self.new_op(temp_context) 978 self.new_op(CheckClass()) 979 self.new_op(JumpIfFalse(continue_block)) 980 981 if temp_first_argument is not None: 982 self.new_op(temp_first_argument) 983 984 # Check the current value (the argument) against the known context 985 # (given as the source). 986 987 self.new_op(CheckInstance()) 988 self.optimiser.set_source(temp_context) 989 990 self.new_op(JumpIfTrue(adjust_block)) 991 992 # Where the context is inappropriate, drop the incomplete frame and 993 # raise an exception. 994 995 self.new_op(DropFrame()) 996 self.new_op(LoadResult()) 997 998 self.make_exception("TypeError", node) 999 self.new_op(StoreException()) 1000 self.new_op(RaiseException()) 1001 1002 if target is None or temp_first_argument is not None: 1003 self.set_block(adjust_block) 1004 self.new_op(AdjustFrame(1)) 1005 1006 self.set_block(continue_block) 1007 1008 def _doCallFunc(self, temp_target, target=None): 1009 1010 "Make the invocation." 1011 1012 # For classes, the target itself is used, since the instantiator will be 1013 # obtained via the class. 1014 1015 if isinstance(target, (Class, Function)): 1016 self.new_op(JumpWithFrameDirect(target)) 1017 else: 1018 self.new_op(temp_target) 1019 self.new_op(LoadCallable()) 1020 self.new_op(JumpWithFrame()) 1021 1022 def _endCallFuncArgs(self, nargs): 1023 1024 "Set the frame size." 1025 1026 self.frame_makers[-1].attr = nargs 1027 self.frame_makers.pop() 1028 1029 def _endCallFunc(self, temp_target=None, target=None, temp_context=None, load_result=1): 1030 1031 "Finish the invocation and tidy up afterwards." 1032 1033 self.new_op(DropFrame()) 1034 if load_result: 1035 self.new_op(LoadResult()) 1036 1037 # Discard any temporary storage instructions. 1038 1039 if temp_target is not None: 1040 self.discard_temp(temp_target) 1041 1042 if temp_context is not None: 1043 self.discard_temp(temp_context) 1044 1045 def _generateFunctionDefaults(self, function): 1046 1047 """ 1048 Generate the default initialisation code for 'function', returning 1049 a temporary storage reference if a dynamic object was created for the 1050 function. 1051 """ 1052 1053 attr_to_default = zip(function.default_attrs, function.defaults) 1054 if not attr_to_default: 1055 return None 1056 1057 # Where a lambda is involved, construct a dynamic object to hold the 1058 # defaults. 1059 1060 dynamic = function.name is None 1061 1062 if dynamic: 1063 self.make_instance(self.get_builtin_class("function", function), len(attr_to_default)) 1064 temp = self.get_temp() 1065 1066 for attr, default in attr_to_default: 1067 self.dispatch(default) 1068 1069 self.record_value() 1070 if dynamic: 1071 self.new_op(temp) 1072 self.new_op(StoreAttr(attr)) 1073 else: 1074 self.new_op(StoreAddress(attr)) 1075 self.set_source() 1076 self.discard_value() 1077 1078 if dynamic: 1079 return temp 1080 else: 1081 return None 1082 1083 def _visitName(self, node, classes): 1084 1085 """ 1086 Visit the name-related 'node', generating instructions based on the 1087 given 'classes'. 1088 """ 1089 1090 name = node.name 1091 scope = self.get_scope(name) 1092 #print self.module.name, node.lineno, name, scope 1093 self._generateName(name, scope, classes, node) 1094 1095 def _generateName(self, name, scope, classes, node): 1096 1097 """ 1098 Generate code for the access to 'name' in 'scope' using the given 1099 'classes', and using the given 'node' as the source of the access. 1100 """ 1101 1102 NameInstruction, AddressInstruction, AddressContextInstruction = classes 1103 1104 if scope == "local": 1105 unit = self.unit 1106 if isinstance(unit, Function): 1107 self.new_op(NameInstruction(unit.all_locals()[name])) 1108 elif isinstance(unit, Class): 1109 if AddressContextInstruction is not None: 1110 self.new_op(LoadConst(unit)) 1111 self.new_op(AddressContextInstruction(unit.all_class_attributes()[name])) 1112 else: 1113 self.new_op(AddressInstruction(unit.all_class_attributes()[name])) 1114 elif isinstance(unit, Module): 1115 self.new_op(AddressInstruction(unit.module_attributes()[name])) 1116 else: 1117 raise TranslateError(self.module.full_name(), node, "Program unit %r has no local %r." % (unit, name)) 1118 1119 elif scope == "global": 1120 globals = self.module.module_attributes() 1121 if globals.has_key(name): 1122 self.new_op(AddressInstruction(globals[name])) 1123 else: 1124 raise TranslateError(self.module.full_name(), node, "Module %r has no attribute %r." % (self.module, name)) 1125 1126 else: 1127 self.new_op(AddressInstruction(self.get_builtin(name, node))) 1128 1129 def _visitUnary(self, node): 1130 1131 """ 1132 _t = node.expr 1133 try: 1134 _result = _t.__pos__() 1135 except AttributeError: 1136 raise TypeError 1137 """ 1138 1139 method = unary_methods[node.__class__.__name__] 1140 1141 handler_block = self.new_block() 1142 else_block = self.new_block() 1143 end_block = self.new_block() 1144 1145 # Evaluate and store the operand in temporary storage. 1146 1147 self.dispatch(node.expr) 1148 temp = self.optimiser.optimise_temp_storage() 1149 1150 self.new_op(temp) 1151 1152 # Try to get the attribute, handling exceptions. 1153 1154 self.new_op(PushHandler(handler_block)) 1155 1156 # Get the method on temp. 1157 1158 self._generateAttr(node, method, self.attribute_load_instructions) 1159 temp_method = self.optimiser.optimise_temp_storage() 1160 1161 # Finish handling any attribute access exceptions. 1162 1163 have_handler = self.new_op(PopHandler()) 1164 1165 # Add arguments. 1166 # NOTE: No support for defaults. 1167 1168 self._startCallFunc() 1169 self.new_op(temp) # Explicit context as first argument. 1170 self.new_op(StoreFrame(0)) 1171 self._endCallFuncArgs(1) 1172 self._doCallFunc(temp_method) 1173 self._endCallFunc(temp_method) 1174 1175 # Store the result. 1176 1177 temp_out = self.get_temp() 1178 self.new_op(Jump(end_block)) 1179 1180 # End method attempt. 1181 1182 self.set_block(handler_block) 1183 1184 if have_handler: 1185 self.new_op(PopHandler()) 1186 self._handleAttributeError(node, temp_method, else_block) 1187 1188 # Raise a TypeError. 1189 1190 self.set_block(else_block) 1191 self.make_exception("TypeError", node) 1192 self.new_op(StoreException()) 1193 self.new_op(RaiseException()) 1194 1195 # Produce the result. 1196 1197 self.set_block(end_block) 1198 self.new_op(temp_out) 1199 1200 # Compilation duties... 1201 1202 self.discard_temp(temp) 1203 self.discard_temp(temp_out) 1204 1205 def _visitBinaryBit(self, node): 1206 1207 """ 1208 Need to impose binary rules over a sequence of nodes. The 1209 short-circuiting of the similar logical operators is not imposed by the 1210 bitwise operators. 1211 """ 1212 1213 left = None 1214 1215 for right in node.nodes: 1216 if left is not None: 1217 self._visitBinaryMethods(node, left, right) 1218 left = right 1219 1220 def _visitBinary(self, node): 1221 1222 """ 1223 _t1 = node.left 1224 _t2 = node.right 1225 try: 1226 _result = _t1.__add__(_t2) 1227 if _result is NotImplemented: 1228 raise AttributeError 1229 except AttributeError: 1230 try: 1231 _result = _t2.__radd__(_t1) 1232 if _result is NotImplemented: 1233 raise AttributeError 1234 except AttributeError: 1235 raise TypeError 1236 """ 1237 1238 self._visitBinaryMethods(node, node.left, node.right) 1239 1240 def _visitBinaryMethods(self, node, left, right): 1241 1242 left_method, right_method = binary_methods[node.__class__.__name__] 1243 1244 # Evaluate and store the left operand in temporary storage. 1245 1246 self.dispatch(left) 1247 temp1 = self.optimiser.optimise_temp_storage() 1248 1249 # Evaluate and store the right operand in temporary storage. 1250 1251 self.dispatch(right) 1252 temp2 = self.optimiser.optimise_temp_storage() 1253 1254 temp_out = self._generateBinary(node, temp1, temp2, left_method, right_method) 1255 1256 # Produce the result. 1257 1258 self.new_op(temp_out) 1259 1260 # Compilation duties... 1261 1262 self.discard_temp(temp1) 1263 self.discard_temp(temp2) 1264 self.discard_temp(temp_out) 1265 1266 def _generateBinary(self, node, temp1, temp2, left_method, right_method): 1267 1268 """ 1269 For the given 'node', generate the binary operator pattern for the 1270 operands 'temp1' and 'temp2', employing 'left_method' and 'right_method' 1271 as defined for binary operators, but also used in comparisons (for which 1272 this method is provided). 1273 1274 A temporary storage reference is returned from this method. 1275 """ 1276 1277 right_block = self.new_block() 1278 left_else_block = self.new_block() 1279 right_else_block = self.new_block() 1280 end_block = self.new_block() 1281 1282 # Left method. 1283 1284 temp_out = self._generateOpMethod(node, temp1, temp2, left_method, left_else_block, right_block, end_block) 1285 self.discard_temp(temp_out) # NOTE: Will re-use the same storage. 1286 1287 self.set_block(left_else_block) 1288 self.new_op(ClearException()) 1289 1290 # Right method. 1291 1292 self.set_block(right_block) 1293 temp_out = self._generateOpMethod(node, temp2, temp1, right_method, right_else_block, right_else_block, end_block) 1294 1295 # Raise a TypeError. 1296 1297 self.set_block(right_else_block) 1298 self.make_exception("TypeError", node) 1299 self.new_op(StoreException()) 1300 self.new_op(RaiseException()) 1301 1302 self.set_block(end_block) 1303 return temp_out 1304 1305 def _generateOpMethod(self, node, temp1, temp2, method_name, handled_block, next_method_block, end_block): 1306 1307 """ 1308 For the given 'node', generate the operator method invocation using the 1309 operands 'temp1' and 'temp2', employing the given 'method_name', and 1310 jumping appropriately to 'handled_block' where an AttributeError was 1311 handled, to 'next_method_block' where a NotImplemented result is 1312 returned, or to 'end_block' if the method call was successful. 1313 1314 A temporary storage reference is returned from this method. 1315 """ 1316 1317 handler_block = self.new_block() 1318 1319 # Try to get the attribute, handling exceptions. 1320 1321 self.new_op(PushHandler(handler_block)) 1322 self.new_op(temp1) 1323 1324 # Get method on temp1. 1325 1326 self._generateAttr(node, method_name, self.attribute_load_instructions) 1327 temp_method = self.optimiser.optimise_temp_storage() 1328 1329 # Finish handling any attribute access exceptions. 1330 1331 have_handler = self.new_op(PopHandler()) 1332 1333 # Add arguments. 1334 # NOTE: No support for defaults. 1335 1336 self._startCallFunc() 1337 self.new_op(temp1) 1338 self.new_op(StoreFrame(0)) 1339 self.new_op(temp2) 1340 self.new_op(StoreFrame(1)) 1341 self._endCallFuncArgs(2) 1342 self._doCallFunc(temp_method) 1343 self._endCallFunc(temp_method) 1344 1345 # Store the result. 1346 1347 temp_out = self.get_temp() 1348 1349 # Test for NotImplemented. 1350 # Don't actually raise an exception. 1351 1352 self.new_op(TestIdentityAddress(self.importer.get_predefined_constant("NotImplemented"))) 1353 self.new_op(JumpIfTrue(next_method_block)) 1354 self.new_op(Jump(end_block)) 1355 1356 # End method attempt. 1357 1358 self.set_block(handler_block) 1359 1360 if have_handler: 1361 self.new_op(PopHandler()) 1362 self._handleAttributeError(node, temp_method, handled_block) 1363 1364 return temp_out 1365 1366 def _handleAttributeError(self, node, temp_method, handled_block): 1367 1368 """ 1369 Add exception handling to the method acquisition instructions where the 1370 attribute access cannot be resolved at compile-time. 1371 """ 1372 1373 if not (self.optimiser.should_optimise_known_target() and self.optimiser.is_constant_input(temp_method)): 1374 self.load_builtin("AttributeError", node) 1375 self.new_op(CheckException()) 1376 self.new_op(JumpIfTrue(handled_block)) 1377 self.new_op(RaiseException()) 1378 1379 def _generateTuple(self, node): 1380 1381 "Make a tuple using the given program 'node'." 1382 1383 self.make_instance(self.get_builtin_class("tuple", node), len(node.nodes)) 1384 temp = self.get_temp() 1385 self._populateSequence(temp, node) 1386 self.new_op(temp) 1387 self.discard_temp(temp) 1388 1389 def _generateList(self, node): 1390 1391 "Make a list using the given program 'node'." 1392 1393 # Make a fragment containing the list elements. 1394 1395 self.new_op(MakeFragment(len(node.nodes) + 1)) 1396 temp = self.get_temp() 1397 self._populateSequence(temp, node) 1398 self.new_op(temp) 1399 self.record_value() 1400 1401 self.make_instance(self.get_builtin_class("list", node), 1) 1402 list_temp = self.get_temp() 1403 self.new_op(list_temp) 1404 self.new_op(StoreAttr(Attr(0, None, None))) 1405 self.set_source() 1406 self.discard_value() 1407 1408 self.new_op(list_temp) 1409 self.discard_temp(temp) 1410 self.discard_temp(list_temp) 1411 1412 def _populateSequence(self, temp, node): 1413 1414 """ 1415 Populate a sequence using the given 'temp' reference and program 'node'. 1416 """ 1417 1418 for i, n in enumerate(node.nodes): 1419 self.dispatch(n) 1420 self.record_value() 1421 self.new_op(temp) 1422 self.new_op(StoreAttr(Attr(i, None, None))) 1423 self.set_source() 1424 self.discard_value() 1425 1426 def _generateTestBoolean(self, node, temp): 1427 1428 """ 1429 Generate a test of the boolean status of the current value for the given 1430 program 'node'. 1431 """ 1432 1433 # Get method on temp. 1434 # NOTE: Using __bool__ instead of __nonzero__. 1435 1436 self._generateAttr(node, "__bool__", self.attribute_load_instructions) 1437 temp_method = self.optimiser.optimise_temp_storage() 1438 1439 self._startCallFunc() 1440 self.new_op(temp) 1441 self.new_op(StoreFrame(0)) 1442 self._endCallFuncArgs(1) 1443 self._doCallFunc(temp_method) 1444 self._endCallFunc(temp_method) 1445 1446 self.discard_temp(temp_method) 1447 1448 # Convert result to boolean (a StoreBoolean operation). 1449 1450 self.new_op(TestIdentityAddress(self.importer.get_predefined_constant("True"))) 1451 1452 def _generateLoadBoolean(self, node): 1453 1454 """ 1455 Generate instructions to load the appropriate value given the current 1456 boolean status. 1457 """ 1458 1459 true_block = self.new_block() 1460 end_block = self.new_block() 1461 1462 self.new_op(JumpIfTrue(true_block)) 1463 self.new_op(LoadConst(self.importer.get_predefined_constant("False"))) 1464 self.new_op(Jump(end_block)) 1465 1466 self.set_block(true_block) 1467 self.new_op(LoadConst(self.importer.get_predefined_constant("True"))) 1468 1469 self.set_block(end_block) 1470 1471 # vim: tabstop=4 expandtab shiftwidth=4