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