OLD | NEW |
---|---|
1 # Copyright (C) 2013 Google Inc. All rights reserved. | 1 # Copyright (C) 2013 Google Inc. All rights reserved. |
2 # coding=utf-8 | 2 # coding=utf-8 |
3 # | 3 # |
4 # Redistribution and use in source and binary forms, with or without | 4 # Redistribution and use in source and binary forms, with or without |
5 # modification, are permitted provided that the following conditions are | 5 # modification, are permitted provided that the following conditions are |
6 # met: | 6 # met: |
7 # | 7 # |
8 # * Redistributions of source code must retain the above copyright | 8 # * Redistributions of source code must retain the above copyright |
9 # notice, this list of conditions and the following disclaimer. | 9 # notice, this list of conditions and the following disclaimer. |
10 # * Redistributions in binary form must reproduce the above | 10 # * Redistributions in binary form must reproduce the above |
(...skipping 664 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
675 def resolution_tests_methods(effective_overloads): | 675 def resolution_tests_methods(effective_overloads): |
676 """Yields resolution test and associated method, in resolution order, for ef fective overloads of a given length. | 676 """Yields resolution test and associated method, in resolution order, for ef fective overloads of a given length. |
677 | 677 |
678 This is the heart of the resolution algorithm. | 678 This is the heart of the resolution algorithm. |
679 http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm | 679 http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm |
680 | 680 |
681 Note that a given method can be listed multiple times, with different tests! | 681 Note that a given method can be listed multiple times, with different tests! |
682 This is to handle implicit type conversion. | 682 This is to handle implicit type conversion. |
683 | 683 |
684 Returns: | 684 Returns: |
685 [(test, method)] | 685 [(test, method)] |
bashi
2014/10/15 00:02:12
Could you update this comment?
| |
686 """ | 686 """ |
687 methods = [effective_overload[0] | 687 methods = [effective_overload[0] |
688 for effective_overload in effective_overloads] | 688 for effective_overload in effective_overloads] |
689 if len(methods) == 1: | 689 if len(methods) == 1: |
690 # If only one method with a given length, no test needed | 690 # If only one method with a given length, no test needed |
691 yield 'true', methods[0] | 691 yield 'true', methods[0], -1 |
692 return | 692 return |
693 | 693 |
694 # 6. If there is more than one entry in S, then set d to be the | 694 # 6. If there is more than one entry in S, then set d to be the |
695 # distinguishing argument index for the entries of S. | 695 # distinguishing argument index for the entries of S. |
696 index = distinguishing_argument_index(effective_overloads) | 696 index = distinguishing_argument_index(effective_overloads) |
697 # (7-9 are for handling |undefined| values for optional arguments before | 697 # (7-9 are for handling |undefined| values for optional arguments before |
698 # the distinguishing argument (as “missing”), so you can specify only some | 698 # the distinguishing argument (as “missing”), so you can specify only some |
699 # optional arguments. We don’t support this, so we skip these steps.) | 699 # optional arguments. We don’t support this, so we skip these steps.) |
700 # 10. If i = d, then: | 700 # 10. If i = d, then: |
701 # (d is the distinguishing argument index) | 701 # (d is the distinguishing argument index) |
702 # 1. Let V be argi. | 702 # 1. Let V be argi. |
703 # Note: This is the argument that will be used to resolve which | 703 # Note: This is the argument that will be used to resolve which |
704 # overload is selected. | 704 # overload is selected. |
705 cpp_value = 'info[%s]' % index | 705 cpp_value = 'info[%s]' % index |
706 | 706 |
707 # Extract argument and IDL type to simplify accessing these in each loop. | 707 # Extract argument and IDL type to simplify accessing these in each loop. |
708 arguments = [method['arguments'][index] for method in methods] | 708 arguments = [method['arguments'][index] for method in methods] |
709 arguments_methods = zip(arguments, methods) | 709 arguments_methods = zip(arguments, methods) |
710 idl_types = [argument['idl_type_object'] for argument in arguments] | 710 idl_types = [argument['idl_type_object'] for argument in arguments] |
711 idl_types_methods = zip(idl_types, methods) | 711 idl_types_methods = zip(idl_types, methods) |
712 | 712 |
713 for argument in arguments: | |
714 argument['is_distinguishing_argument'] = True | |
715 | |
713 # We can’t do a single loop through all methods or simply sort them, because | 716 # We can’t do a single loop through all methods or simply sort them, because |
714 # a method may be listed in multiple steps of the resolution algorithm, and | 717 # a method may be listed in multiple steps of the resolution algorithm, and |
715 # which test to apply differs depending on the step. | 718 # which test to apply differs depending on the step. |
716 # | 719 # |
717 # Instead, we need to go through all methods at each step, either finding | 720 # Instead, we need to go through all methods at each step, either finding |
718 # first match (if only one test is allowed) or filtering to matches (if | 721 # first match (if only one test is allowed) or filtering to matches (if |
719 # multiple tests are allowed), and generating an appropriate tests. | 722 # multiple tests are allowed), and generating an appropriate tests. |
720 | 723 |
721 # 2. If V is undefined, and there is an entry in S whose list of | 724 # 2. If V is undefined, and there is an entry in S whose list of |
722 # optionality values has “optional” at index i, then remove from S all | 725 # optionality values has “optional” at index i, then remove from S all |
723 # other entries. | 726 # other entries. |
724 try: | 727 try: |
725 method = next(method for argument, method in arguments_methods | 728 method = next(method for argument, method in arguments_methods |
726 if argument['is_optional']) | 729 if argument['is_optional']) |
727 test = '%s->IsUndefined()' % cpp_value | 730 test = '%s->IsUndefined()' % cpp_value |
728 yield test, method | 731 yield test, method, -1 |
729 except StopIteration: | 732 except StopIteration: |
730 pass | 733 pass |
731 | 734 |
732 # 3. Otherwise: if V is null or undefined, and there is an entry in S that | 735 # 3. Otherwise: if V is null or undefined, and there is an entry in S that |
733 # has one of the following types at position i of its type list, | 736 # has one of the following types at position i of its type list, |
734 # • a nullable type | 737 # • a nullable type |
735 try: | 738 try: |
736 method = next(method for idl_type, method in idl_types_methods | 739 method = next(method for idl_type, method in idl_types_methods |
737 if idl_type.is_nullable) | 740 if idl_type.is_nullable) |
738 test = 'isUndefinedOrNull(%s)' % cpp_value | 741 test = 'isUndefinedOrNull(%s)' % cpp_value |
739 yield test, method | 742 yield test, method, -1 |
740 except StopIteration: | 743 except StopIteration: |
741 pass | 744 pass |
742 | 745 |
743 # 4. Otherwise: if V is a platform object – but not a platform array | 746 # 4. Otherwise: if V is a platform object – but not a platform array |
744 # object – and there is an entry in S that has one of the following | 747 # object – and there is an entry in S that has one of the following |
745 # types at position i of its type list, | 748 # types at position i of its type list, |
746 # • an interface type that V implements | 749 # • an interface type that V implements |
747 # (Unlike most of these tests, this can return multiple methods, since we | 750 # (Unlike most of these tests, this can return multiple methods, since we |
748 # test if it implements an interface. Thus we need a for loop, not a next.) | 751 # test if it implements an interface. Thus we need a for loop, not a next.) |
749 # (We distinguish wrapper types from built-in interface types.) | 752 # (We distinguish wrapper types from built-in interface types.) |
750 for idl_type, method in ((idl_type, method) | 753 for idl_type, method in ((idl_type, method) |
751 for idl_type, method in idl_types_methods | 754 for idl_type, method in idl_types_methods |
752 if idl_type.is_wrapper_type): | 755 if idl_type.is_wrapper_type): |
753 test = 'V8{idl_type}::hasInstance({cpp_value}, info.GetIsolate())'.forma t(idl_type=idl_type.base_type, cpp_value=cpp_value) | 756 test = 'V8{idl_type}::hasInstance({cpp_value}, info.GetIsolate())'.forma t(idl_type=idl_type.base_type, cpp_value=cpp_value) |
754 yield test, method | 757 yield test, method, index |
755 | 758 |
756 # 8. Otherwise: if V is any kind of object except for a native Date object, | 759 # 8. Otherwise: if V is any kind of object except for a native Date object, |
757 # a native RegExp object, and there is an entry in S that has one of the | 760 # a native RegExp object, and there is an entry in S that has one of the |
758 # following types at position i of its type list, | 761 # following types at position i of its type list, |
759 # • an array type | 762 # • an array type |
760 # • a sequence type | 763 # • a sequence type |
761 # ... | 764 # ... |
762 # • a dictionary | 765 # • a dictionary |
763 # | 766 # |
764 # FIXME: | 767 # FIXME: |
765 # We don't strictly follow the algorithm here. The algorithm says "remove | 768 # We don't strictly follow the algorithm here. The algorithm says "remove |
766 # all other entries" if there is "one entry" matching, but we yield all | 769 # all other entries" if there is "one entry" matching, but we yield all |
767 # entries to support following constructors: | 770 # entries to support following constructors: |
768 # [constructor(sequence<DOMString> arg), constructor(Dictionary arg)] | 771 # [constructor(sequence<DOMString> arg), constructor(Dictionary arg)] |
769 # interface I { ... } | 772 # interface I { ... } |
770 # (Need to check array types before objects because an array is an object) | 773 # (Need to check array types before objects because an array is an object) |
771 for idl_type, method in idl_types_methods: | 774 for idl_type, method in idl_types_methods: |
772 if idl_type.native_array_element_type: | 775 if idl_type.native_array_element_type: |
773 # (We test for Array instead of generic Object to type-check.) | 776 # (We test for Array instead of generic Object to type-check.) |
774 # FIXME: test for Object during resolution, then have type check for | 777 # FIXME: test for Object during resolution, then have type check for |
775 # Array in overloaded method: http://crbug.com/262383 | 778 # Array in overloaded method: http://crbug.com/262383 |
776 yield '%s->IsArray()' % cpp_value, method | 779 yield '%s->IsArray()' % cpp_value, method, index |
777 for idl_type, method in idl_types_methods: | 780 for idl_type, method in idl_types_methods: |
778 if idl_type.is_dictionary or idl_type.name == 'Dictionary': | 781 if idl_type.is_dictionary or idl_type.name == 'Dictionary': |
779 # FIXME: should be '{1}->IsObject() && !{1}->IsDate() && !{1}->IsReg Exp()'.format(cpp_value) | 782 # FIXME: should be '{1}->IsObject() && !{1}->IsDate() && !{1}->IsReg Exp()'.format(cpp_value) |
780 # FIXME: the IsDate and IsRegExp checks can be skipped if we've | 783 # FIXME: the IsDate and IsRegExp checks can be skipped if we've |
781 # already generated tests for them. | 784 # already generated tests for them. |
782 yield '%s->IsObject()' % cpp_value, method | 785 yield '%s->IsObject()' % cpp_value, method, index |
783 | 786 |
784 # (Check for exact type matches before performing automatic type conversion; | 787 # (Check for exact type matches before performing automatic type conversion; |
785 # only needed if distinguishing between primitive types.) | 788 # only needed if distinguishing between primitive types.) |
786 if len([idl_type.is_primitive_type for idl_type in idl_types]) > 1: | 789 if len([idl_type.is_primitive_type for idl_type in idl_types]) > 1: |
787 # (Only needed if match in step 11, otherwise redundant.) | 790 # (Only needed if match in step 11, otherwise redundant.) |
788 if any(idl_type.is_string_type or idl_type.is_enum | 791 if any(idl_type.is_string_type or idl_type.is_enum |
789 for idl_type in idl_types): | 792 for idl_type in idl_types): |
790 # 10. Otherwise: if V is a Number value, and there is an entry in S | 793 # 10. Otherwise: if V is a Number value, and there is an entry in S |
791 # that has one of the following types at position i of its type | 794 # that has one of the following types at position i of its type |
792 # list, | 795 # list, |
793 # • a numeric type | 796 # • a numeric type |
794 try: | 797 try: |
795 method = next(method for idl_type, method in idl_types_methods | 798 method = next(method for idl_type, method in idl_types_methods |
796 if idl_type.is_numeric_type) | 799 if idl_type.is_numeric_type) |
797 test = '%s->IsNumber()' % cpp_value | 800 test = '%s->IsNumber()' % cpp_value |
798 yield test, method | 801 yield test, method, index |
799 except StopIteration: | 802 except StopIteration: |
800 pass | 803 pass |
801 | 804 |
802 # (Perform automatic type conversion, in order. If any of these match, | 805 # (Perform automatic type conversion, in order. If any of these match, |
803 # that’s the end, and no other tests are needed.) To keep this code simple, | 806 # that’s the end, and no other tests are needed.) To keep this code simple, |
804 # we rely on the C++ compiler's dead code elimination to deal with the | 807 # we rely on the C++ compiler's dead code elimination to deal with the |
805 # redundancy if both cases below trigger. | 808 # redundancy if both cases below trigger. |
806 | 809 |
807 # 11. Otherwise: if there is an entry in S that has one of the following | 810 # 11. Otherwise: if there is an entry in S that has one of the following |
808 # types at position i of its type list, | 811 # types at position i of its type list, |
809 # • DOMString | 812 # • DOMString |
810 # • ByteString | 813 # • ByteString |
811 # • ScalarValueString [a DOMString typedef, per definition.] | 814 # • ScalarValueString [a DOMString typedef, per definition.] |
812 # • an enumeration type | 815 # • an enumeration type |
813 try: | 816 try: |
814 method = next(method for idl_type, method in idl_types_methods | 817 method = next(method for idl_type, method in idl_types_methods |
815 if idl_type.is_string_type or idl_type.is_enum) | 818 if idl_type.is_string_type or idl_type.is_enum) |
816 yield 'true', method | 819 yield 'true', method, -1 |
817 except StopIteration: | 820 except StopIteration: |
818 pass | 821 pass |
819 | 822 |
820 # 12. Otherwise: if there is an entry in S that has one of the following | 823 # 12. Otherwise: if there is an entry in S that has one of the following |
821 # types at position i of its type list, | 824 # types at position i of its type list, |
822 # • a numeric type | 825 # • a numeric type |
823 try: | 826 try: |
824 method = next(method for idl_type, method in idl_types_methods | 827 method = next(method for idl_type, method in idl_types_methods |
825 if idl_type.is_numeric_type) | 828 if idl_type.is_numeric_type) |
826 yield 'true', method | 829 yield 'true', method, -1 |
827 except StopIteration: | 830 except StopIteration: |
828 pass | 831 pass |
829 | 832 |
830 | 833 |
831 ################################################################################ | 834 ################################################################################ |
832 # Utility functions | 835 # Utility functions |
833 ################################################################################ | 836 ################################################################################ |
834 | 837 |
835 def Counter(iterable): | 838 def Counter(iterable): |
836 # Once using Python 2.7, using collections.Counter | 839 # Once using Python 2.7, using collections.Counter |
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1133 deleter = next( | 1136 deleter = next( |
1134 method | 1137 method |
1135 for method in interface.operations | 1138 for method in interface.operations |
1136 if ('deleter' in method.specials and | 1139 if ('deleter' in method.specials and |
1137 len(method.arguments) == 1 and | 1140 len(method.arguments) == 1 and |
1138 str(method.arguments[0].idl_type) == 'DOMString')) | 1141 str(method.arguments[0].idl_type) == 'DOMString')) |
1139 except StopIteration: | 1142 except StopIteration: |
1140 return None | 1143 return None |
1141 | 1144 |
1142 return property_deleter(deleter) | 1145 return property_deleter(deleter) |
OLD | NEW |