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