Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(422)

Side by Side Diff: third_party/WebKit/Source/bindings/scripts/v8_interface.py

Issue 2712913002: [WebAgentsAPI]: Split overload set functions into their own module. (Closed)
Patch Set: Feedback addressed. Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/WebKit/Source/bindings/scripts/overload_set_algorithm.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 15 matching lines...) Expand all
26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 29
30 # pylint: disable=relative-import 30 # pylint: disable=relative-import
31 31
32 """Generate template values for an interface. 32 """Generate template values for an interface.
33 33
34 Design doc: http://www.chromium.org/developers/design-documents/idl-compiler 34 Design doc: http://www.chromium.org/developers/design-documents/idl-compiler
35 """ 35 """
36 36 from operator import or_
37 from collections import defaultdict
38 import itertools
39 from operator import itemgetter, or_
40 37
41 from idl_definitions import IdlOperation, IdlArgument 38 from idl_definitions import IdlOperation, IdlArgument
42 from idl_types import IdlType, inherits_interface 39 from idl_types import IdlType, inherits_interface
40 from overload_set_algorithm import effective_overload_set_by_length
41 from overload_set_algorithm import method_overloads_by_name
42
43 import v8_attributes 43 import v8_attributes
44 from v8_globals import includes 44 from v8_globals import includes
45 import v8_methods 45 import v8_methods
46 import v8_types 46 import v8_types
47 import v8_utilities 47 import v8_utilities
48 from v8_utilities import (cpp_name_or_partial, cpp_name, has_extended_attribute_ value, 48 from v8_utilities import (cpp_name_or_partial, cpp_name, has_extended_attribute_ value,
49 runtime_enabled_feature_name, is_legacy_interface_type _checking) 49 runtime_enabled_feature_name, is_legacy_interface_type _checking)
50 50
51 51
52 INTERFACE_H_INCLUDES = frozenset([ 52 INTERFACE_H_INCLUDES = frozenset([
(...skipping 685 matching lines...) Expand 10 before | Expand all | Expand 10 after
738 """ 738 """
739 # Add overload information only to overloaded methods, so template code can 739 # Add overload information only to overloaded methods, so template code can
740 # easily verify if a function is overloaded 740 # easily verify if a function is overloaded
741 for name, overloads in method_overloads_by_name(methods): 741 for name, overloads in method_overloads_by_name(methods):
742 # Resolution function is generated after last overloaded function; 742 # Resolution function is generated after last overloaded function;
743 # package necessary information into |method.overloads| for that method. 743 # package necessary information into |method.overloads| for that method.
744 overloads[-1]['overloads'] = overloads_context(interface, overloads) 744 overloads[-1]['overloads'] = overloads_context(interface, overloads)
745 overloads[-1]['overloads']['name'] = name 745 overloads[-1]['overloads']['name'] = name
746 746
747 747
748 def method_overloads_by_name(methods):
749 """Returns generator of overloaded methods by name: [name, [method]]"""
750 # Filter to only methods that are actually overloaded
751 method_counts = Counter(method['name'] for method in methods)
752 overloaded_method_names = set(name
753 for name, count in method_counts.iteritems()
754 if count > 1)
755 overloaded_methods = [method for method in methods
756 if method['name'] in overloaded_method_names]
757
758 # Group by name (generally will be defined together, but not necessarily)
759 return sort_and_groupby(overloaded_methods, itemgetter('name'))
760 748
761 749
762 def overloads_context(interface, overloads): 750 def overloads_context(interface, overloads):
763 """Returns |overloads| template values for a single name. 751 """Returns |overloads| template values for a single name.
764 752
765 Sets |method.overload_index| in place for |method| in |overloads| 753 Sets |method.overload_index| in place for |method| in |overloads|
766 and returns dict of overall overload template values. 754 and returns dict of overall overload template values.
767 """ 755 """
768 assert len(overloads) > 1 # only apply to overloaded names 756 assert len(overloads) > 1 # only apply to overloaded names
769 for index, method in enumerate(overloads, 1): 757 for index, method in enumerate(overloads, 1):
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
871 'valid_arities': (lengths 859 'valid_arities': (lengths
872 # Only need to report valid arities if there is a gap in the 860 # Only need to report valid arities if there is a gap in the
873 # sequence of possible lengths, otherwise invalid leng th means 861 # sequence of possible lengths, otherwise invalid leng th means
874 # "not enough arguments". 862 # "not enough arguments".
875 if lengths[-1] - lengths[0] != len(lengths) - 1 else N one), 863 if lengths[-1] - lengths[0] != len(lengths) - 1 else N one),
876 'visible': has_overload_visible, 864 'visible': has_overload_visible,
877 'has_partial_overloads': has_partial_overloads, 865 'has_partial_overloads': has_partial_overloads,
878 } 866 }
879 867
880 868
881 def effective_overload_set(F):
882 """Returns the effective overload set of an overloaded function.
883
884 An effective overload set is the set of overloaded functions + signatures
885 (type list of arguments, with optional and variadic arguments included or
886 not), and is used in the overload resolution algorithm.
887
888 For example, given input [f1(optional long x), f2(DOMString s)], the output
889 is informally [f1(), f1(long), f2(DOMString)], and formally
890 [(f1, [], []), (f1, [long], [optional]), (f2, [DOMString], [required])].
891
892 Currently the optionality list is a list of |is_optional| booleans (True
893 means optional, False means required); to support variadics this needs to
894 be tri-valued as required, optional, or variadic.
895
896 Formally:
897 An effective overload set represents the allowable invocations for a
898 particular operation, constructor (specified with [Constructor] or
899 [NamedConstructor]), legacy caller or callback function.
900
901 An additional argument N (argument count) is needed when overloading
902 variadics, but we don't use that currently.
903
904 Spec: http://heycam.github.io/webidl/#dfn-effective-overload-set
905
906 Formally the input and output lists are sets, but methods are stored
907 internally as dicts, which can't be stored in a set because they are not
908 hashable, so we use lists instead.
909
910 Arguments:
911 F: list of overloads for a given callable name.
912
913 Returns:
914 S: list of tuples of the form (callable, type list, optionality list).
915 """
916 # Code closely follows the algorithm in the spec, for clarity and
917 # correctness, and hence is not very Pythonic.
918
919 # 1. Initialize S to ∅.
920 # (We use a list because we can't use a set, as noted above.)
921 S = []
922
923 # 2. Let F be a set with elements as follows, according to the kind of
924 # effective overload set:
925 # (Passed as argument, nothing to do.)
926
927 # 3. & 4. (maxarg, m) are only needed for variadics, not used.
928
929 # 5. For each operation, extended attribute or callback function X in F:
930 for X in F: # X is the "callable", F is the overloads.
931 arguments = X['arguments']
932 # 1. Let n be the number of arguments X is declared to take.
933 n = len(arguments)
934 # 2. Let t0..n−1 be a list of types, where ti is the type of X’s
935 # argument at index i.
936 # (“type list”)
937 t = tuple(argument['idl_type_object'] for argument in arguments)
938 # 3. Let o0..n−1 be a list of optionality values, where oi is “variadic”
939 # if X’s argument at index i is a final, variadic argument, “optional”
940 # if the argument is optional, and “required” otherwise.
941 # (“optionality list”)
942 # (We’re just using a boolean for optional/variadic vs. required.)
943 o = tuple(argument['is_optional'] or argument['is_variadic']
944 for argument in arguments)
945 # 4. Add to S the tuple <X, t0..n−1, o0..n−1>.
946 S.append((X, t, o))
947 # 5. If X is declared to be variadic, then:
948 # (Not used, so not implemented.)
949 # 6. Initialize i to n−1.
950 i = n - 1
951 # 7. While i ≥ 0:
952 # Spec bug (fencepost error); should be “While i > 0:”
953 # https://www.w3.org/Bugs/Public/show_bug.cgi?id=25590
954 while i > 0:
955 # 1. If argument i of X is not optional, then break this loop.
956 if not o[i]:
957 break
958 # 2. Otherwise, add to S the tuple <X, t0..i−1, o0..i−1>.
959 S.append((X, t[:i], o[:i]))
960 # 3. Set i to i−1.
961 i = i - 1
962 # 8. If n > 0 and all arguments of X are optional, then add to S the
963 # tuple <X, (), ()> (where “()” represents the empty list).
964 if n > 0 and all(oi for oi in o):
965 S.append((X, [], []))
966 # 6. The effective overload set is S.
967 return S
968
969
970 def effective_overload_set_by_length(overloads):
971 def type_list_length(entry):
972 # Entries in the effective overload set are 3-tuples:
973 # (callable, type list, optionality list)
974 return len(entry[1])
975
976 effective_overloads = effective_overload_set(overloads)
977 return list(sort_and_groupby(effective_overloads, type_list_length))
978
979 869
980 def distinguishing_argument_index(entries): 870 def distinguishing_argument_index(entries):
981 """Returns the distinguishing argument index for a sequence of entries. 871 """Returns the distinguishing argument index for a sequence of entries.
982 872
983 Entries are elements of the effective overload set with the same number 873 Entries are elements of the effective overload set with the same number
984 of arguments (formally, same type list length), each a 3-tuple of the form 874 of arguments (formally, same type list length), each a 3-tuple of the form
985 (callable, type list, optionality list). 875 (callable, type list, optionality list).
986 876
987 Spec: http://heycam.github.io/webidl/#dfn-distinguishing-argument-index 877 Spec: http://heycam.github.io/webidl/#dfn-distinguishing-argument-index
988 878
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after
1249 if idl_type.is_numeric_type) 1139 if idl_type.is_numeric_type)
1250 yield 'true', method 1140 yield 'true', method
1251 except StopIteration: 1141 except StopIteration:
1252 pass 1142 pass
1253 1143
1254 1144
1255 ################################################################################ 1145 ################################################################################
1256 # Utility functions 1146 # Utility functions
1257 ################################################################################ 1147 ################################################################################
1258 1148
1259 def Counter(iterable):
1260 # Once using Python 2.7, using collections.Counter
1261 counter = defaultdict(lambda: 0)
1262 for item in iterable:
1263 counter[item] += 1
1264 return counter
1265
1266
1267 def common(dicts, f): 1149 def common(dicts, f):
1268 """Returns common result of f across an iterable of dicts, or None. 1150 """Returns common result of f across an iterable of dicts, or None.
1269 1151
1270 Call f for each dict and return its result if the same across all dicts. 1152 Call f for each dict and return its result if the same across all dicts.
1271 """ 1153 """
1272 values = (f(d) for d in dicts) 1154 values = (f(d) for d in dicts)
1273 first_value = next(values) 1155 first_value = next(values)
1274 if all(value == first_value for value in values): 1156 if all(value == first_value for value in values):
1275 return first_value 1157 return first_value
1276 return None 1158 return None
(...skipping 10 matching lines...) Expand all
1287 1169
1288 def common_value(dicts, key): 1170 def common_value(dicts, key):
1289 """Returns common value of a key across an iterable of dicts, or None. 1171 """Returns common value of a key across an iterable of dicts, or None.
1290 1172
1291 Auxiliary function for overloads, so can consolidate an extended attribute 1173 Auxiliary function for overloads, so can consolidate an extended attribute
1292 that appears with the same value on all items in an overload set. 1174 that appears with the same value on all items in an overload set.
1293 """ 1175 """
1294 return common(dicts, lambda d: d.get(key)) 1176 return common(dicts, lambda d: d.get(key))
1295 1177
1296 1178
1297 def sort_and_groupby(l, key=None):
1298 """Returns a generator of (key, list), sorting and grouping list by key."""
1299 l.sort(key=key)
1300 return ((k, list(g)) for k, g in itertools.groupby(l, key))
1301
1302
1303 ################################################################################ 1179 ################################################################################
1304 # Constructors 1180 # Constructors
1305 ################################################################################ 1181 ################################################################################
1306 1182
1307 # [Constructor] 1183 # [Constructor]
1308 def constructor_context(interface, constructor): 1184 def constructor_context(interface, constructor):
1309 # [RaisesException=Constructor] 1185 # [RaisesException=Constructor]
1310 is_constructor_raises_exception = \ 1186 is_constructor_raises_exception = \
1311 interface.extended_attributes.get('RaisesException') == 'Constructor' 1187 interface.extended_attributes.get('RaisesException') == 'Constructor'
1312 1188
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
1484 extended_attributes = deleter.extended_attributes 1360 extended_attributes = deleter.extended_attributes
1485 is_call_with_script_state = v8_utilities.has_extended_attribute_value(delete r, 'CallWith', 'ScriptState') 1361 is_call_with_script_state = v8_utilities.has_extended_attribute_value(delete r, 'CallWith', 'ScriptState')
1486 is_ce_reactions = 'CEReactions' in extended_attributes 1362 is_ce_reactions = 'CEReactions' in extended_attributes
1487 return { 1363 return {
1488 'is_call_with_script_state': is_call_with_script_state, 1364 'is_call_with_script_state': is_call_with_script_state,
1489 'is_ce_reactions': is_ce_reactions, 1365 'is_ce_reactions': is_ce_reactions,
1490 'is_custom': 'Custom' in extended_attributes, 1366 'is_custom': 'Custom' in extended_attributes,
1491 'is_raises_exception': 'RaisesException' in extended_attributes, 1367 'is_raises_exception': 'RaisesException' in extended_attributes,
1492 'name': cpp_name(deleter), 1368 'name': cpp_name(deleter),
1493 } 1369 }
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/bindings/scripts/overload_set_algorithm.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698