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

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

Issue 2731683002: [WebAgentsAPI]: Introduce OverloadSetAdapter. (Closed)
Patch Set: 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 | « no previous file | third_party/WebKit/Source/bindings/scripts/overload_set_algorithm_test.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright 2017 The Chromium Authors. All rights reserved. 1 # Copyright 2017 The Chromium Authors. All rights reserved.
2 # coding=utf-8 2 # coding=utf-8
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 from collections import Counter 6 from collections import Counter
7 import itertools 7 import itertools
8 from operator import itemgetter 8 from operator import itemgetter
9 9
10 10
11 def sort_and_groupby(list_to_sort, key=None): 11 def sort_and_groupby(list_to_sort, key=None):
12 """Returns a generator of (key, list), sorting and grouping list by key.""" 12 """Returns a generator of (key, list), sorting and grouping list by key."""
13 list_to_sort.sort(key=key) 13 list_to_sort.sort(key=key)
14 return ((k, list(g)) for k, g in itertools.groupby(list_to_sort, key)) 14 return ((k, list(g)) for k, g in itertools.groupby(list_to_sort, key))
15 15
16 16
17 def effective_overload_set(F): # pylint: disable=invalid-name 17 class OverloadSetAdapter(object):
18 """Base class for the second effective_overload_set argument. Python is
19 a type-lax language, so this is mostly documentation of the expected
20 interface."""
21
22 def arguments(self, operation):
23 """Given an operation, return the list of its arguments."""
24 raise NotImplementedError
25
26 def type(self, argument):
27 """Given an argument, return its type."""
28 raise NotImplementedError
29
30 def is_optional(self, argument):
31 """Given an argument, return whether it is optional."""
32 raise NotImplementedError
33
34 def is_variadic(self, argument):
35 """"Given an argument, return whether it is variadic."""
36 raise NotImplementedError
37
38
39 class MethodContextAdapter(OverloadSetAdapter):
40 def arguments(self, operation):
41 return operation['arguments']
42
43 def type(self, argument):
44 return argument['idl_type_object']
45
46 def is_optional(self, argument):
47 return argument['is_optional']
48
49 def is_variadic(self, argument):
50 return argument['is_variadic']
51
52
53 def effective_overload_set(F, adapter): # pylint: disable=invalid-name
18 """Returns the effective overload set of an overloaded function. 54 """Returns the effective overload set of an overloaded function.
19 55
20 An effective overload set is the set of overloaded functions + signatures 56 An effective overload set is the set of overloaded functions + signatures
21 (type list of arguments, with optional and variadic arguments included or 57 (type list of arguments, with optional and variadic arguments included or
22 not), and is used in the overload resolution algorithm. 58 not), and is used in the overload resolution algorithm.
23 59
24 For example, given input [f1(optional long x), f2(DOMString s)], the output 60 For example, given input [f1(optional long x), f2(DOMString s)], the output
25 is informally [f1(), f1(long), f2(DOMString)], and formally 61 is informally [f1(), f1(long), f2(DOMString)], and formally
26 [(f1, [], []), (f1, [long], [optional]), (f2, [DOMString], [required])]. 62 [(f1, [], []), (f1, [long], [optional]), (f2, [DOMString], [required])].
27 63
(...skipping 10 matching lines...) Expand all
38 variadics, but we don't use that currently. 74 variadics, but we don't use that currently.
39 75
40 Spec: http://heycam.github.io/webidl/#dfn-effective-overload-set 76 Spec: http://heycam.github.io/webidl/#dfn-effective-overload-set
41 77
42 Formally the input and output lists are sets, but methods are stored 78 Formally the input and output lists are sets, but methods are stored
43 internally as dicts, which can't be stored in a set because they are not 79 internally as dicts, which can't be stored in a set because they are not
44 hashable, so we use lists instead. 80 hashable, so we use lists instead.
45 81
46 Arguments: 82 Arguments:
47 F: list of overloads for a given callable name. 83 F: list of overloads for a given callable name.
84 value_reader: an OverloadSetValueReader instance.
48 85
49 Returns: 86 Returns:
50 S: list of tuples of the form (callable, type list, optionality list). 87 S: list of tuples of the form (callable, type list, optionality list).
51 """ 88 """
52 # Code closely follows the algorithm in the spec, for clarity and 89 # Code closely follows the algorithm in the spec, for clarity and
53 # correctness, and hence is not very Pythonic. 90 # correctness, and hence is not very Pythonic.
54 91
55 # 1. Initialize S to ∅. 92 # 1. Initialize S to ∅.
56 # (We use a list because we can't use a set, as noted above.) 93 # (We use a list because we can't use a set, as noted above.)
57 S = [] # pylint: disable=invalid-name 94 S = [] # pylint: disable=invalid-name
58 95
59 # 2. Let F be a set with elements as follows, according to the kind of 96 # 2. Let F be a set with elements as follows, according to the kind of
60 # effective overload set: 97 # effective overload set:
61 # (Passed as argument, nothing to do.) 98 # (Passed as argument, nothing to do.)
62 99
63 # 3. & 4. (maxarg, m) are only needed for variadics, not used. 100 # 3. & 4. (maxarg, m) are only needed for variadics, not used.
64 101
65 # 5. For each operation, extended attribute or callback function X in F: 102 # 5. For each operation, extended attribute or callback function X in F:
66 for X in F: # X is the "callable". pylint: disable=invalid-name 103 for X in F: # X is the "callable". pylint: disable=invalid-name
67 arguments = X['arguments'] # pylint: disable=invalid-name 104 arguments = adapter.arguments(X) # pylint: disable=invalid-name
68 # 1. Let n be the number of arguments X is declared to take. 105 # 1. Let n be the number of arguments X is declared to take.
69 n = len(arguments) # pylint: disable=invalid-name 106 n = len(arguments) # pylint: disable=invalid-name
70 # 2. Let t0..n−1 be a list of types, where ti is the type of X’s 107 # 2. Let t0..n−1 be a list of types, where ti is the type of X’s
71 # argument at index i. 108 # argument at index i.
72 # (“type list”) 109 # (“type list”)
73 t = tuple(argument['idl_type_object'] # pylint: disable=invalid-name 110 t = tuple(adapter.type(argument) # pylint: disable=invalid-name
74 for argument in arguments) 111 for argument in arguments)
75 # 3. Let o0..n−1 be a list of optionality values, where oi is “variadic” 112 # 3. Let o0..n−1 be a list of optionality values, where oi is “variadic”
76 # if X’s argument at index i is a final, variadic argument, “optional” 113 # if X’s argument at index i is a final, variadic argument, “optional”
77 # if the argument is optional, and “required” otherwise. 114 # if the argument is optional, and “required” otherwise.
78 # (“optionality list”) 115 # (“optionality list”)
79 # (We’re just using a boolean for optional/variadic vs. required.) 116 # (We’re just using a boolean for optional/variadic vs. required.)
80 o = tuple(argument['is_optional'] # pylint: disable=invalid-name 117 o = tuple(adapter.is_optional(argument) # pylint: disable=invalid-name
81 or argument['is_variadic'] for argument in arguments) 118 or adapter.is_variadic(argument)
119 for argument in arguments)
82 # 4. Add to S the tuple <X, t0..n−1, o0..n−1>. 120 # 4. Add to S the tuple <X, t0..n−1, o0..n−1>.
83 S.append((X, t, o)) 121 S.append((X, t, o))
84 # 5. If X is declared to be variadic, then: 122 # 5. If X is declared to be variadic, then:
85 # (Not used, so not implemented.) 123 # (Not used, so not implemented.)
86 # 6. Initialize i to n−1. 124 # 6. Initialize i to n−1.
87 i = n - 1 125 i = n - 1
88 # 7. While i ≥ 0: 126 # 7. While i ≥ 0:
89 # Spec bug (fencepost error); should be “While i > 0:” 127 # Spec bug (fencepost error); should be “While i > 0:”
90 # https://www.w3.org/Bugs/Public/show_bug.cgi?id=25590 128 # https://www.w3.org/Bugs/Public/show_bug.cgi?id=25590
91 while i > 0: 129 while i > 0:
92 # 1. If argument i of X is not optional, then break this loop. 130 # 1. If argument i of X is not optional, then break this loop.
93 if not o[i]: 131 if not o[i]:
94 break 132 break
95 # 2. Otherwise, add to S the tuple <X, t0..i−1, o0..i−1>. 133 # 2. Otherwise, add to S the tuple <X, t0..i−1, o0..i−1>.
96 S.append((X, t[:i], o[:i])) 134 S.append((X, t[:i], o[:i]))
97 # 3. Set i to i−1. 135 # 3. Set i to i−1.
98 i = i - 1 136 i = i - 1
99 # 8. If n > 0 and all arguments of X are optional, then add to S the 137 # 8. If n > 0 and all arguments of X are optional, then add to S the
100 # tuple <X, (), ()> (where “()” represents the empty list). 138 # tuple <X, (), ()> (where “()” represents the empty list).
101 if n > 0 and all(oi for oi in o): 139 if n > 0 and all(oi for oi in o):
102 S.append((X, [], [])) 140 S.append((X, (), ()))
103 # 6. The effective overload set is S. 141 # 6. The effective overload set is S.
104 return S 142 return S
105 143
106 144
107 def effective_overload_set_by_length(overloads): 145 def effective_overload_set_by_length(overloads):
108 def type_list_length(entry): 146 def type_list_length(entry):
109 # Entries in the effective overload set are 3-tuples: 147 # Entries in the effective overload set are 3-tuples:
110 # (callable, type list, optionality list) 148 # (callable, type list, optionality list)
111 return len(entry[1]) 149 return len(entry[1])
112 150
113 effective_overloads = effective_overload_set(overloads) 151 effective_overloads = effective_overload_set(overloads,
152 MethodContextAdapter())
114 return list(sort_and_groupby(effective_overloads, type_list_length)) 153 return list(sort_and_groupby(effective_overloads, type_list_length))
115 154
116 155
117 def method_overloads_by_name(methods): 156 def method_overloads_by_name(methods):
118 """Returns generator of overloaded methods by name: [name, [method]]""" 157 """Returns generator of overloaded methods by name: [name, [method]]"""
119 # Filter to only methods that are actually overloaded 158 # Filter to only methods that are actually overloaded
120 method_counts = Counter(method['name'] for method in methods) 159 method_counts = Counter(method['name'] for method in methods)
121 overloaded_method_names = set(name 160 overloaded_method_names = set(name
122 for name, count in method_counts.iteritems() 161 for name, count in method_counts.iteritems()
123 if count > 1) 162 if count > 1)
124 overloaded_methods = [method for method in methods 163 overloaded_methods = [method for method in methods
125 if method['name'] in overloaded_method_names] 164 if method['name'] in overloaded_method_names]
126 165
127 # Group by name (generally will be defined together, but not necessarily) 166 # Group by name (generally will be defined together, but not necessarily)
128 return sort_and_groupby(overloaded_methods, itemgetter('name')) 167 return sort_and_groupby(overloaded_methods, itemgetter('name'))
OLDNEW
« no previous file with comments | « no previous file | third_party/WebKit/Source/bindings/scripts/overload_set_algorithm_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698