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