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