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 # For other parameter lists, only accept as many arguments as we are 723 # allowed. 724 725 elif nargs > nargs_max: 726 raise TranslateError(self.module.full_name(), node, 727 "Too many arguments for %r: need at most %d argument(s)." % (target.name, nargs_max)) 728 729 else: 730 frame_size = nargs_max 731 732 # Where defaults are involved, put them into the frame. 733 734 self._generateCallFuncDefaultArgs(target, temp, nargs_min, nargs_max, employed_positions) 735 736 # Set the frame size. 737 738 self._endCallFuncArgs(frame_size) 739 740 # Or generate instructions to do this at run-time. 741 742 else: 743 max_pos = max(max(employed_positions or [-1]), max_keyword_pos, frame_pos - 1) 744 745 # Only check non-empty frames (using the callable's details). 746 747 if employed_positions or max_pos >= 0: 748 self.new_op(temp) 749 self.new_op(CheckFrame(max_pos + 1)) 750 751 # Set the frame size. 752 753 self._endCallFuncArgs(max_pos + 1) 754 755 def _generateCallFuncDefaultArgs(self, target, temp, nargs_min, nargs_max, employed_positions): 756 757 """ 758 For the given 'target' and 'temp' reference to the target, generate 759 default arguments for those positions in the range 'nargs_min'... 760 'nargs_max' which are not present in the 'employed_positions' 761 collection. 762 """ 763 764 # Where a lambda is involved, construct a dynamic object to hold the 765 # defaults. 766 767 dynamic = target.name is None 768 769 # Here, we use negative index values to visit the right hand end of 770 # the defaults list. 771 772 for pos in range(nargs_min, nargs_max): 773 if pos not in employed_positions: 774 if dynamic: 775 self.new_op(temp) 776 self.new_op(LoadAttr(target.default_attrs[pos - nargs_min])) 777 else: 778 self.new_op(LoadAddress(target.default_attrs[pos - nargs_min])) 779 self.new_op(StoreFrame(pos)) 780 781 def _doCallFunc(self, instruction, target=None): 782 783 "Make the invocation." 784 785 # For classes, the target itself is used, since the instantiator will be 786 # obtained via the class. 787 788 if isinstance(target, Class): 789 self.new_op(LoadConst(target)) 790 else: 791 self.new_op(instruction) 792 793 self.new_op(LoadCallable()) 794 self.new_op(JumpWithFrame()) 795 796 def _endCallFuncArgs(self, nargs): 797 798 "Set the frame size." 799 800 self.frame_makers[-1].attr = nargs 801 self.frame_makers.pop() 802 803 def _endCallFunc(self, instruction=None, target=None, load_result=1): 804 805 "Finish the invocation and tidy up afterwards." 806 807 self.new_op(DropFrame()) 808 if load_result: 809 self.new_op(LoadResult()) 810 811 # Discard any temporary storage instructions. 812 813 if instruction is not None: 814 self.discard_temp(instruction) 815 816 def _generateFunctionDefaults(self, function): 817 818 """ 819 Generate the default initialisation code for 'function', returning 820 a temporary storage reference if a dynamic object was created for the 821 function. 822 """ 823 824 attr_to_default = zip(function.default_attrs, function.defaults) 825 if not attr_to_default: 826 return None 827 828 # Where a lambda is involved, construct a dynamic object to hold the 829 # defaults. 830 831 dynamic = function.name is None 832 833 if dynamic: 834 self.make_object(self.get_builtin_class("function", function), len(attr_to_default)) 835 temp = self.get_temp() 836 837 for attr, default in attr_to_default: 838 self.dispatch(default) 839 840 self.record_value() 841 if dynamic: 842 self.new_op(temp) 843 self.new_op(StoreAttr(attr)) 844 else: 845 self.new_op(StoreAddress(attr)) 846 self.set_source() 847 self.discard_value() 848 849 if dynamic: 850 return temp 851 else: 852 return None 853 854 def _visitName(self, node, classes): 855 856 """ 857 Visit the name-related 'node', generating instructions based on the 858 given 'classes'. 859 """ 860 861 name = node.name 862 scope = self.get_scope(name) 863 #print self.module.name, node.lineno, name, scope 864 self._generateName(name, scope, classes, node) 865 866 def _generateName(self, name, scope, classes, node): 867 868 """ 869 Generate code for the access to 'name' in 'scope' using the given 870 'classes', and using the given 'node' as the source of the access. 871 """ 872 873 NameInstruction, AddressInstruction = classes 874 875 if scope == "local": 876 unit = self.unit 877 if isinstance(unit, Function): 878 self.new_op(NameInstruction(unit.all_locals()[name])) 879 elif isinstance(unit, Class): 880 self.new_op(AddressInstruction(unit.all_class_attributes()[name])) 881 elif isinstance(unit, Module): 882 self.new_op(AddressInstruction(unit.module_attributes()[name])) 883 else: 884 raise TranslateError(self.module.full_name(), node, "Program unit %r has no local %r." % (unit, name)) 885 886 elif scope == "global": 887 globals = self.module.module_attributes() 888 if globals.has_key(name): 889 self.new_op(AddressInstruction(globals[name])) 890 else: 891 raise TranslateError(self.module.full_name(), node, "Module %r has no attribute %r." % (self.module, name)) 892 893 else: 894 self.new_op(AddressInstruction(self.get_builtin(name, node))) 895 896 def _visitUnary(self, node): 897 898 """ 899 _t = node.expr 900 try: 901 _result = _t.__pos__() 902 except AttributeError: 903 raise TypeError 904 """ 905 906 method = unary_methods[node.__class__.__name__] 907 908 type_error_block = self.new_block() 909 end_block = self.new_block() 910 911 # Evaluate and store the operand in temporary storage. 912 913 self.dispatch(node.expr) 914 temp = self.optimiser.optimise_temp_storage() 915 916 self.new_op(temp) 917 918 # Get the method on temp. 919 920 self._generateAttr(node, method, self.attribute_load_instructions) 921 temp_method = self.optimiser.optimise_temp_storage() 922 923 self._handleAttributeError(node, type_error_block) 924 925 # Add arguments. 926 # NOTE: No support for defaults. 927 928 self._startCallFunc() 929 self.new_op(temp) # Explicit context as first argument. 930 self.new_op(StoreFrame(0)) 931 self._endCallFuncArgs(1) 932 self._doCallFunc(temp_method) 933 self._endCallFunc(temp_method) 934 self.new_op(Jump(end_block)) 935 936 # Store the result. 937 938 temp_out = self.get_temp() 939 940 # Raise a TypeError. 941 942 self.set_block(type_error_block) 943 self.load_builtin("TypeError", node) 944 self.new_op(StoreException()) 945 self.new_op(RaiseException()) 946 947 self.set_block(end_block) 948 949 # Produce the result. 950 951 self.new_op(temp_out) 952 953 # Compilation duties... 954 955 self.discard_temp(temp) 956 self.discard_temp(temp_out) 957 958 def _visitBinary(self, node): 959 960 """ 961 _t1 = node.left 962 _t2 = node.right 963 try: 964 _result = _t1.__add__(_t2) 965 if _result is NotImplemented: 966 raise AttributeError 967 except AttributeError: 968 try: 969 _result = _t2.__radd__(_t1) 970 if _result is NotImplemented: 971 raise AttributeError 972 except AttributeError: 973 raise TypeError 974 """ 975 976 left_method, right_method = binary_methods[node.__class__.__name__] 977 978 # Evaluate and store the left operand in temporary storage. 979 980 self.dispatch(node.left) 981 temp1 = self.optimiser.optimise_temp_storage() 982 983 # Evaluate and store the right operand in temporary storage. 984 985 self.dispatch(node.right) 986 temp2 = self.optimiser.optimise_temp_storage() 987 988 temp_out = self._generateBinary(node, temp1, temp2, left_method, right_method) 989 990 # Produce the result. 991 992 self.new_op(temp_out) 993 994 # Compilation duties... 995 996 self.discard_temp(temp1) 997 self.discard_temp(temp2) 998 self.discard_temp(temp_out) 999 1000 def _generateBinary(self, node, temp1, temp2, left_method, right_method): 1001 1002 """ 1003 For the given 'node', generate the binary operator pattern for the 1004 operands 'temp1' and 'temp2', employing 'left_method' and 'right_method' 1005 as defined for binary operators, but also used in comparisons (for which 1006 this method is provided). 1007 1008 A temporary storage reference is returned from this method. 1009 """ 1010 1011 right_block = self.new_block() 1012 type_error_block = self.new_block() 1013 end_block = self.new_block() 1014 1015 # Left method. 1016 1017 temp_out = self._generateOpMethod(node, temp1, temp2, left_method, right_block, end_block) 1018 self.discard_temp(temp_out) # NOTE: Will re-use the same storage. 1019 1020 # Right method. 1021 1022 self.set_block(right_block) 1023 temp_out = self._generateOpMethod(node, temp2, temp1, right_method, type_error_block, end_block) 1024 1025 # Raise a TypeError. 1026 1027 self.set_block(type_error_block) 1028 self.load_builtin("TypeError", node) 1029 self.new_op(StoreException()) 1030 self.new_op(RaiseException()) 1031 1032 self.set_block(end_block) 1033 return temp_out 1034 1035 def _generateOpMethod(self, node, temp1, temp2, method_name, next_method_block, end_block): 1036 1037 """ 1038 For the given 'node', generate the operator method invocation using the 1039 operands 'temp1' and 'temp2', employing the given 'method_name', and 1040 jumping appropriately to 'next_method_block' where a NotImplemented 1041 result is returned, or to 'end_block' if the method call was successful. 1042 1043 A temporary storage reference is returned from this method. 1044 """ 1045 1046 end_attempt_block = self.new_block() 1047 1048 self.new_op(temp1) 1049 1050 # Get method on temp1. 1051 1052 self._generateAttr(node, method_name, self.attribute_load_instructions) 1053 temp_method = self.optimiser.optimise_temp_storage() 1054 1055 self._handleAttributeError(node, end_attempt_block) 1056 1057 # Add arguments. 1058 # NOTE: No support for defaults. 1059 1060 self._startCallFunc() 1061 self.new_op(temp1) 1062 self.new_op(StoreFrame(0)) 1063 self.new_op(temp2) 1064 self.new_op(StoreFrame(1)) 1065 self._endCallFuncArgs(2) 1066 self._doCallFunc(temp_method) 1067 self._endCallFunc(temp_method) 1068 1069 # Store the result. 1070 1071 temp_out = self.get_temp() 1072 1073 # Test for NotImplemented. 1074 # Don't actually raise an exception. 1075 1076 self.new_op(TestIdentityAddress(self.importer.get_predefined_constant("NotImplemented"))) 1077 self.new_op(JumpIfTrue(next_method_block)) 1078 self.new_op(Jump(end_block)) 1079 1080 # End method attempt. 1081 1082 self.set_block(end_attempt_block) 1083 return temp_out 1084 1085 def _handleAttributeError(self, node, end_call_block): 1086 1087 """ 1088 Add exception handling to the method acquisition instructions where the 1089 attribute access cannot be resolved at compile-time. 1090 """ 1091 1092 if not self.optimiser.optimise_known_target(): 1093 self.load_builtin("AttributeError", node) 1094 self.new_op(CheckException()) 1095 self.new_op(JumpIfTrue(end_call_block)) 1096 1097 def _generateSequence(self, sequence_type, node): 1098 1099 "Make a sequence of 'sequence_type' for the given program 'node'." 1100 1101 self.make_object(self.get_builtin_class(sequence_type, node), len(node.nodes)) 1102 temp = self.get_temp() 1103 1104 for i, n in enumerate(node.nodes): 1105 self.dispatch(n) 1106 self.record_value() 1107 self.new_op(temp) 1108 self.new_op(StoreAttr(Attr(i, None, None))) 1109 self.set_source() 1110 self.discard_value() 1111 1112 self.new_op(temp) 1113 self.discard_temp(temp) 1114 1115 def _generateTestBoolean(self, node, temp): 1116 1117 """ 1118 Generate a test of the boolean status of the current value for the given 1119 program 'node'. 1120 """ 1121 1122 # Get method on temp. 1123 # NOTE: Using __bool__ instead of __nonzero__. 1124 1125 self._generateAttr(node, "__bool__", self.attribute_load_instructions) 1126 temp_method = self.optimiser.optimise_temp_storage() 1127 1128 self._startCallFunc() 1129 self.new_op(temp) 1130 self.new_op(StoreFrame(0)) 1131 self._endCallFuncArgs(1) 1132 self._doCallFunc(temp_method) 1133 self._endCallFunc(temp_method) 1134 1135 self.discard_temp(temp_method) 1136 1137 # Convert result to boolean (a StoreBoolean operation). 1138 1139 self.new_op(TestIdentityAddress(self.importer.get_predefined_constant("True"))) 1140 1141 def _generateLoadBoolean(self, node): 1142 1143 """ 1144 Generate instructions to load the appropriate value given the current 1145 boolean status. 1146 """ 1147 1148 true_block = self.new_block() 1149 end_block = self.new_block() 1150 1151 self.new_op(JumpIfTrue(true_block)) 1152 self.new_op(LoadConst(self.importer.get_predefined_constant("False"))) 1153 self.new_op(Jump(end_block)) 1154 1155 self.set_block(true_block) 1156 self.new_op(LoadConst(self.importer.get_predefined_constant("True"))) 1157 1158 self.set_block(end_block) 1159 1160 # vim: tabstop=4 expandtab shiftwidth=4