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