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

Unified Diff: client/dom/scripts/dartgenerator.py

Issue 9290020: Add support for native bindings generation to dartgenerator.py. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: . Created 8 years, 11 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 | « client/dom/scripts/dartdomgenerator.py ('k') | client/dom/src/native_DOMImplementation.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: client/dom/scripts/dartgenerator.py
diff --git a/client/dom/scripts/dartgenerator.py b/client/dom/scripts/dartgenerator.py
index 0a8184d4cacfab2ba85606a4f436a565665394fd..5952bbffd3228b2606f6f8fb19932705491772fb 100755
--- a/client/dom/scripts/dartgenerator.py
+++ b/client/dom/scripts/dartgenerator.py
@@ -365,7 +365,7 @@ class DartGenerator(object):
def Generate(self, database, output_dir,
module_source_preference=[], source_filter=None,
super_database=None, common_prefix=None, super_map={},
- lib_dir = None):
+ lib_dir=None, systems=[]):
"""Generates Dart and JS files for the loaded interfaces.
Args:
@@ -390,28 +390,39 @@ class DartGenerator(object):
self._ComputeInheritanceClosure()
+ self._systems = []
+
interface_system = InterfacesSystem(
TemplateLoader(self._template_dir, ['dom/interface', 'dom', '']),
self._database, self._emitters, self._output_dir)
+ self._systems.append(interface_system)
- wrapping_system = WrappingImplementationSystem(
- TemplateLoader(self._template_dir, ['dom/wrapping', 'dom', '']),
- self._database, self._emitters, self._output_dir)
+ if 'native' in systems:
antonm 2012/02/01 13:03:43 nit: some concerns: systems may have system we don
+ native_system = NativeImplementationSystem(
+ TemplateLoader(self._template_dir, ['dom/native', 'dom', '']),
+ self._database, self._emitters, self._auxiliary_dir,
+ self._output_dir)
- # Makes interface files available for listing in the library for the
- # wrapping implementation.
+ self._systems.append(native_system)
- wrapping_system._interface_system = interface_system
+ if 'wrapping' in systems:
+ wrapping_system = WrappingImplementationSystem(
+ TemplateLoader(self._template_dir, ['dom/wrapping', 'dom', '']),
+ self._database, self._emitters, self._output_dir)
- frog_system = FrogSystem(
- TemplateLoader(self._template_dir, ['dom/frog', 'dom', '']),
- self._database, self._emitters, self._output_dir)
+ # Makes interface files available for listing in the library for the
+ # wrapping implementation.
+ wrapping_system._interface_system = interface_system
+ self._systems.append(wrapping_system)
+
+ if 'frog' in systems:
+ frog_system = FrogSystem(
+ TemplateLoader(self._template_dir, ['dom/frog', 'dom', '']),
+ self._database, self._emitters, self._output_dir)
- frog_system._interface_system = interface_system
+ frog_system._interface_system = interface_system
+ self._systems.append(frog_system)
- self._systems = [interface_system,
- wrapping_system,
- frog_system]
# Render all interfaces into Dart and save them in files.
for interface in database.GetInterfaces():
@@ -1305,29 +1316,7 @@ class WrappingInterfaceGenerator(object):
self._type_map.Emit(' "$INTERFACE": native_$(CLASS)_create_$(CLASS),\n',
INTERFACE=interface_name, CLASS=self._class_name)
- base = 'DOMWrapperBase'
- if interface.parents:
- supertype = interface.parents[0].type.id
- # FIXME: We're currently injecting List<..> and EventTarget as
- # supertypes in dart.idl. We should annotate/preserve as
- # attributes instead. For now, this hack lets the interfaces
- # inherit, but not the classes.
- if (not _IsDartListType(supertype) and
- not supertype == 'EventTarget'):
- base = self._ImplClassName(supertype)
- if _IsDartCollectionType(supertype):
- # List methods are injected in AddIndexer.
- pass
- elif supertype == 'EventTarget':
- # Most implementors of EventTarget specify the EventListener operations
- # again. If the operations are not specified, try to inherit from the
- # EventTarget implementation.
- #
- # Applies to MessagePort.
- if not [op for op in interface.operations if op.id == 'addEventListener']:
- base = self._ImplClassName(supertype)
- else:
- base = self._ImplClassName(supertype)
+ base = self._BaseClassName(interface)
(self._members_emitter,
self._top_level_emitter) = self._dart_code.Emit(
@@ -1348,6 +1337,32 @@ class WrappingInterfaceGenerator(object):
def _ImplClassName(self, type_name):
return '_' + type_name + 'WrappingImplementation'
+ def _BaseClassName(self, interface):
+ if not interface.parents:
+ return 'DOMWrapperBase'
+
+ supertype = interface.parents[0].type.id
+
+ # FIXME: We're currently injecting List<..> and EventTarget as
+ # supertypes in dart.idl. We should annotate/preserve as
+ # attributes instead. For now, this hack lets the interfaces
+ # inherit, but not the classes.
+ # List methods are injected in AddIndexer.
+ if _IsDartListType(supertype) or _IsDartCollectionType(supertype):
+ return 'DOMWrapperBase'
+
+ if supertype == 'EventTarget':
+ # Most implementors of EventTarget specify the EventListener operations
+ # again. If the operations are not specified, try to inherit from the
+ # EventTarget implementation.
+ #
+ # Applies to MessagePort.
+ if not [op for op in interface.operations if op.id == 'addEventListener']:
+ return self._ImplClassName(supertype)
+ return 'DOMWrapperBase'
+
+ return self._ImplClassName(supertype)
+
def FinishInterface(self):
"""."""
pass
@@ -1441,24 +1456,8 @@ class WrappingInterfaceGenerator(object):
#
# class YImpl extends ListBase<T> { copies of transitive XImpl methods; }
#
- if ('HasIndexGetter' in self._interface.ext_attrs or
- 'HasNumericIndexGetter' in self._interface.ext_attrs):
- method_name = '_index'
- self._members_emitter.Emit(
- '\n'
- ' $TYPE operator[](int index) { return $METHOD(this, index); }\n'
- ' static $TYPE $METHOD(var _this, int index) native;\n',
- TYPE=element_type, METHOD=method_name)
- self._js_code.Emit(
- '\n'
- 'function native_$(CLASS)_$(METHOD)(_this, index) {\n'
- ' try {\n'
- ' return __dom_wrap(_this.$dom[index]);\n'
- ' } catch (e) {\n'
- ' throw __dom_wrap_exception(e);\n'
- ' }\n'
- '}\n',
- CLASS=self._class_name, METHOD=method_name)
+ if self._HasNativeIndexGetter(self._interface):
+ self._EmitNativeIndexGetter(self._interface, element_type)
else:
self._members_emitter.Emit(
'\n'
@@ -1467,26 +1466,8 @@ class WrappingInterfaceGenerator(object):
' }\n',
TYPE=element_type)
-
- if 'HasCustomIndexSetter' in self._interface.ext_attrs:
- method_name = '_set_index'
- self._members_emitter.Emit(
- '\n'
- ' void operator[]=(int index, $TYPE value) {\n'
- ' return $METHOD(this, index, value);\n'
- ' }\n'
- ' static $METHOD(_this, index, value) native;\n',
- TYPE=element_type, METHOD=method_name)
- self._js_code.Emit(
- '\n'
- 'function native_$(CLASS)_$(METHOD)(_this, index, value) {\n'
- ' try {\n'
- ' return _this.$dom[index] = __dom_unwrap(value);\n'
- ' } catch (e) {\n'
- ' throw __dom_wrap_exception(e);\n'
- ' }\n'
- '}\n',
- CLASS=self._class_name, METHOD=method_name)
+ if self._HasNativeIndexSetter(self._interface):
+ self._EmitNativeIndexSetter(self._interface, element_type)
else:
self._members_emitter.Emit(
'\n'
@@ -1584,6 +1565,51 @@ class WrappingInterfaceGenerator(object):
' }\n',
TYPE=element_type)
+ def _HasNativeIndexGetter(self, interface):
+ return ('HasIndexGetter' in interface.ext_attrs or
+ 'HasNumericIndexGetter' in interface.ext_attrs)
+
+ def _EmitNativeIndexGetter(self, interface, element_type):
+ method_name = '_index'
+ self._members_emitter.Emit(
+ '\n'
+ ' $TYPE operator[](int index) { return $METHOD(this, index); }\n'
+ ' static $TYPE $METHOD(var _this, int index) native;\n',
+ TYPE=element_type, METHOD=method_name)
+ self._js_code.Emit(
+ '\n'
+ 'function native_$(CLASS)_$(METHOD)(_this, index) {\n'
+ ' try {\n'
+ ' return __dom_wrap(_this.$dom[index]);\n'
+ ' } catch (e) {\n'
+ ' throw __dom_wrap_exception(e);\n'
+ ' }\n'
+ '}\n',
+ CLASS=self._class_name, METHOD=method_name)
+
+ def _HasNativeIndexSetter(self, interface):
+ return 'HasCustomIndexSetter' in interface.ext_attrs
+
+ def _EmitNativeIndexSetter(self, interface, element_type):
+ method_name = '_set_index'
+ self._members_emitter.Emit(
+ '\n'
+ ' void operator[]=(int index, $TYPE value) {\n'
+ ' return $METHOD(this, index, value);\n'
+ ' }\n'
+ ' static $METHOD(_this, index, value) native;\n',
+ TYPE=element_type, METHOD=method_name)
+ self._js_code.Emit(
+ '\n'
+ 'function native_$(CLASS)_$(METHOD)(_this, index, value) {\n'
+ ' try {\n'
+ ' return _this.$dom[index] = __dom_unwrap(value);\n'
+ ' } catch (e) {\n'
+ ' throw __dom_wrap_exception(e);\n'
+ ' }\n'
+ '}\n',
+ CLASS=self._class_name, METHOD=method_name)
+
def AddOperation(self, info):
"""
Arguments:
@@ -2034,3 +2060,223 @@ class FrogInterfaceGenerator(object):
NAME=info.name,
PARAMS=info.ParametersImplementationDeclaration(
lambda type_name: self._NarrowInputType(type_name)))
+
+
+# ------------------------------------------------------------------------------
+
+class NativeImplementationSystem(System):
+
+ def __init__(self, templates, database, emitters, auxiliary_dir, output_dir):
+ super(NativeImplementationSystem, self).__init__(
+ templates, database, emitters, output_dir)
+
+ self._auxiliary_dir = auxiliary_dir
+ self._dom_public_files = []
+ self._dom_impl_files = []
+
+ def InterfaceGenerator(self,
+ interface,
+ common_prefix,
+ super_interface_name,
+ source_filter):
+ interface_name = interface.id
+
+ dart_interface_path = self._FilePathForDartInterface(interface_name)
+ self._dom_public_files.append(dart_interface_path)
+
+ dart_impl_path = self._FilePathForDartImplementation(interface_name)
+ self._dom_impl_files.append(dart_impl_path)
+
+ return NativeImplementationGenerator(interface, super_interface_name,
+ self._emitters.FileEmitter(dart_impl_path),
+ self._BaseDefines(interface),
+ self._templates)
+
+ def ProcessCallback(self, interface, info):
+ self._dom_public_files.append(self._FilePathForDartInterface(interface.id))
+
+ def GenerateLibraries(self, lib_dir):
+ auxiliary_dir = os.path.relpath(self._auxiliary_dir, self._output_dir)
+
+ # Generate dom_public.dart.
+ dom_public_path = os.path.join(self._output_dir, 'dom_public.dart')
+
+ dom_public_imports_emitter = emitter.Emitter()
+ for file in self._dom_public_files:
+ path = os.path.relpath(file, os.path.dirname(dom_public_path))
+ dom_public_imports_emitter.Emit('#source("$PATH");\n', PATH=path)
+
+ dom_public_emitter = self._emitters.FileEmitter(dom_public_path)
+ dom_public_emitter.Emit(self._templates.Load('dom_public.darttemplate'),
+ AUXILIARY_DIR=auxiliary_dir,
+ SOURCES=dom_public_imports_emitter.Fragments())
+
+ # Generate dom_impl.dart.
+ dom_impl_path = os.path.join(self._output_dir, 'dom_impl.dart')
+
+ dom_impl_imports_emitter = emitter.Emitter()
+ for file in self._dom_impl_files:
+ path = os.path.relpath(file, os.path.dirname(dom_impl_path))
+ dom_impl_imports_emitter.Emit('#source("$PATH");\n', PATH=path)
+
+ dom_impl_emitter = self._emitters.FileEmitter(dom_impl_path)
+ dom_impl_emitter.Emit(self._templates.Load('dom_impl.darttemplate'),
+ AUXILIARY_DIR=auxiliary_dir,
+ SOURCES=dom_impl_imports_emitter.Fragments())
+
+ def Finish(self):
+ pass
+
+ def _FilePathForDartInterface(self, interface_name):
+ return os.path.join(self._output_dir, 'src', 'interface',
+ '%s.dart' % interface_name)
+
+ def _FilePathForDartImplementation(self, interface_name):
+ return os.path.join(self._output_dir, 'dart',
+ '%sImplementation.dart' % interface_name)
+
+
+class NativeImplementationGenerator(WrappingInterfaceGenerator):
+ """Generates Dart implementation for one DOM IDL interface."""
+
+ def __init__(self, interface, super_interface, dart_impl_emitter,
+ base_members, templates):
+ """Generates Dart code for the given interface.
+
+ Args:
+
+ interface: an IDLInterface instance. It is assumed that all types have
+ been converted to Dart types (e.g. int, String), unless they are in
+ the same package as the interface.
+ super_interface: A string or None, the name of the common interface that
+ this interface implements, if any.
+ dart_impl_emitter: an Emitter for the file containing the Dart
+ implementation class.
+ base_members: a set of names of members defined in a base class. This is
+ used to avoid static member 'overriding' in the generated Dart code.
+ """
+ self._interface = interface
+ self._super_interface = super_interface
+ self._dart_impl_emitter = dart_impl_emitter
+ self._base_members = base_members
+ self._templates = templates
+ self._current_secondary_parent = None
+
+ def StartInterface(self):
+ self._class_name = self._ImplClassName(self._interface.id)
+ self._members_emitter = emitter.Emitter()
+
+ def _ImplClassName(self, type_name):
+ return type_name + 'Implementation'
+
+ def FinishInterface(self):
+ interface = self._interface
+ interface_name = interface.id
+
+ base = self._BaseClassName(interface)
+ self._dart_impl_emitter.Emit(
+ self._templates.Load('dart_implementation.darttemplate'),
+ CLASS=self._class_name, BASE=base, INTERFACE=interface_name,
+ MEMBERS=self._members_emitter.Fragments())
+
+ def AddGetter(self, attr):
+ self._members_emitter.Emit(
+ '\n'
+ ' $TYPE get $NAME() native "$(INTERFACE)_$(NAME)_Getter";\n',
+ NAME=attr.id, TYPE=attr.type.id, INTERFACE=self._interface.id)
+
+ def AddSetter(self, attr):
+ self._members_emitter.Emit(
+ '\n'
+ ' void set $NAME($TYPE) native "$(INTERFACE)_$(NAME)_Setter";\n',
+ NAME=attr.id, TYPE=attr.type.id, INTERFACE=self._interface.id)
+
+ def _HasNativeIndexGetter(self, interface):
+ return ('HasCustomIndexGetter' in interface.ext_attrs or
+ 'HasNumericIndexGetter' in interface.ext_attrs)
+
+ def _EmitNativeIndexGetter(self, interface, element_type):
+ native_binding = '%s_numericIndexGetter_Callback' % interface.id
+ self._members_emitter.Emit(
+ '\n'
+ ' $TYPE operator[](int index) native "$NATIVE_BINDING";\n',
+ TYPE=element_type, NATIVE_BINDING=native_binding)
+
+ def _EmitNativeIndexSetter(self, interface, element_type):
+ native_binding = '%s_numericIndexSetter_Callback' % self._interface.id
+ self._members_emitter.Emit(
+ '\n'
+ ' void operator[]=(int index, $TYPE value) native "$NATIVE_BINDING";\n',
+ TYPE=element_type, NATIVE_BINDING=native_binding)
+
+ def AddOperation(self, info):
+ """
+ Arguments:
+ info: An OperationInfo object.
+ """
+
+ if 'Custom' in info.overloads[0].ext_attrs:
+ self._members_emitter.Emit(
+ '\n'
+ ' $TYPE $NAME($PARAMETERS) native "$(INTERFACE)_$(NAME)_Callback";\n',
+ TYPE=info.type_name,
+ NAME=info.name,
+ PARAMETERS=info.ParametersImplementationDeclaration(),
+ INTERFACE=self._interface.id)
+ return
+
+ body = self._members_emitter.Emit(
+ '\n'
+ ' $TYPE $NAME($PARAMETERS) {\n'
+ '$!BODY'
+ ' }\n',
+ TYPE=info.type_name,
+ NAME=info.name,
+ PARAMETERS=info.ParametersImplementationDeclaration())
+
+ # Process in order of ascending number of arguments to ensure missing
+ # optional arguments are processed early.
+ overloads = sorted(info.overloads,
+ key=lambda overload: len(overload.arguments))
+ self._native_version = 0
+ fallthrough = self.GenerateDispatch(body, info, ' ', 0, overloads)
+ if fallthrough:
+ body.Emit(' throw "Incorrect number or type of arguments";\n');
+
+ def GenerateSingleOperation(self, emitter, info, indent, operation):
+ """Generates a call to a single operation.
+
+ 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.
+ operation: the IDLOperation to call.
+ """
+
+ arg_names = [info.arg_infos[i][0]
+ for (i, arg) in enumerate(operation.arguments)]
+
+ self._native_version += 1
+ native_name = '_%s' % info.name
+ if self._native_version > 1:
+ native_name = '%s_%s' % (native_name, self._native_version)
+
+ argument_expressions = ', '.join(arg_names)
+ if info.type_name != 'void':
+ emitter.Emit('$(INDENT)return $NATIVENAME($ARGS);\n',
+ INDENT=indent,
+ NATIVENAME=native_name,
+ ARGS=argument_expressions)
+ else:
+ emitter.Emit('$(INDENT)$NATIVENAME($ARGS);\n'
+ '$(INDENT)return;\n',
+ INDENT=indent,
+ NATIVENAME=native_name,
+ ARGS=argument_expressions)
+
+ self._members_emitter.Emit(' $TYPE $NATIVE_NAME($PARAMS) native '
+ '"$(INTERFACE)$(NATIVE_NAME)_Callback";\n',
+ NATIVE_NAME=native_name,
+ TYPE=info.type_name,
+ PARAMS=', '.join(arg_names),
+ INTERFACE=self._interface.id)
« no previous file with comments | « client/dom/scripts/dartdomgenerator.py ('k') | client/dom/src/native_DOMImplementation.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698