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