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