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, 2010, 2011 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_instance(self, cls, n): 34 35 """ 36 Request a new instance using the given class 'cls' and with 'n' 37 attributes. 38 """ 39 40 # Load the class in order to locate the instance template. 41 42 self.new_op(LoadConst(cls)) 43 44 # NOTE: Instance headers are one location. 45 46 self.new_op(MakeInstance(n + 1)) 47 48 def make_exception(self, name, node): 49 50 "Make an exception of the given 'name' using 'node'." 51 52 # NOTE: Reserving an attribute. 53 54 self.make_instance(self.get_builtin_class(name, node), 1) 55 56 # Name-related methods. 57 58 def get_scope(self, name): 59 60 "Return the scope for the given 'name'." 61 62 attr, scope, from_name = self.unit._get_with_scope(name) 63 return scope 64 65 def load_builtin(self, name, node): 66 67 "Generate an instruction loading 'name' for the given 'node'." 68 69 self.new_op(LoadAddress(self.get_builtin(name, node))) 70 71 def get_builtin_class(self, name, node): 72 73 "Return the built-in class with the given 'name' for the given 'node'." 74 75 return self.get_builtin(name, node).get_value() 76 77 def get_builtin(self, name, node): 78 79 """ 80 Return the built-in module definition for the given 'name', used by the 81 given 'node'. 82 """ 83 84 if self.builtins is not None: 85 try: 86 return self.builtins[name] 87 except KeyError: 88 raise TranslateError("No __builtins__ definition is available for name %r." % name) 89 else: 90 raise TranslateError("No __builtins__ module is available for name %r." % name) 91 92 # Common methods. 93 94 def _generateGuards(self, node): 95 96 if not (self.optimiser.should_optimise_accesses_by_attribute_usage() and hasattr(node, "_attrtypes")): 97 return 98 99 # For each name, attempt to restrict the type employed. 100 101 for name, targets in node._attrtypes.items(): 102 103 # NOTE: Need to merge targets using the same type but suggesting 104 # NOTE: different kinds of attributes (instance vs. class). 105 106 # Where only one object type is suggested, produce a guard. 107 # NOTE: This only supports classes as types, not modules. 108 109 if len(targets) == 1: 110 target_name, is_static = list(targets)[0] 111 112 # Access the object table to get the attribute. 113 # NOTE: This depends on the special entry in the table 114 # NOTE: for class equivalence tests. 115 116 try: 117 obj = self.objtable.access(target_name, target_name) 118 119 # Where no attribute entry exists, the target could be a module. 120 # NOTE: Should perhaps raise an error. 121 122 except TableError, exc: 123 print "Possible guard for", target_name, "not enforceable." 124 continue 125 126 # NOTE: Could test the correctness of the guard where the nature 127 # NOTE: of the name is known. 128 # NOTE: The known value would be retrieved from the unit's 129 # NOTE: locals and tested as being a class or an instance of a 130 # NOTE: particular class. 131 132 # Generate the guard by loading a reference to the class. 133 134 after_test_block = self.new_block() 135 136 self.new_op(LoadClass(obj)) 137 temp_target = self.optimiser.optimise_temp_storage() 138 139 # For only static attributes, classes are acceptable. 140 141 if is_static: 142 143 # Generate name is target (for classes). 144 145 self.dispatch(compiler.ast.Name(name)) 146 self.new_op(TestIdentity()) 147 self.optimiser.set_source(temp_target) 148 149 # Jump to the next guard or the code if successful. 150 151 self.new_op(JumpIfTrue(after_test_block)) 152 153 # Where instance attributes are involved, only instances are 154 # acceptable. 155 156 # Generate isinstance(name, target). 157 158 self.dispatch(compiler.ast.Name(name)) 159 self.new_op(CheckInstance()) 160 self.optimiser.set_source(temp_target) 161 162 # Jump to the next guard or the code if successful. 163 164 self.new_op(JumpIfTrue(after_test_block)) 165 166 # Where the type is inappropriate, raise an exception. 167 168 self.make_exception("TypeError", node) 169 self.new_op(StoreException()) 170 self.new_op(RaiseException()) 171 172 self.set_block(after_test_block) 173 174 def _visitAttr(self, node, classes): 175 176 """ 177 Visit the attribute-related 'node', generating instructions based on the 178 given 'classes'. 179 """ 180 181 self.dispatch(node.expr) 182 self._generateAttr(node, node.attrname, classes) 183 184 def _generateAttr(self, node, attrname, classes): 185 186 """ 187 Generate code for the access to 'attrname' using the given 'classes'. 188 """ 189 190 AddressInstruction, AddressContextInstruction, AddressContextCondInstruction, \ 191 AttrInstruction, AttrIndexInstruction, AttrIndexContextCondInstruction = classes 192 193 # Where the last operation (defining the attribute owner) yields a 194 # constant... 195 196 target_plus_name = self.optimiser.optimise_constant_accessor() 197 198 # Only try and discover the position if the target can be resolved. 199 # Since instances cannot be constants, this involves classes and 200 # modules. 201 # It is acceptable to replace the instruction providing the constant 202 # input because doing so does not lose any input information required by 203 # the replacement instructions. 204 205 if target_plus_name is not None: 206 target, target_name = target_plus_name 207 208 # Check for class.__class__. 209 210 if attrname == "__class__": 211 if isinstance(target, Class): 212 if AddressInstruction is LoadAddress: 213 self.replace_active_value(LoadAddress(self.get_builtin("type", node))) 214 return 215 else: 216 raise TranslateError("Assigning to __class__ is not permitted.") 217 218 # Access the object table to get the attribute. 219 220 try: 221 attr = self.objtable.access(target_name, attrname) 222 except TableError, exc: 223 raise TranslateError(exc.args[0]) 224 225 # Produce a suitable instruction. 226 227 if AddressInstruction is not None: 228 self.replace_active_value(AddressInstruction(attr)) 229 else: 230 raise TranslateError("Storing of class or module attribute %r via an object is not permitted." % attrname) 231 232 return 233 234 # Where the last operation involves the special 'self' name, check to 235 # see if the attribute is acceptably positioned and produce a direct 236 # access to the attribute. 237 238 # This is the only reliable way of detecting instance accesses at 239 # compile-time since in general, objects could be classes or modules, 240 # but 'self' should only refer to instances. 241 242 elif self.optimiser.optimise_self_access(self.unit, attrname): 243 244 # Either generate an instruction operating on an instance attribute. 245 246 try: 247 attr = self.unit.parent.instance_attributes()[attrname] 248 self.new_op(AttrInstruction(attr)) 249 return 250 251 # Or generate an instruction operating on a class attribute. 252 # NOTE: Any simple instruction providing self is not removed. 253 254 except KeyError: 255 256 try: 257 attr = self.unit.parent.all_attributes()[attrname] 258 259 # Switch the context if the class attribute is compatible with 260 # the instance. 261 262 if attr.defined_within_hierarchy(): 263 264 # Only permit loading (not storing) of class attributes via self. 265 266 if AddressContextInstruction is not None: 267 self.new_op(AddressContextInstruction(attr)) 268 else: 269 raise TranslateError("Storing of class attribute %r via self not permitted." % attrname) 270 271 # Preserve the context if the class attribute comes from an 272 # incompatible class. 273 274 elif attr.defined_outside_hierarchy(): 275 276 # Only permit loading (not storing) of class attributes via self. 277 278 if AddressInstruction is not None: 279 self.new_op(AddressInstruction(attr)) 280 else: 281 raise TranslateError("Storing of class attribute %r via self not permitted." % attrname) 282 283 # Otherwise, test for a suitable context at run-time. 284 285 else: 286 287 # Only permit loading (not storing) of class attributes via self. 288 289 if AddressContextCondInstruction is not None: 290 self.new_op(AddressContextCondInstruction(attr)) 291 else: 292 raise TranslateError("Storing of class attribute %r via self not permitted." % attrname) 293 294 return 295 296 # Or delegate the attribute access to a general instruction 297 # since the kind of attribute cannot be deduced. 298 299 except KeyError: 300 pass 301 302 # Attempt to deduce the target of an attribute access by searching for a 303 # unique type providing the names associated with the accessed object. 304 305 elif self.optimiser.should_optimise_accesses_by_attribute_usage(): 306 307 target_names = self.possible_accessor_types(node) 308 309 if target_names is not None and len(target_names) == 1: 310 target_name, is_static = list(target_names)[0] 311 312 # Check for class.__class__. 313 314 if attrname == "__class__": 315 if is_static: 316 self.load_builtin("type", node) 317 return 318 319 # Access the object table to get the attribute. 320 321 try: 322 attr = self.objtable.access(target_name, attrname) 323 324 # Disallow non-class/instance optimisations. 325 326 except TableError, exc: 327 print "Possible optimisation for", target_name, "not permissable." 328 329 # Produce a suitable instruction. 330 331 else: 332 if AddressContextCondInstruction is not None and attr.is_static_attribute(): 333 self.new_op(AddressContextCondInstruction(attr)) 334 elif AttrInstruction is not None and not attr.is_static_attribute(): 335 self.new_op(AttrInstruction(attr)) 336 else: 337 raise TranslateError("Storing of class or module attribute %r via an object is not permitted." % attrname) 338 339 return 340 341 # Check for class.__class__. 342 343 if attrname == "__class__": 344 345 # Remember the accessor. 346 347 temp_accessor = self.optimiser.optimise_temp_storage() 348 349 attr_block = self.new_block() 350 end_block = self.new_block() 351 352 self.new_op(CheckClass()) 353 self.new_op(JumpIfFalse(attr_block)) 354 self.load_builtin("type", node) 355 self.new_op(Jump(end_block)) 356 self.set_block(attr_block) 357 358 # Recall the accessor. 359 360 self.new_op(temp_accessor) 361 362 # Otherwise, perform a normal operation. 363 364 try: 365 index = self.objtable.get_index(attrname) 366 367 except self.objtable.TableError: 368 369 # If this error arises on generated code, check the names_used 370 # attribute on the Importer. 371 372 raise TranslateError("No attribute entry exists for name %r." % attrname) 373 374 # NOTE: Test for class vs. instance attributes, generating 375 # NOTE: context-related instructions. 376 377 if AttrIndexContextCondInstruction is not None: 378 self.new_op(AttrIndexContextCondInstruction(index)) 379 380 # Store instructions do not need to consider context modifications. 381 382 else: 383 self.new_op(AttrIndexInstruction(index)) 384 385 # Where __class__ was involved, define the start of the following code. 386 387 if attrname == "__class__": 388 self.set_block(end_block) 389 390 # Invocations involve the following: 391 # 392 # 1. Reservation of a frame for the arguments 393 # 2. Identification of the target which is then held in temporary storage 394 # 3. Optional inclusion of a context (important for methods) 395 # 4. Preparation of the argument frame 396 # 5. Invocation of the target 397 # 6. Discarding of the frame 398 # 399 # In order to support nested invocations - such as a(b(c)) - use of the 400 # temporary storage is essential. 401 402 def _startCallFunc(self): 403 404 "Record the location of the invocation." 405 406 op = MakeFrame() 407 self.new_op(op) # records the start of the frame 408 self.frame_makers.append(op) 409 410 def _generateCallFunc(self, args, node): 411 412 """ 413 Support a generic function invocation using the given 'args', occurring 414 on the given 'node', where the expression providing the invocation 415 target has just been generated. 416 417 In other situations, the invocation is much simpler and does not need to 418 handle the full flexibility of a typical Python invocation. Internal 419 invocations, such as those employed by operators and certain 420 control-flow mechanisms, use predetermined arguments and arguably do not 421 need to support the same things as the more general invocations. 422 """ 423 424 target, context, temp_target, temp_context = self._generateCallFuncContext() 425 self._generateCallFuncArgs(target, context, temp_target, temp_context, args, node) 426 return temp_target, target, temp_context 427 428 def _generateCallFuncContext(self): 429 430 """ 431 Produce code which loads and checks the context of the current 432 invocation, the instructions for whose target have already been 433 produced, returning a list of instructions which reference the 434 invocation target. 435 """ 436 437 t = self.optimiser.optimise_known_target() 438 if t: 439 target, context = t 440 441 # Detect dynamic functions acting like instances. 442 443 if isinstance(target, Function) and target.is_dynamic(): 444 target, context = None, None 445 else: 446 target, context = None, None 447 448 # Store the target in temporary storage for subsequent referencing. 449 450 temp_target = self.optimiser.optimise_temp_storage() 451 452 # Where a target or context are not known or where an instance is known 453 # to be the context, load the context. 454 455 if target is None or isinstance(context, Instance): 456 self.new_op(temp_target) 457 self.new_op(LoadContextIntoValue()) 458 temp_context = self.optimiser.optimise_temp_storage() 459 self.new_op(StoreFrame(0)) 460 461 # Class contexts should be made available for testing of the first 462 # argument. 463 # NOTE: Class methods should eventually be supported. 464 465 elif isinstance(context, Class): 466 self.new_op(temp_target) 467 self.new_op(LoadContextIntoValue()) 468 temp_context = self.optimiser.optimise_temp_storage() 469 470 # Otherwise omit the context. 471 472 else: 473 temp_context = None 474 475 return target, context, temp_target, temp_context 476 477 def _generateCallFuncArgs(self, target, context, temp_target, temp_context, args, node): 478 479 """ 480 Given invocation 'target' and 'context' information, the 'temp_target' 481 reference to the target, the 'temp_context' reference to the context, a 482 list of nodes representing the 'args' (arguments), generate instructions 483 which load the arguments for the invocation defined by the given 'node'. 484 """ 485 486 # Evaluate the arguments. 487 488 employed_positions = set() 489 employed_keywords = set() 490 extra_keywords = [] 491 positional_args = [] 492 keyword_args = [] 493 494 # Find keyword arguments in advance in order to help resolve targets. 495 496 have_keywords = 0 497 498 for arg in args: 499 if isinstance(arg, compiler.ast.Keyword): 500 employed_keywords.add(arg.name) 501 keyword_args.append(arg) 502 have_keywords = 1 503 elif not have_keywords: 504 positional_args.append(arg) 505 506 possible_targets = self.paramtable.all_possible_objects(employed_keywords) 507 508 # Note the presence of the context in the frame where appropriate. 509 510 # For unknown invocations and method invocations. 511 512 if target is None or isinstance(context, Instance): 513 ncontext = 1 514 expect_testable_self = 0 515 516 # Handle calls to classes by obtaining the instantiator function. 517 # A context is reserved for the new instance, but this is not provided 518 # in the invocation (since the instantiator will fill the locals slot 519 # concerned). 520 521 elif isinstance(target, Class): 522 ncontext = 1 523 expect_testable_self = 0 524 target = target.get_instantiator() 525 526 # Method calls via classes. 527 528 elif isinstance(context, Class): 529 ncontext = 0 530 expect_testable_self = 1 531 532 # Function calls. 533 534 else: 535 ncontext = 0 536 expect_testable_self = 0 537 538 # Traverse the positional arguments adding them using the incrementing 539 # frame position. 540 541 first = 1 542 frame_pos = ncontext 543 temp_first_argument = None 544 545 for arg in positional_args: 546 self.dispatch(arg) 547 self.new_op(StoreFrame(frame_pos)) 548 employed_positions.add(frame_pos) 549 550 # Check to see if the first argument is appropriate (compatible with 551 # the target where methods are being invoked via classes). 552 553 if first and (expect_testable_self or target is None): 554 555 # Drop any test if the target and the context are known. 556 557 if not self.optimiser.have_correct_self_for_target(context, self.unit): 558 559 # Otherwise, remember the first argument for a subsequent 560 # test. 561 562 temp_first_argument = self.optimiser.optimise_temp_storage() 563 564 first = 0 565 frame_pos += 1 566 567 # Adjust the invocation frame for unknown invocations. 568 # Test the first argument if appropriate. 569 570 self._generateCallFuncContextTest(temp_target, target, temp_context, temp_first_argument, node) 571 572 # Traverse the keyword arguments adding them at the appropriate frame 573 # positions. 574 575 max_keyword_pos = -1 576 577 for arg in keyword_args: 578 579 # Optimise where the target is known now. 580 581 if target is not None: 582 583 # Find the parameter table entry for the target. 584 585 target_name = target.full_name() 586 587 # Look for a callable with the precise target name. 588 589 table_entry = self.paramtable.table[target_name] 590 591 # Look the name up in the parameter table entry. 592 593 try: 594 pos = table_entry[arg.name] 595 596 # Where no position is found, this could be an extra keyword 597 # argument. 598 599 except KeyError: 600 extra_keywords.append(arg) 601 continue 602 603 # Test for illegal conditions. 604 605 if pos in employed_positions: 606 raise TranslateError("Keyword argument %r overwrites parameter %r." % (arg.name, pos)) 607 608 employed_positions.add(pos) 609 610 # Generate code for the keyword and the positioning 611 # operation. 612 613 self.dispatch(arg.expr) 614 self.new_op(StoreFrame(pos)) 615 616 # Otherwise, generate the code needed to obtain the details of 617 # the parameter location. 618 619 else: 620 621 # Combine the target details with the name to get the location. 622 # See the access method on the List class. 623 624 try: 625 paramindex = self.paramtable.get_index(arg.name) 626 627 # Where no position is found, this could be an extra keyword 628 # argument. 629 630 except self.paramtable.TableError: 631 extra_keywords.append(arg) 632 continue 633 634 # Generate code for the keyword and the positioning 635 # operation. Get the value as the source of the assignment. 636 637 self.dispatch(arg.expr) 638 self.record_value() 639 640 # Store the source value using the callable's parameter 641 # table information. 642 643 self.new_op(temp_target) 644 self.new_op(StoreFrameIndex(paramindex)) 645 646 self.set_source() 647 self.discard_value() 648 649 # Record the highest possible frame position for this argument. 650 651 max_keyword_pos = max(max_keyword_pos, max(self.paramtable.all_attribute_positions(arg.name))) 652 653 # Use the frame position counter as a general argument counter. 654 655 frame_pos += 1 656 657 # NOTE: Extra keywords are not supported. 658 # NOTE: Somehow, the above needs to be combined with * arguments. 659 660 if extra_keywords: 661 print "Warning: extra keyword argument(s) %s not handled." % ", ".join([arg.name for arg in extra_keywords]) 662 663 # Either test for a complete set of arguments. 664 665 if target is not None: 666 667 # Make sure that enough arguments have been given. 668 669 nargs_max = len(target.positional_names) 670 ndefaults = len(target.defaults) 671 nargs_min = nargs_max - ndefaults 672 673 # Visit each argument position and look for a supplied argument. 674 675 for i in range(ncontext, nargs_min): 676 if i not in employed_positions: 677 raise TranslateError( 678 "Argument %r not supplied for %r: need at least %d argument(s)." % (i+1, target.name, nargs_min)) 679 680 nargs = frame_pos 681 682 # Determine whether too many arguments have been given and how big 683 # the frame should be. 684 685 # For parameter lists with * or ** parameters, accept as many 686 # arguments as are allowed or as many as we have. 687 688 if target.has_star or target.has_dstar: 689 frame_size = max(nargs, nargs_max) 690 691 # NOTE: We now need to pack these arguments into a suitable 692 # NOTE: structure for the * parameter. 693 694 # For other parameter lists, only accept as many arguments as we are 695 # allowed. 696 697 elif nargs > nargs_max: 698 raise TranslateError( 699 "Too many arguments for %r: need at most %d argument(s)." % (target.name, nargs_max)) 700 701 else: 702 frame_size = nargs_max 703 704 # Where defaults are involved, put them into the frame. 705 706 self._generateCallFuncDefaultArgs(target, temp_target, nargs_min, nargs_max, employed_positions) 707 708 # Set the frame size. 709 710 self._endCallFuncArgs(frame_size) 711 712 # Or just set the frame size and have the function check the arguments. 713 714 else: 715 max_pos = max(max(employed_positions or [-1]), max_keyword_pos, frame_pos - 1) 716 self._endCallFuncArgs(max_pos + 1) 717 718 def _generateCallFuncDefaultArgs(self, target, temp_target, nargs_min, nargs_max, employed_positions): 719 720 """ 721 For the given 'target' and 'temp_target' reference to the target, 722 generate default arguments for those positions in the range 723 'nargs_min'...'nargs_max' which are not present in the 724 'employed_positions' collection. 725 """ 726 727 # Where appropriate, construct a dynamic object to hold the defaults. 728 729 dynamic = target.is_dynamic() 730 731 # Here, we use negative index values to visit the right hand end of 732 # the defaults list. 733 734 for pos in range(nargs_min, nargs_max): 735 if pos not in employed_positions: 736 if dynamic: 737 self.new_op(temp_target) 738 self.new_op(LoadAttr(target.default_attrs[pos - nargs_min])) 739 else: 740 self.new_op(LoadAddress(target.default_attrs[pos - nargs_min])) 741 self.new_op(StoreFrame(pos)) 742 743 def _generateCallFuncContextTest(self, temp_target, target, temp_context, temp_first_argument, node): 744 745 """ 746 Generate code to test for 'temp_target', representing the given 747 'target', the context provided by 'temp_context' against 748 'temp_first_argument', and to signal an exception (using 'node') if the 749 context is incompatible with the first frame argument. 750 751 In addition, the invocation frame will be shifted if 'temp_context' 752 indicates a function or a class. 753 """ 754 755 adjust_block = self.new_block() 756 continue_block = self.new_block() 757 758 # Add some preliminary tests where the target is not known. 759 760 if target is None: 761 762 # Adjust the frame if a replaceable context is provided. 763 764 self.new_op(temp_context) 765 self.new_op(CheckContext()) 766 self.new_op(JumpIfFalse(adjust_block)) 767 768 # Skip adjustment and tests if the context is not a class. 769 # Classes themselves employ a placeholder context so that 770 # instantiators can be callable with a context which will be 771 # overwritten in the frame. 772 773 self.new_op(temp_context) 774 self.new_op(CheckClass()) 775 self.new_op(JumpIfFalse(continue_block)) 776 777 if temp_first_argument is not None: 778 self.new_op(temp_first_argument) 779 780 # Check the current value (the argument) against the known context 781 # (given as the source). 782 783 self.new_op(CheckInstance()) 784 self.optimiser.set_source(temp_context) 785 786 self.new_op(JumpIfTrue(adjust_block)) 787 788 # Where the context is inappropriate, drop the incomplete frame and 789 # raise an exception. 790 791 self.new_op(DropFrame()) 792 self.new_op(LoadResultIntoValue()) 793 794 self.make_exception("TypeError", node) 795 self.new_op(StoreException()) 796 self.new_op(RaiseException()) 797 798 if target is None or temp_first_argument is not None: 799 self.set_block(adjust_block) 800 self.new_op(AdjustFrame(1)) 801 802 self.set_block(continue_block) 803 804 def _doCallFunc(self, temp_target, target=None): 805 806 "Make the invocation." 807 808 # For classes, the target itself is used, since the instantiator will be 809 # obtained via the class. 810 811 if isinstance(target, (Class, Function)): 812 self.new_op(JumpWithFrameDirect(target)) 813 else: 814 self.new_op(temp_target) 815 self.new_op(LoadCallable()) 816 self.new_op(JumpWithFrame()) 817 818 def _endCallFuncArgs(self, nargs): 819 820 "Set the frame size." 821 822 self.frame_makers[-1].attr = nargs 823 self.frame_makers.pop() 824 825 def _endCallFunc(self, temp_target=None, temp_context=None, load_result=1): 826 827 "Finish the invocation and tidy up afterwards." 828 829 self.new_op(DropFrame()) 830 if load_result: 831 self.new_op(LoadResultIntoValue()) 832 833 # Discard any temporary storage instructions. 834 835 if temp_target is not None: 836 self.discard_temp(temp_target) 837 838 if temp_context is not None: 839 self.discard_temp(temp_context) 840 841 def _visitFunctionDeclaration(self, node): 842 843 """ 844 Visit the function declaration at 'node', which can be a lambda or a 845 named function. As a consequence an instruction will be generated which 846 provides a reference to the function. 847 """ 848 849 fn = node.unit 850 ndefaults = len(fn.defaults) 851 temp = self._generateFunctionDefaults(fn) 852 853 # Populate the new object required for the function. 854 855 if temp is not None: 856 self.new_op(LoadConst(fn)) 857 self.new_op(LoadCallable()) 858 self.new_op(temp) 859 self.new_op(StoreCallable()) 860 861 self.new_op(temp) 862 #self.discard_temp(temp) 863 else: 864 self.new_op(LoadFunction(fn)) 865 866 def _visitFunctionDefinition(self, node): 867 868 """ 869 Visit the function definition at 'node', which can be a lambda or a 870 named function, generating the prelude with argument and default 871 checking, plus the body of the function itself. 872 """ 873 874 # Check frames using the function's details. 875 876 fn = node.unit 877 nparams = len(fn.positional_names) 878 ndefaults = len(fn.defaults) 879 880 fn.body_block = self.new_block() 881 882 # Check the number of parameters and defaults. 883 884 self.new_op(CheckFrame((nparams, ndefaults))) 885 886 if ndefaults > 0: 887 if fn.is_dynamic(): 888 self.new_op(LoadTemp(0)) # context provides storage 889 else: 890 self.new_op(LoadFunction(fn)) 891 892 self.new_op(FillDefaults((nparams, ndefaults))) 893 894 # Produce the body. 895 896 self.set_block(fn.body_block) 897 898 # For functions with star parameters, make a special list for the 899 # extra arguments and re-map the parameter. 900 901 if fn.has_star: 902 self.new_op(CopyExtra(nparams)) 903 904 # Ensure that the star parameter has a slot in the frame. 905 906 self.new_op(CheckExtra(nparams)) 907 self.new_op(StoreTemp(nparams)) 908 909 # Extend the frame for local usage. 910 911 extend = ExtendFrame() 912 self.new_op(extend) 913 914 # Perform tuple assignment for any tuple parameters. 915 916 self._visitFunctionTupleParameters(fn, node) 917 918 # Add any attribute usage guards. 919 920 self._generateGuards(node) 921 922 # Visit the actual code. 923 924 self.dispatch(node.code) 925 926 # Add a return statement where one is not already produced. 927 928 if not isinstance(self.last_op(), Return): 929 930 # Return None for normal functions without explicit return 931 # statements. 932 933 if not fn.is_lambda(): 934 self.dispatch(compiler.ast.Name("None")) 935 936 self.new_op(LoadValueIntoResult()) 937 self.new_op(Return()) 938 939 # Make sure that enough frame space is reserved from the start. 940 941 self.set_frame_usage(node, extend) 942 943 def _visitFunctionTupleParameters(self, fn, node, parameters=None): 944 945 """ 946 Visit the tuple parameters for function 'fn', obtaining the appropriate 947 elements from each supplied argument and assigning them to the specified 948 names for each parameter. 949 """ 950 951 if parameters is not None: 952 self._generateAttr(node, "__getitem__", self.attribute_load_instructions) 953 temp_getitem = self.optimiser.optimise_temp_storage() 954 955 for i, parameter in parameters or fn.tuple_parameters(): 956 957 # Either load the parameter from the frame. 958 959 if parameters is None: 960 self.new_op(LoadName(Attr(i, None, None))) 961 962 # Or load a value from the current collection. 963 964 else: 965 self._startCallFunc() 966 self.new_op(temp_getitem) 967 temp_target, target, temp_context = self._generateCallFunc([compiler.ast.Const(i)], node) 968 self._doCallFunc(temp_target, target) 969 self._endCallFunc() 970 971 # Where a tuple is the target, attempt to descend into the value 972 # obtained. 973 974 if isinstance(parameter, list): 975 self._visitFunctionTupleParameters(fn, node, parameter) 976 977 # Store the item in the namespace entry for the given name. 978 979 else: 980 self.record_value() 981 self.new_op(StoreName(fn[parameter])) 982 self.set_source() 983 self.discard_value() 984 985 if parameters is not None: 986 self.discard_temp(temp_getitem) 987 988 def _generateFunctionDefaults(self, function): 989 990 """ 991 Generate the default initialisation code for 'function', returning 992 a temporary storage reference if a dynamic object was created for the 993 function. 994 """ 995 996 attr_to_default = zip(function.default_attrs, function.defaults) 997 if not attr_to_default: 998 return None 999 1000 # Where non-constant defaults are involved, construct a dynamic object 1001 # to hold the defaults. 1002 1003 dynamic = function.is_dynamic() 1004 1005 if dynamic: 1006 self.make_instance(self.get_builtin_class("function", function), len(attr_to_default)) 1007 temp = self.get_temp() 1008 1009 for attr, default in attr_to_default: 1010 self.dispatch(default) 1011 1012 self.record_value() 1013 if dynamic: 1014 self.new_op(temp) 1015 self.new_op(StoreAttr(attr)) 1016 else: 1017 self.new_op(StoreAddress(attr)) 1018 self.set_source() 1019 self.discard_value() 1020 1021 if dynamic: 1022 return temp 1023 else: 1024 return None 1025 1026 def _visitName(self, node, classes): 1027 1028 """ 1029 Visit the name-related 'node', generating instructions based on the 1030 given 'classes'. 1031 """ 1032 1033 name = node.name 1034 1035 # Get the expected scope of the name. 1036 1037 scope = getattr(node, "_scope", None) or self.get_scope(name) 1038 self._generateName(name, scope, classes, node) 1039 1040 def _generateName(self, name, scope, classes, node): 1041 1042 """ 1043 Generate code for the access to 'name' in 'scope' using the given 1044 'classes', and using the given 'node' as the source of the access. 1045 """ 1046 1047 NameInstruction, AddressInstruction, AddressContextInstruction = classes 1048 1049 # Handle names referring to constants. 1050 1051 if scope == "constant": 1052 const = self.importer.get_predefined_constant(name) 1053 self.new_op(LoadConst(const)) 1054 1055 # Handle all other names. 1056 1057 elif scope == "local": 1058 unit = self.unit 1059 if isinstance(unit, Function): 1060 self.new_op(NameInstruction(unit.all_locals()[name])) 1061 elif isinstance(unit, Class): 1062 if AddressContextInstruction is not None: 1063 self.new_op(LoadConst(unit)) 1064 self.new_op(AddressContextInstruction(unit.all_class_attributes()[name])) 1065 else: 1066 self.new_op(AddressInstruction(unit.all_class_attributes()[name])) 1067 elif isinstance(unit, Module): 1068 self.new_op(AddressInstruction(unit.module_attributes()[name])) 1069 else: 1070 raise TranslateError("Program unit has no local %r." % name) 1071 1072 elif scope == "global": 1073 globals = self.module.module_attributes() 1074 if globals.has_key(name): 1075 self.new_op(AddressInstruction(globals[name])) 1076 else: 1077 raise TranslateError("Module has no attribute %r." % name) 1078 1079 elif scope == "builtins": 1080 self.new_op(AddressInstruction(self.get_builtin(name, node))) 1081 1082 else: 1083 # NOTE: This may happen because a class attribute is optimised away. 1084 print "Program unit uses unknown name %r." % name 1085 1086 def _visitUnary(self, node): 1087 1088 """ 1089 Invoke the appropriate operator module function for the operation 1090 represented by 'node'. 1091 """ 1092 1093 temp_fn = self._getOperatorFunction(node) 1094 self._visitCall(node, temp_fn, (node.expr,)) 1095 self.discard_temp(temp_fn) 1096 1097 def _visitBinaryBit(self, node): 1098 1099 """ 1100 Need to impose binary rules over a sequence of nodes. The 1101 short-circuiting of the similar logical operators is not imposed by the 1102 bitwise operators. 1103 """ 1104 1105 temp_fn = self._getOperatorFunction(node) 1106 left = None 1107 1108 for right in node.nodes: 1109 if left is not None: 1110 self._visitCall(node, temp_fn, (left, right)) 1111 left = right 1112 1113 self.discard_temp(temp_fn) 1114 1115 def _visitBinary(self, node): 1116 1117 """ 1118 Invoke the appropriate operator module function for the operation 1119 represented by 'node'. 1120 """ 1121 1122 temp_fn = self._getOperatorFunction(node) 1123 self._visitCall(node, temp_fn, (node.left, node.right)) 1124 self.discard_temp(temp_fn) 1125 1126 def _visitCall(self, node, temp_fn, args): 1127 1128 """ 1129 Invoke the appropriate operator module function for the operation 1130 represented by 'node', given a 'temp_fn' reference to a function, along 1131 with the 'args' (the operand nodes). 1132 """ 1133 1134 # Evaluate and store the operands in temporary storage. 1135 1136 temp_list = [] 1137 1138 for arg in args: 1139 self.dispatch(arg) 1140 temp_list.append(self.optimiser.optimise_temp_storage()) 1141 1142 self._generateInvocation(temp_fn, temp_list) 1143 1144 # Compilation duties... 1145 1146 for temp in temp_list: 1147 self.discard_temp(temp) 1148 1149 def _generateInvocation(self, temp_fn, temp_list): 1150 1151 """ 1152 Invoke the function 'temp_fn' using the operands from 'temp_list' as 1153 arguments. 1154 """ 1155 1156 self._startCallFunc() 1157 1158 for i, temp in enumerate(temp_list): 1159 self.new_op(temp) 1160 self.new_op(StoreFrame(i)) 1161 1162 self._endCallFuncArgs(len(temp_list)) 1163 self._doCallFunc(temp_fn) 1164 self._endCallFunc(temp_fn) 1165 1166 def _getOperatorFunction(self, node, operator_name=None): 1167 1168 "Return an operator function reference for the given 'node'." 1169 1170 return self._generateOperatorFunction(operator_name or node.__class__.__name__) 1171 1172 def _getOperatorAugAssignFunction(self, node): 1173 1174 """ 1175 Return an operator augmented assignment function reference for the given 1176 'node'. 1177 """ 1178 1179 return self._generateOperatorFunction(node.op) 1180 1181 def _generateOperatorFunction(self, opname): 1182 1183 "Return an operator function reference for the given 'opname'." 1184 1185 operator_fn = operator_functions[opname] 1186 1187 # Get the operator module. 1188 1189 operator_module = self.importer.get_module("operator") 1190 1191 # Get the appropriate function from the operator module. 1192 1193 self.new_op(LoadAddress(operator_module[operator_fn])) 1194 return self.optimiser.optimise_temp_storage() 1195 1196 def _handleAttributeError(self, node, temp_method, handled_block): 1197 1198 """ 1199 Add exception handling to the method acquisition instructions where the 1200 attribute access cannot be resolved at compile-time. 1201 """ 1202 1203 if not (self.optimiser.should_optimise_known_target() and self.optimiser.is_constant_input(temp_method)): 1204 self.load_builtin("AttributeError", node) 1205 self.new_op(CheckException()) 1206 self.new_op(JumpIfTrue(handled_block)) 1207 self.new_op(RaiseException()) 1208 1209 def _generateTuple(self, node): 1210 1211 "Make a tuple using the given program 'node'." 1212 1213 # Reserve space for the elements themselves. 1214 1215 self.make_instance(self.get_builtin_class("tuple", node), len(node.nodes)) 1216 temp = self.get_temp() 1217 1218 # Store using 0-based index values. 1219 1220 self._populateSequence(temp, node) 1221 1222 self.new_op(temp) 1223 self.discard_temp(temp) 1224 1225 def _generateList(self, node): 1226 1227 "Make a list using the given program 'node'." 1228 1229 # Make a fragment containing the list elements. 1230 1231 self.new_op(MakeFragment(len(node.nodes) + 1)) 1232 temp = self.get_temp() 1233 self._populateSequence(temp, node) 1234 self.new_op(temp) 1235 self.record_value() 1236 1237 # Reserve space for _elements (the fragment reference). 1238 1239 self.make_instance(self.get_builtin_class("list", node), 1) 1240 list_temp = self.get_temp() 1241 self.new_op(list_temp) 1242 self.new_op(StoreAttr(Attr(0, None, None))) # _elements is at position 0 1243 self.set_source() 1244 self.discard_value() 1245 1246 self.new_op(list_temp) 1247 self.discard_temp(temp) 1248 self.discard_temp(list_temp) 1249 1250 def _populateSequence(self, temp, node, offset=0): 1251 1252 """ 1253 Populate a sequence using the given 'temp' reference and program 'node'. 1254 """ 1255 1256 for i, n in enumerate(node.nodes): 1257 self.dispatch(n) 1258 self.record_value() 1259 self._storeInSequence(temp, i, offset) 1260 self.discard_value() 1261 1262 def _storeInSequence(self, temp, i, offset=0): 1263 1264 """ 1265 Store the current active value in the fragment referenced by 'temp' at 1266 position 'i' with the given starting 'offset'. 1267 """ 1268 1269 self.new_op(temp) 1270 self.new_op(StoreAttr(Attr(i + offset, None, None))) 1271 self.set_source() 1272 1273 def _generateTestBoolean(self, node, temp): 1274 1275 """ 1276 Generate a test of the boolean status of the current value for the given 1277 program 'node'. 1278 """ 1279 1280 # Get method on temp. 1281 # NOTE: Using __bool__ instead of __nonzero__. 1282 1283 self._generateAttr(node, "__bool__", self.attribute_load_instructions) 1284 temp_method = self.optimiser.optimise_temp_storage() 1285 1286 self._generateInvocation(temp_method, (temp,)) 1287 1288 self.discard_temp(temp_method) 1289 1290 # Convert result to boolean (a StoreBoolean operation). 1291 1292 self.new_op(TestIdentityAddress(self.importer.get_predefined_constant("True"))) 1293 1294 def _generateLoadBoolean(self, node): 1295 1296 """ 1297 Generate instructions to load the appropriate value given the current 1298 boolean status. 1299 """ 1300 1301 true_block = self.new_block() 1302 end_block = self.new_block() 1303 1304 self.new_op(JumpIfTrue(true_block)) 1305 self.new_op(LoadConst(self.importer.get_predefined_constant("False"))) 1306 self.new_op(Jump(end_block)) 1307 1308 self.set_block(true_block) 1309 self.new_op(LoadConst(self.importer.get_predefined_constant("True"))) 1310 1311 self.set_block(end_block) 1312 1313 def _visitPrint(self, node, function_name): 1314 self._startCallFunc() 1315 self.load_builtin(function_name, node) 1316 1317 args = [node.dest or compiler.ast.Name("None")] + node.nodes 1318 1319 temp_target, target, temp_context = self._generateCallFunc(args, node) 1320 self._doCallFunc(temp_target, target) 1321 self._endCallFunc(temp_target, temp_context) 1322 1323 # vim: tabstop=4 expandtab shiftwidth=4