Index: lib/dom/scripts/systemwrapping.py |
diff --git a/lib/dom/scripts/systemwrapping.py b/lib/dom/scripts/systemwrapping.py |
index 7ec5be45685609c2f15a5e088d801a535b49a3d5..aa9089e63e5339b18410050004db58d6bd63d12c 100644 |
--- a/lib/dom/scripts/systemwrapping.py |
+++ b/lib/dom/scripts/systemwrapping.py |
@@ -6,6 +6,7 @@ |
"""This module provides shared functionality for the systems to generate |
wrapping binding from the IDL database.""" |
+import generator |
import os |
from generator import * |
from systembase import * |
@@ -372,7 +373,7 @@ class WrappingInterfaceGenerator(object): |
overloads = sorted(info.overloads, |
key=lambda overload: len(overload.arguments)) |
self._native_version = 0 |
- fallthrough = self.GenerateDispatch(body, info, ' ', 0, overloads) |
+ fallthrough = generator.GenerateDispatch(self, body, info, ' ', 0, overloads) |
if fallthrough: |
body.Emit(' throw "Incorrect number or type of arguments";\n'); |
@@ -425,122 +426,3 @@ class WrappingInterfaceGenerator(object): |
NAME=native_name, |
TYPE=info.type_name, |
PARAMS=', '.join(['receiver'] + arg_names) ) |
- |
- |
- def GenerateDispatch(self, emitter, info, indent, position, overloads): |
- """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(): |
- self.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 = self.GenerateDispatch( |
- true_code, info, indent + ' ', position + 1, positive) |
- fallthrough2 = self.GenerateDispatch( |
- 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 self.GenerateDispatch( |
- 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) |
- self.GenerateDispatch( |
- true_code, info, indent + ' ', position + 1, positive) |
- return True |