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 + 2 # include space for instantiators to expand backwards 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 # Otherwise omit the context. 512 513 else: 514 pass # NOTE: Class methods should be supported. 515 516 return target, context, temp 517 518 def _generateCallFuncArgs(self, target, context, temp, args, node): 519 520 """ 521 Given invocation 'target' and 'context' information, the 'temp' 522 reference to the target, a list of nodes representing the 'args' 523 (arguments), generate instructions which load the arguments for the 524 invocation defined by the given 'node'. 525 """ 526 527 # Evaluate the arguments. 528 529 employed_positions = set() 530 employed_keywords = set() 531 extra_keywords = [] 532 533 # Find keyword arguments in advance in order to help resolve targets. 534 535 for arg in args: 536 if isinstance(arg, compiler.ast.Keyword): 537 employed_keywords.add(arg.name) 538 539 possible_targets = self.paramtable.all_possible_objects(employed_keywords) 540 541 # Note the presence of the context in the frame where appropriate. 542 543 if target is None or isinstance(context, Instance): 544 ncontext = 1 545 expect_context = 0 546 547 # Handle calls to classes. 548 # The resulting target must match that used in the actual invocation. 549 550 elif isinstance(target, Class): 551 ncontext = 0 552 expect_context = 0 553 target = target.get_instantiator() 554 555 # Method calls via classes. 556 557 elif isinstance(context, Class): 558 ncontext = 0 559 expect_context = 1 560 561 # Function calls. 562 563 else: 564 ncontext = 0 565 expect_context = 0 566 567 first = 1 568 frame_pos = ncontext 569 max_keyword_pos = -1 570 571 for arg in args: 572 573 # Handle positional and keyword arguments separately. 574 575 if isinstance(arg, compiler.ast.Keyword): 576 577 # Optimise where the target is known now. 578 579 if target is not None: 580 581 # Find the parameter table entry for the target. 582 583 target_name = target.full_name() 584 585 # Look for a callable with the precise target name. 586 587 table_entry = self.paramtable.table[target_name] 588 589 # Look the name up in the parameter table entry. 590 591 try: 592 pos = table_entry[arg.name] 593 594 # Where no position is found, this could be an extra keyword 595 # argument. 596 597 except KeyError: 598 extra_keywords.append(arg) 599 continue 600 601 # Test for illegal conditions. 602 603 if pos in employed_positions: 604 raise TranslateError(self.module.full_name(), node, 605 "Keyword argument %r overwrites parameter %r." % (arg.name, pos)) 606 607 employed_positions.add(pos) 608 609 # Generate code for the keyword and the positioning 610 # operation. 611 612 self.dispatch(arg.expr) 613 self.new_op(StoreFrame(pos)) 614 615 # Otherwise, generate the code needed to obtain the details of 616 # the parameter location. 617 618 else: 619 620 # Combine the target details with the name to get the location. 621 # See the access method on the List class. 622 623 try: 624 paramindex = self.paramtable.get_index(arg.name) 625 626 # Where no position is found, this could be an extra keyword 627 # argument. 628 629 except self.paramtable.TableError: 630 extra_keywords.append(arg) 631 continue 632 633 # Generate code for the keyword and the positioning 634 # operation. Get the value as the source of the assignment. 635 636 self.dispatch(arg.expr) 637 self.record_value() 638 639 # Store the source value using the callable's parameter 640 # table information. 641 642 self.new_op(temp) 643 self.new_op(StoreFrameIndex(paramindex)) 644 645 self.set_source() 646 self.discard_value() 647 648 # Record the highest possible frame position for this argument. 649 650 max_keyword_pos = max(max_keyword_pos, max(self.paramtable.all_attribute_positions(arg.name))) 651 652 else: 653 self.dispatch(arg) 654 self.new_op(StoreFrame(frame_pos)) 655 656 employed_positions.add(frame_pos) 657 658 # Check to see if the first argument is appropriate (compatible with 659 # the target where methods are being invoked via classes). 660 661 if first and expect_context: 662 663 # Drop any test if the target and the context are known. 664 665 if not self.optimiser.have_correct_self_for_target(context, self.unit): 666 667 continue_block = self.new_block() 668 669 self.new_op(CheckSelf()) 670 self.optimiser.set_source(temp) 671 self.new_op(JumpIfTrue(continue_block)) 672 673 # Where the context is inappropriate, drop the incomplete frame and 674 # raise an exception. 675 676 self.new_op(DropFrame()) 677 self.new_op(LoadResult()) 678 679 self.load_builtin("TypeError", node) 680 self.new_op(StoreException()) 681 self.new_op(RaiseException()) 682 683 self.set_block(continue_block) 684 685 first = 0 686 frame_pos += 1 687 688 # NOTE: Extra keywords are not supported. 689 # NOTE: Somehow, the above needs to be combined with * arguments. 690 691 if extra_keywords: 692 print "Warning: extra keyword argument(s) %s not handled." % ", ".join([arg.name for arg in extra_keywords]) 693 694 # Either test for a complete set of arguments. 695 696 if target is not None: 697 698 # Make sure that enough arguments have been given. 699 700 nargs_max = len(target.positional_names) 701 ndefaults = len(target.defaults) 702 nargs_min = nargs_max - ndefaults 703 704 # Visit each argument position and look for a supplied argument. 705 706 for i in range(ncontext, nargs_min): 707 if i not in employed_positions: 708 raise TranslateError(self.module.full_name(), node, 709 "Argument %r not supplied for %r: need at least %d argument(s)." % (i+1, target.name, nargs_min)) 710 711 nargs = frame_pos 712 713 # Determine whether too many arguments have been given and how big 714 # the frame should be. 715 716 # For parameter lists with * or ** parameters, accept as many 717 # arguments as are allowed or as many as we have. 718 719 if target.has_star or target.has_dstar: 720 frame_size = max(nargs, nargs_max) 721 722 # NOTE: We now need to pack these arguments into a suitable 723 # NOTE: structure for the * parameter. 724 725 # For other parameter lists, only accept as many arguments as we are 726 # allowed. 727 728 elif nargs > nargs_max: 729 raise TranslateError(self.module.full_name(), node, 730 "Too many arguments for %r: need at most %d argument(s)." % (target.name, nargs_max)) 731 732 else: 733 frame_size = nargs_max 734 735 # Where defaults are involved, put them into the frame. 736 737 self._generateCallFuncDefaultArgs(target, temp, nargs_min, nargs_max, employed_positions) 738 739 # Set the frame size. 740 741 self._endCallFuncArgs(frame_size) 742 743 # Or just set the frame size and have the function check the arguments. 744 745 else: 746 max_pos = max(max(employed_positions or [-1]), max_keyword_pos, frame_pos - 1) 747 self._endCallFuncArgs(max_pos + 1) 748 749 def _generateCallFuncDefaultArgs(self, target, temp, nargs_min, nargs_max, employed_positions): 750 751 """ 752 For the given 'target' and 'temp' reference to the target, generate 753 default arguments for those positions in the range 'nargs_min'... 754 'nargs_max' which are not present in the 'employed_positions' 755 collection. 756 """ 757 758 # Where a lambda is involved, construct a dynamic object to hold the 759 # defaults. 760 761 dynamic = target.name is None 762 763 # Here, we use negative index values to visit the right hand end of 764 # the defaults list. 765 766 for pos in range(nargs_min, nargs_max): 767 if pos not in employed_positions: 768 if dynamic: 769 self.new_op(temp) 770 self.new_op(LoadAttr(target.default_attrs[pos - nargs_min])) 771 else: 772 self.new_op(LoadAddress(target.default_attrs[pos - nargs_min])) 773 self.new_op(StoreFrame(pos)) 774 775 def _doCallFunc(self, instruction, target=None): 776 777 "Make the invocation." 778 779 # For classes, the target itself is used, since the instantiator will be 780 # obtained via the class. 781 782 if isinstance(target, (Class, Function)): 783 self.new_op(JumpWithFrameDirect(target)) 784 else: 785 self.new_op(instruction) 786 self.new_op(LoadCallable()) 787 self.new_op(JumpWithFrame()) 788 789 def _endCallFuncArgs(self, nargs): 790 791 "Set the frame size." 792 793 self.frame_makers[-1].attr = nargs 794 self.frame_makers.pop() 795 796 def _endCallFunc(self, instruction=None, target=None, load_result=1): 797 798 "Finish the invocation and tidy up afterwards." 799 800 self.new_op(DropFrame()) 801 if load_result: 802 self.new_op(LoadResult()) 803 804 # Discard any temporary storage instructions. 805 806 if instruction is not None: 807 self.discard_temp(instruction) 808 809 def _generateFunctionDefaults(self, function): 810 811 """ 812 Generate the default initialisation code for 'function', returning 813 a temporary storage reference if a dynamic object was created for the 814 function. 815 """ 816 817 attr_to_default = zip(function.default_attrs, function.defaults) 818 if not attr_to_default: 819 return None 820 821 # Where a lambda is involved, construct a dynamic object to hold the 822 # defaults. 823 824 dynamic = function.name is None 825 826 if dynamic: 827 self.make_object(self.get_builtin_class("function", function), len(attr_to_default)) 828 temp = self.get_temp() 829 830 for attr, default in attr_to_default: 831 self.dispatch(default) 832 833 self.record_value() 834 if dynamic: 835 self.new_op(temp) 836 self.new_op(StoreAttr(attr)) 837 else: 838 self.new_op(StoreAddress(attr)) 839 self.set_source() 840 self.discard_value() 841 842 if dynamic: 843 return temp 844 else: 845 return None 846 847 def _visitName(self, node, classes): 848 849 """ 850 Visit the name-related 'node', generating instructions based on the 851 given 'classes'. 852 """ 853 854 name = node.name 855 scope = self.get_scope(name) 856 #print self.module.name, node.lineno, name, scope 857 self._generateName(name, scope, classes, node) 858 859 def _generateName(self, name, scope, classes, node): 860 861 """ 862 Generate code for the access to 'name' in 'scope' using the given 863 'classes', and using the given 'node' as the source of the access. 864 """ 865 866 NameInstruction, AddressInstruction = classes 867 868 if scope == "local": 869 unit = self.unit 870 if isinstance(unit, Function): 871 self.new_op(NameInstruction(unit.all_locals()[name])) 872 elif isinstance(unit, Class): 873 self.new_op(AddressInstruction(unit.all_class_attributes()[name])) 874 elif isinstance(unit, Module): 875 self.new_op(AddressInstruction(unit.module_attributes()[name])) 876 else: 877 raise TranslateError(self.module.full_name(), node, "Program unit %r has no local %r." % (unit, name)) 878 879 elif scope == "global": 880 globals = self.module.module_attributes() 881 if globals.has_key(name): 882 self.new_op(AddressInstruction(globals[name])) 883 else: 884 raise TranslateError(self.module.full_name(), node, "Module %r has no attribute %r." % (self.module, name)) 885 886 else: 887 self.new_op(AddressInstruction(self.get_builtin(name, node))) 888 889 def _visitUnary(self, node): 890 891 """ 892 _t = node.expr 893 try: 894 _result = _t.__pos__() 895 except AttributeError: 896 raise TypeError 897 """ 898 899 method = unary_methods[node.__class__.__name__] 900 901 type_error_block = self.new_block() 902 end_block = self.new_block() 903 904 # Evaluate and store the operand in temporary storage. 905 906 self.dispatch(node.expr) 907 temp = self.optimiser.optimise_temp_storage() 908 909 self.new_op(temp) 910 911 # Get the method on temp. 912 913 self._generateAttr(node, method, self.attribute_load_instructions) 914 temp_method = self.optimiser.optimise_temp_storage() 915 916 self._handleAttributeError(node, type_error_block) 917 918 # Add arguments. 919 # NOTE: No support for defaults. 920 921 self._startCallFunc() 922 self.new_op(temp) # Explicit context as first argument. 923 self.new_op(StoreFrame(0)) 924 self._endCallFuncArgs(1) 925 self._doCallFunc(temp_method) 926 self._endCallFunc(temp_method) 927 928 # Store the result. 929 930 temp_out = self.get_temp() 931 self.new_op(Jump(end_block)) 932 933 # Raise a TypeError. 934 935 self.set_block(type_error_block) 936 self.load_builtin("TypeError", node) 937 self.new_op(StoreException()) 938 self.new_op(RaiseException()) 939 940 self.set_block(end_block) 941 942 # Produce the result. 943 944 self.new_op(temp_out) 945 946 # Compilation duties... 947 948 self.discard_temp(temp) 949 self.discard_temp(temp_out) 950 951 def _visitBinary(self, node): 952 953 """ 954 _t1 = node.left 955 _t2 = node.right 956 try: 957 _result = _t1.__add__(_t2) 958 if _result is NotImplemented: 959 raise AttributeError 960 except AttributeError: 961 try: 962 _result = _t2.__radd__(_t1) 963 if _result is NotImplemented: 964 raise AttributeError 965 except AttributeError: 966 raise TypeError 967 """ 968 969 left_method, right_method = binary_methods[node.__class__.__name__] 970 971 # Evaluate and store the left operand in temporary storage. 972 973 self.dispatch(node.left) 974 temp1 = self.optimiser.optimise_temp_storage() 975 976 # Evaluate and store the right operand in temporary storage. 977 978 self.dispatch(node.right) 979 temp2 = self.optimiser.optimise_temp_storage() 980 981 temp_out = self._generateBinary(node, temp1, temp2, left_method, right_method) 982 983 # Produce the result. 984 985 self.new_op(temp_out) 986 987 # Compilation duties... 988 989 self.discard_temp(temp1) 990 self.discard_temp(temp2) 991 self.discard_temp(temp_out) 992 993 def _generateBinary(self, node, temp1, temp2, left_method, right_method): 994 995 """ 996 For the given 'node', generate the binary operator pattern for the 997 operands 'temp1' and 'temp2', employing 'left_method' and 'right_method' 998 as defined for binary operators, but also used in comparisons (for which 999 this method is provided). 1000 1001 A temporary storage reference is returned from this method. 1002 """ 1003 1004 right_block = self.new_block() 1005 type_error_block = self.new_block() 1006 end_block = self.new_block() 1007 1008 # Left method. 1009 1010 temp_out = self._generateOpMethod(node, temp1, temp2, left_method, right_block, end_block) 1011 self.discard_temp(temp_out) # NOTE: Will re-use the same storage. 1012 1013 # Right method. 1014 1015 self.set_block(right_block) 1016 temp_out = self._generateOpMethod(node, temp2, temp1, right_method, type_error_block, end_block) 1017 1018 # Raise a TypeError. 1019 1020 self.set_block(type_error_block) 1021 self.load_builtin("TypeError", node) 1022 self.new_op(StoreException()) 1023 self.new_op(RaiseException()) 1024 1025 self.set_block(end_block) 1026 return temp_out 1027 1028 def _generateOpMethod(self, node, temp1, temp2, method_name, next_method_block, end_block): 1029 1030 """ 1031 For the given 'node', generate the operator method invocation using the 1032 operands 'temp1' and 'temp2', employing the given 'method_name', and 1033 jumping appropriately to 'next_method_block' where a NotImplemented 1034 result is returned, or to 'end_block' if the method call was successful. 1035 1036 A temporary storage reference is returned from this method. 1037 """ 1038 1039 end_attempt_block = self.new_block() 1040 1041 self.new_op(temp1) 1042 1043 # Get method on temp1. 1044 1045 self._generateAttr(node, method_name, self.attribute_load_instructions) 1046 temp_method = self.optimiser.optimise_temp_storage() 1047 1048 self._handleAttributeError(node, end_attempt_block) 1049 1050 # Add arguments. 1051 # NOTE: No support for defaults. 1052 1053 self._startCallFunc() 1054 self.new_op(temp1) 1055 self.new_op(StoreFrame(0)) 1056 self.new_op(temp2) 1057 self.new_op(StoreFrame(1)) 1058 self._endCallFuncArgs(2) 1059 self._doCallFunc(temp_method) 1060 self._endCallFunc(temp_method) 1061 1062 # Store the result. 1063 1064 temp_out = self.get_temp() 1065 1066 # Test for NotImplemented. 1067 # Don't actually raise an exception. 1068 1069 self.new_op(TestIdentityAddress(self.importer.get_predefined_constant("NotImplemented"))) 1070 self.new_op(JumpIfTrue(next_method_block)) 1071 self.new_op(Jump(end_block)) 1072 1073 # End method attempt. 1074 1075 self.set_block(end_attempt_block) 1076 return temp_out 1077 1078 def _handleAttributeError(self, node, end_call_block): 1079 1080 """ 1081 Add exception handling to the method acquisition instructions where the 1082 attribute access cannot be resolved at compile-time. 1083 """ 1084 1085 if not self.optimiser.optimise_known_target(): 1086 self.load_builtin("AttributeError", node) 1087 self.new_op(CheckException()) 1088 self.new_op(JumpIfTrue(end_call_block)) 1089 1090 def _generateSequence(self, sequence_type, node): 1091 1092 "Make a sequence of 'sequence_type' for the given program 'node'." 1093 1094 self.make_object(self.get_builtin_class(sequence_type, node), len(node.nodes)) 1095 temp = self.get_temp() 1096 1097 for i, n in enumerate(node.nodes): 1098 self.dispatch(n) 1099 self.record_value() 1100 self.new_op(temp) 1101 self.new_op(StoreAttr(Attr(i, None, None))) 1102 self.set_source() 1103 self.discard_value() 1104 1105 self.new_op(temp) 1106 self.discard_temp(temp) 1107 1108 def _generateTestBoolean(self, node, temp): 1109 1110 """ 1111 Generate a test of the boolean status of the current value for the given 1112 program 'node'. 1113 """ 1114 1115 # Get method on temp. 1116 # NOTE: Using __bool__ instead of __nonzero__. 1117 1118 self._generateAttr(node, "__bool__", self.attribute_load_instructions) 1119 temp_method = self.optimiser.optimise_temp_storage() 1120 1121 self._startCallFunc() 1122 self.new_op(temp) 1123 self.new_op(StoreFrame(0)) 1124 self._endCallFuncArgs(1) 1125 self._doCallFunc(temp_method) 1126 self._endCallFunc(temp_method) 1127 1128 self.discard_temp(temp_method) 1129 1130 # Convert result to boolean (a StoreBoolean operation). 1131 1132 self.new_op(TestIdentityAddress(self.importer.get_predefined_constant("True"))) 1133 1134 def _generateLoadBoolean(self, node): 1135 1136 """ 1137 Generate instructions to load the appropriate value given the current 1138 boolean status. 1139 """ 1140 1141 true_block = self.new_block() 1142 end_block = self.new_block() 1143 1144 self.new_op(JumpIfTrue(true_block)) 1145 self.new_op(LoadConst(self.importer.get_predefined_constant("False"))) 1146 self.new_op(Jump(end_block)) 1147 1148 self.set_block(true_block) 1149 self.new_op(LoadConst(self.importer.get_predefined_constant("True"))) 1150 1151 self.set_block(end_block) 1152 1153 # vim: tabstop=4 expandtab shiftwidth=4