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