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