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

Unified Diff: Source/bindings/scripts/v8_interface.py

Issue 275763002: Compute distinguishing argument index (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Simplify index computation Created 6 years, 7 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | Source/bindings/tests/idls/TestObject.idl » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: Source/bindings/scripts/v8_interface.py
diff --git a/Source/bindings/scripts/v8_interface.py b/Source/bindings/scripts/v8_interface.py
index 4f6cf147e98c965eff7b04c1904e4000066c66ea..925a10da10fe398afd66be611d1ce9a394dd689b 100644
--- a/Source/bindings/scripts/v8_interface.py
+++ b/Source/bindings/scripts/v8_interface.py
@@ -329,15 +329,16 @@ def generate_overloads_by_type(methods):
if method['name'] in overloaded_method_names]
# Group by name (generally will be defined together, but not necessarily)
- overloaded_methods.sort(key=itemgetter('name'))
- method_overloads = dict(
- (name, list(methods_iterator)) for name, methods_iterator in
- itertools.groupby(overloaded_methods, itemgetter('name')))
+ method_overloads = sort_and_groupby(overloaded_methods, itemgetter('name'))
# Add overload information only to overloaded methods, so template code can
# easily verify if a function is overloaded
for name, overloads in method_overloads.iteritems():
- effective_overload_set(overloads) # to test, compute but discard result
+ effective_overloads_by_length = effective_overload_set_by_length(overloads)
+ for effective_overloads in effective_overloads_by_length.itervalues():
+ # To test, compute but discard result
+ distinguishing_argument_index(effective_overloads)
+
for index, method in enumerate(overloads, 1):
method.update({
'overload_index': index,
@@ -392,7 +393,7 @@ def effective_overload_set(F):
F: list of overloads for a given callable name.
Returns:
- S: list of tuples of the form <callable, type list, optionality list>.
+ S: list of tuples of the form (callable, type list, optionality list).
"""
# Code closely follows the algorithm in the spec, for clarity and
# correctness, and hence is not very Pythonic.
@@ -414,12 +415,14 @@ def effective_overload_set(F):
n = len(arguments)
# 2. Let t0..n−1 be a list of types, where ti is the type of X’s
# argument at index i.
- t = [argument['idl_type'] for argument in arguments] # type list
+ # (“type list”)
+ t = tuple(argument['idl_type_object'] for argument in arguments)
# 3. Let o0..n−1 be a list of optionality values, where oi is “variadic”
# if X’s argument at index i is a final, variadic argument, “optional”
# if the argument is optional, and “required” otherwise.
- # (We're just using a boolean for optional vs. required.)
- o = [argument['is_optional'] for argument in arguments] # optionality list
+ # (“optionality list”)
+ # (We’re just using a boolean for optional vs. required.)
+ o = tuple(argument['is_optional'] for argument in arguments)
# 4. Add to S the tuple <X, t0..n−1, o0..n−1>.
S.append((X, t, o))
# 5. If X is declared to be variadic, then:
@@ -445,6 +448,79 @@ def effective_overload_set(F):
return S
+def effective_overload_set_by_length(overloads):
+ def type_list_length(entry):
+ # Entries in the effective overload set are 3-tuples:
+ # (callable, type list, optionality list)
+ return len(entry[1])
+
+ effective_overloads = effective_overload_set(overloads)
+ return sort_and_groupby(effective_overloads, type_list_length)
+
+
+def distinguishing_argument_index(entries):
+ """Returns the distinguishing argument index for a sequence of entries.
+
+ Entries are elements of the effective overload set with the same number
+ of arguments (formally, same type list length), each a 3-tuple of the form
+ (callable, type list, optionality list).
+
+ Spec: http://heycam.github.io/webidl/#dfn-distinguishing-argument-index
+
+ If there is more than one entry in an effective overload set that has a
+ given type list length, then for those entries there must be an index i
+ such that for each pair of entries the types at index i are
+ distinguishable.
+ The lowest such index is termed the distinguishing argument index for the
+ entries of the effective overload set with the given type list length.
+ """
+ if len(entries) < 2:
+ # Only need to distinguish if two or more entries
+ return
+ type_lists = [tuple(idl_type.name for idl_type in entry[1])
+ for entry in entries]
+ type_list_length = len(type_lists[0])
+ assert all(len(type_list) == type_list_length for type_list in type_lists)
+ name = entries[0][0]['name']
+
+ # The spec defines the distinguishing argument index by conditions it must
+ # satisfy, but does not give an algorithm.
+ #
+ # We compute the distinguishing argument index by first computing the
+ # minimum index where not all types are the same, and then checking that
+ # all types in this position are distinguishable (and the optionality lists
+ # up to this point are identical), since "minimum index where not all types
+ # are the same" is a *necessary* condition, and more direct to check than
+ # distinguishability.
+ types_by_index = (set(types) for types in zip(*type_lists))
+ try:
+ # “In addition, for each index j, where j is less than the
+ # distinguishing argument index for a given type list length, the types
+ # at index j in all of the entries’ type lists must be the same”
+ index = next(i for i, types in enumerate(types_by_index)
+ if len(types) > 1)
+ except StopIteration:
+ raise ValueError('No distinguishing index found for %s, length %s:\n'
+ 'All entries have the same type list:\n'
+ '%s' % (name, type_list_length, type_lists[0]))
+ # Check optionality
+ # “and the booleans in the corresponding list indicating argument
+ # optionality must be the same.”
+ # FIXME: spec typo: optionality value is no longer a boolean
+ # https://www.w3.org/Bugs/Public/show_bug.cgi?id=25628
+ initial_optionality_lists = set(entry[2][:index] for entry in entries)
+ if len(initial_optionality_lists) > 1:
+ raise ValueError(
+ 'Invalid optionality lists for %s, length %s:\n'
+ 'Optionality lists differ below distinguishing argument index %s:\n'
+ '%s'
+ % (name, type_list_length, index, set(initial_optionality_lists)))
+
+ # FIXME: check distinguishability
+
+ return index
+
+
def overload_resolution_expression(method):
# Expression is an OR of ANDs: each term in the OR corresponds to a
# possible argument count for a given method, with type checks.
@@ -533,6 +609,18 @@ def overload_check_argument(index, argument):
return None
+################################################################################
+# Utility functions
+################################################################################
+
+def Counter(iterable):
+ # Once using Python 2.7, using collections.Counter
+ counter = defaultdict(lambda: 0)
+ for item in iterable:
+ counter[item] += 1
+ return counter
+
+
def common_value(dicts, key):
"""Returns common value of a key across an iterable of dicts, or None.
@@ -546,12 +634,10 @@ def common_value(dicts, key):
return None
-def Counter(iterable):
- # Once using Python 2.7, using collections.Counter
- counter = defaultdict(lambda: 0)
- for item in iterable:
- counter[item] += 1
- return counter
+def sort_and_groupby(l, key=None):
+ """Returns a dict of {key: list}, sorting and grouping input list by key."""
+ l.sort(key=key)
+ return dict((k, list(g)) for k, g in itertools.groupby(l, key))
################################################################################
« no previous file with comments | « no previous file | Source/bindings/tests/idls/TestObject.idl » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698