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

Unified Diff: lib/dom/scripts/generator.py

Issue 10375026: Start GenerateDispatch refactoring. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 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 | lib/dom/scripts/systemhtml.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/dom/scripts/generator.py
diff --git a/lib/dom/scripts/generator.py b/lib/dom/scripts/generator.py
index 8d72a6c024459201352f46a8d717b078d2417b26..25cfd43f28129ec0d6039b99b58dafb54af963dc 100644
--- a/lib/dom/scripts/generator.py
+++ b/lib/dom/scripts/generator.py
@@ -721,3 +721,121 @@ def GetIDLTypeInfo(idl_type_name):
if match:
return SequenceIDLTypeInfo(idl_type_name, GetIDLTypeInfo(match.group(1)))
return _idl_type_registry.get(idl_type_name, IDLTypeInfo(idl_type_name))
+
+def GenerateDispatch(generator, emitter, info, indent, position, overloads):
podivilov 2012/05/05 16:44:12 I don't think it's a good idea to move this method
sra1 2012/05/05 18:02:06 Pavel, could you say why? My concern is that nati
podivilov 2012/05/10 10:51:43 We currently use this method in two systems - nati
Anton Muhin 2012/05/10 11:30:13 I am not sure we should be that picky about how ma
Anton Muhin 2012/05/10 11:30:13 Stephen, this CL just gets rid of code duplication
podivilov 2012/05/10 15:57:13 Why is it needed? We are going to get rid of dupli
Anton Muhin 2012/05/10 16:11:55 What do you suggest? Wait until we get rid of it?
podivilov 2012/05/10 16:20:36 Personally, I prefer that you wait until migration
Anton Muhin 2012/05/10 16:24:08 What's ETA? If it's a day or two, I'd better wait
+ """Generates a dispatch to one of the overloads.
+
+ Arguments:
+ emitter: an Emitter for the body of a block of code.
+ info: the compound information about the operation and its overloads.
+ indent: an indentation string for generated code.
+ position: the index of the parameter to dispatch on.
+ overloads: a list of the remaining IDLOperations to dispatch.
+
+ Returns True if the dispatch can fall through on failure, False if the code
+ always dispatches.
+ """
+
+ def NullCheck(name):
+ return '%s === null' % name
+
+ def TypeCheck(name, type):
+ return '%s is %s' % (name, type)
+
+ def ShouldGenerateSingleOperation():
+ if position == len(info.param_infos):
+ if len(overloads) > 1:
+ raise Exception('Duplicate operations ' + str(overloads))
+ return True
+
+ # Check if we dispatch on RequiredCppParameter arguments. In this
+ # case all trailing arguments must be RequiredCppParameter and there
+ # is no need in dispatch.
+ # TODO(antonm): better diagnositics.
+ if position >= len(overloads[0].arguments):
+ def IsRequiredCppParameter(arg):
+ return 'RequiredCppParameter' in arg.ext_attrs
+ last_overload = overloads[-1]
+ if (len(last_overload.arguments) > position and
+ IsRequiredCppParameter(last_overload.arguments[position])):
+ for overload in overloads:
+ args = overload.arguments[position:]
+ if not all([IsRequiredCppParameter(arg) for arg in args]):
+ raise Exception('Invalid overload for RequiredCppParameter')
+ return True
+
+ return False
+
+ if ShouldGenerateSingleOperation():
+ generator.GenerateSingleOperation(emitter, info, indent, overloads[-1])
+ return False
+
+ # FIXME: Consider a simpler dispatch that iterates over the
+ # overloads and generates an overload specific check. Revisit
+ # when we move to named optional arguments.
+
+ # Partition the overloads to divide and conquer on the dispatch.
+ positive = []
+ negative = []
+ first_overload = overloads[0]
+ param = info.param_infos[position]
+
+ if position < len(first_overload.arguments):
+ # FIXME: This will not work if the second overload has a more
+ # precise type than the first. E.g.,
+ # void foo(Node x);
+ # void foo(Element x);
+ type = DartType(first_overload.arguments[position].type.id)
+ test = TypeCheck(param.name, type)
+ pred = lambda op: len(op.arguments) > position and DartType(op.arguments[position].type.id) == type
+ else:
+ type = None
+ test = NullCheck(param.name)
+ pred = lambda op: position >= len(op.arguments)
+
+ for overload in overloads:
+ if pred(overload):
+ positive.append(overload)
+ else:
+ negative.append(overload)
+
+ if positive and negative:
+ (true_code, false_code) = emitter.Emit(
+ '$(INDENT)if ($COND) {\n'
+ '$!TRUE'
+ '$(INDENT)} else {\n'
+ '$!FALSE'
+ '$(INDENT)}\n',
+ COND=test, INDENT=indent)
+ fallthrough1 = GenerateDispatch(generator,
+ true_code, info, indent + ' ', position + 1, positive)
+ fallthrough2 = GenerateDispatch(generator,
+ false_code, info, indent + ' ', position, negative)
+ return fallthrough1 or fallthrough2
+
+ if negative:
+ raise Exception('Internal error, must be all positive')
+
+ # All overloads require the same test. Do we bother?
+
+ # If the test is the same as the method's formal parameter then checked mode
+ # will have done the test already. (It could be null too but we ignore that
+ # case since all the overload behave the same and we don't know which types
+ # in the IDL are not nullable.)
+ if type == param.dart_type:
+ return GenerateDispatch(generator,
+ emitter, info, indent, position + 1, positive)
+
+ # Otherwise the overloads have the same type but the type is a subtype of
+ # the method's synthesized formal parameter. e.g we have overloads f(X) and
+ # f(Y), implemented by the synthesized method f(Z) where X<Z and Y<Z. The
+ # dispatch has removed f(X), leaving only f(Y), but there is no guarantee
+ # that Y = Z-X, so we need to check for Y.
+ true_code = emitter.Emit(
+ '$(INDENT)if ($COND) {\n'
+ '$!TRUE'
+ '$(INDENT)}\n',
+ COND=test, INDENT=indent)
+ GenerateDispatch(generator,
+ true_code, info, indent + ' ', position + 1, positive)
+ return True
« no previous file with comments | « no previous file | lib/dom/scripts/systemhtml.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698