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

Side by Side Diff: client/dom/scripts/systemfrog.py

Issue 9403004: Wrapperless dart:html generator (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Code review fixes Created 8 years, 10 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 #!/usr/bin/python
2 # Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
3 # for details. All rights reserved. Use of this source code is governed by a
4 # BSD-style license that can be found in the LICENSE file.
5
6 """This module provides shared functionality for the systems to generate
7 frog binding from the IDL database."""
8
9 import os
10 from systembase import *
11
12 class FrogSystem(System):
13
14 def __init__(self, templates, database, emitters, output_dir):
15 super(FrogSystem, self).__init__(
16 templates, database, emitters, output_dir)
17 self._dart_frog_file_paths = []
18
19 def InterfaceGenerator(self,
20 interface,
21 common_prefix,
22 super_interface_name,
23 source_filter):
24 """."""
25 dart_frog_file_path = self._FilePathForFrogImpl(interface.id)
26 self._dart_frog_file_paths.append(dart_frog_file_path)
27
28 template_file = 'impl_%s.darttemplate' % interface.id
29 template = self._templates.TryLoad(template_file)
30 if not template:
31 template = self._templates.Load('frog_impl.darttemplate')
32
33 dart_code = self._emitters.FileEmitter(dart_frog_file_path)
34 return FrogInterfaceGenerator(self, interface, template,
35 super_interface_name, dart_code)
36
37 def GenerateLibraries(self, lib_dir):
38 self._GenerateLibFile(
39 'frog_dom.darttemplate',
40 os.path.join(lib_dir, 'dom_frog.dart'),
41 (self._interface_system._dart_interface_file_paths +
42 self._interface_system._dart_callback_file_paths +
43 self._dart_frog_file_paths))
44
45 def Finish(self):
46 pass
47
48 def _FilePathForFrogImpl(self, interface_name):
49 """Returns the file path of the Frog implementation."""
50 return os.path.join(self._output_dir, 'src', 'frog',
51 '%s.dart' % interface_name)
52
53 # ------------------------------------------------------------------------------
54
55 class FrogInterfaceGenerator(object):
56 """Generates a Frog class for a DOM IDL interface."""
57
58 def __init__(self, system, interface, template, super_interface, dart_code):
59 """Generates Dart code for the given interface.
60
61 Args:
62
63 interface: an IDLInterface instance. It is assumed that all types have
64 been converted to Dart types (e.g. int, String), unless they are in
65 the same package as the interface.
66 template: A string template.
67 super_interface: A string or None, the name of the common interface that
68 this interface implements, if any.
69 dart_code: an Emitter for the file containing the Dart implementation
70 class.
71 """
72 self._system = system
73 self._interface = interface
74 self._template = template
75 self._super_interface = super_interface
76 self._dart_code = dart_code
77 self._current_secondary_parent = None
78
79
80 def StartInterface(self):
81 interface = self._interface
82 interface_name = interface.id
83 self._class_name = self._ImplClassName(interface_name)
84
85 base = None
86 if interface.parents:
87 supertype = interface.parents[0].type.id
88 if IsDartCollectionType(supertype):
89 # List methods are injected in AddIndexer.
90 pass
91 else:
92 base = self._ImplClassName(supertype)
93
94 native_spec = MakeNativeSpec(interface.javascript_binding_name)
95
96 if base:
97 extends = ' extends ' + base
98 elif native_spec[0] == '=':
99 # The implementation is a singleton with no prototype.
100 extends = ''
101 else:
102 extends = ' extends _DOMTypeJs'
103
104 # TODO: Include all implemented interfaces, including other Lists.
105 implements = [interface_name]
106 element_type = MaybeTypedArrayElementType(self._interface)
107 if element_type:
108 implements.append('List<' + element_type + '>')
109
110 self._members_emitter = self._dart_code.Emit(
111 self._template,
112 #class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
113 #$!MEMBERS
114 #}
115 CLASSNAME=self._class_name,
116 EXTENDS=extends,
117 IMPLEMENTS=' implements ' + ', '.join(implements),
118 NATIVESPEC=' native "' + native_spec + '"')
119
120 element_type = MaybeTypedArrayElementType(interface)
121 if element_type:
122 self.AddTypedArrayConstructors(element_type)
123
124
125 def FinishInterface(self):
126 """."""
127 pass
128
129 def _ImplClassName(self, type_name):
130 return '_' + type_name + 'Js'
131
132 def _NarrowToImplementationType(self, type_name):
133 # TODO(sra): Move into the 'system' and cache the result.
134 if type_name == 'EventListener':
135 # Callbacks are typedef functions so don't have a class.
136 return type_name
137 if self._system._database.HasInterface(type_name):
138 interface = self._system._database.GetInterface(type_name)
139 if RecognizeCallback(interface):
140 # Callbacks are typedef functions so don't have a class.
141 return type_name
142 else:
143 return self._ImplClassName(type_name)
144 return type_name
145
146 def _NarrowInputType(self, type_name):
147 return self._NarrowToImplementationType(type_name)
148
149 def _NarrowOutputType(self, type_name):
150 return self._NarrowToImplementationType(type_name)
151
152 def AddConstant(self, constant):
153 # Since we are currently generating native classes without interfaces,
154 # generate the constants as part of the class. This will need to go away
155 # if we revert back to generating interfaces.
156 self._members_emitter.Emit('\n static final $TYPE $NAME = $VALUE;\n',
157 NAME=constant.id,
158 TYPE=constant.type.id,
159 VALUE=constant.value)
160
161 pass
162
163 def AddAttribute(self, getter, setter):
164 output_type = getter and self._NarrowOutputType(getter.type.id)
165 input_type = setter and self._NarrowInputType(setter.type.id)
166
167 # If the (getter, setter) pair is shadowing, we can't generate a shadowing
168 # field (Issue 1633).
169 (super_getter, super_getter_interface) = self._FindShadowedAttribute(getter)
170 (super_setter, super_setter_interface) = self._FindShadowedAttribute(setter)
171 if super_getter or super_setter:
172 if getter and not setter and super_getter and not super_setter:
173 if getter.type.id == super_getter.type.id:
174 # Compatible getter, use the superclass property. This works because
175 # JavaScript will do its own dynamic dispatch.
176 self._members_emitter.Emit(
177 '\n'
178 ' // Use implementation from $SUPER.\n'
179 ' // final $TYPE $NAME;\n',
180 SUPER=super_getter_interface.id,
181 NAME=getter.id, TYPE=output_type)
182 return
183
184 self._members_emitter.Emit('\n // Shadowing definition.')
185 self._AddAttributeUsingProperties(getter, setter)
186 return
187
188 if getter and setter and input_type == output_type:
189 self._members_emitter.Emit(
190 '\n $TYPE $NAME;\n',
191 NAME=getter.id, TYPE=output_type)
192 return
193 if getter and not setter:
194 self._members_emitter.Emit(
195 '\n final $TYPE $NAME;\n',
196 NAME=getter.id, TYPE=output_type)
197 return
198 self._AddAttributeUsingProperties(getter, setter)
199
200 def _AddAttributeUsingProperties(self, getter, setter):
201 if getter:
202 self._AddGetter(getter)
203 if setter:
204 self._AddSetter(setter)
205
206 def _AddGetter(self, attr):
207 # TODO(sra): Remove native body when Issue 829 fixed.
208 self._members_emitter.Emit(
209 '\n $TYPE get $NAME() native "return this.$NAME;";\n',
210 NAME=attr.id, TYPE=self._NarrowOutputType(attr.type.id))
211
212 def _AddSetter(self, attr):
213 # TODO(sra): Remove native body when Issue 829 fixed.
214 self._members_emitter.Emit(
215 ' void set $NAME($TYPE value) native "this.$NAME = value;";\n',
216 NAME=attr.id, TYPE=self._NarrowInputType(attr.type.id))
217
218 def _FindShadowedAttribute(self, attr):
219 """Returns (attribute, superinterface) or (None, None)."""
220 def FindInParent(interface):
221 """Returns matching attribute in parent, or None."""
222 if interface.parents:
223 parent = interface.parents[0]
224 if IsDartCollectionType(parent.type.id):
225 return (None, None)
226 if self._system._database.HasInterface(parent.type.id):
227 parent_interface = self._system._database.GetInterface(parent.type.id)
228 attr2 = FindMatchingAttribute(parent_interface, attr)
229 if attr2:
230 return (attr2, parent_interface)
231 return FindInParent(parent_interface)
232 return (None, None)
233
234 return FindInParent(self._interface) if attr else (None, None)
235
236
237 def AddSecondaryAttribute(self, interface, getter, setter):
238 self._SecondaryContext(interface)
239 self.AddAttribute(getter, setter)
240
241 def AddSecondaryOperation(self, interface, info):
242 self._SecondaryContext(interface)
243 self.AddOperation(info)
244
245 def AddEventAttributes(self, event_attrs):
246 pass
247
248 def _SecondaryContext(self, interface):
249 if interface is not self._current_secondary_parent:
250 self._current_secondary_parent = interface
251 self._members_emitter.Emit('\n // From $WHERE\n', WHERE=interface.id)
252
253 def AddIndexer(self, element_type):
254 """Adds all the methods required to complete implementation of List."""
255 # We would like to simply inherit the implementation of everything except
256 # get length(), [], and maybe []=. It is possible to extend from a base
257 # array implementation class only when there is no other implementation
258 # inheritance. There might be no implementation inheritance other than
259 # DOMBaseWrapper for many classes, but there might be some where the
260 # array-ness is introduced by a non-root interface:
261 #
262 # interface Y extends X, List<T> ...
263 #
264 # In the non-root case we have to choose between:
265 #
266 # class YImpl extends XImpl { add List<T> methods; }
267 #
268 # and
269 #
270 # class YImpl extends ListBase<T> { copies of transitive XImpl methods; }
271 #
272 self._members_emitter.Emit(
273 '\n'
274 ' $TYPE operator[](int index) native "return this[index];";\n',
275 TYPE=self._NarrowOutputType(element_type))
276
277 if 'HasCustomIndexSetter' in self._interface.ext_attrs:
278 self._members_emitter.Emit(
279 '\n'
280 ' void operator[]=(int index, $TYPE value) native "this[index] = valu e";\n',
281 TYPE=self._NarrowInputType(element_type))
282 else:
283 self._members_emitter.Emit(
284 '\n'
285 ' void operator[]=(int index, $TYPE value) {\n'
286 ' throw new UnsupportedOperationException("Cannot assign element of immutable List.");\n'
287 ' }\n',
288 TYPE=self._NarrowInputType(element_type))
289
290 # TODO(sra): Use separate mixins for mutable implementations of List<T>.
291 # TODO(sra): Use separate mixins for typed array implementations of List<T>.
292 template_file = 'immutable_list_mixin.darttemplate'
293 template = self._system._templates.Load(template_file)
294 self._members_emitter.Emit(template, E=element_type)
295
296
297 def AddTypedArrayConstructors(self, element_type):
298 self._members_emitter.Emit(
299 '\n'
300 ' factory $CTOR(int length) => _construct_$CTOR(length);\n'
301 '\n'
302 ' factory $CTOR.fromList(List<$TYPE> list) => _construct_$CTOR(list);\n '
303 '\n'
304 ' factory $CTOR.fromBuffer(ArrayBuffer buffer) => _construct_$CTOR(buff er);\n'
305 '\n'
306 ' static _construct_$CTOR(arg) native \'return new $CTOR(arg);\';\n',
307 CTOR=self._interface.id,
308 TYPE=element_type)
309
310
311 def AddOperation(self, info):
312 """
313 Arguments:
314 info: An OperationInfo object.
315 """
316 # TODO(vsm): Handle overloads.
317 self._members_emitter.Emit(
318 '\n'
319 ' $TYPE $NAME($PARAMS) native;\n',
320 TYPE=self._NarrowOutputType(info.type_name),
321 NAME=info.name,
322 PARAMS=info.ParametersImplementationDeclaration(
323 lambda type_name: self._NarrowInputType(type_name)))
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698