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

Side by Side Diff: tools/dom/scripts/htmldartgenerator.py

Issue 12052076: Support overloaded constructors. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 # Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 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 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. 4 # BSD-style license that can be found in the LICENSE file.
5 5
6 """This module provides shared functionality for the system to generate 6 """This module provides shared functionality for the system to generate
7 dart:html APIs from the IDL database.""" 7 dart:html APIs from the IDL database."""
8 8
9 import emitter
9 from generator import AnalyzeOperation, ConstantOutputOrder, \ 10 from generator import AnalyzeOperation, ConstantOutputOrder, \
10 DartDomNameOfAttribute, FindMatchingAttribute, IsDartCollectionType, \ 11 DartDomNameOfAttribute, FindMatchingAttribute, IsDartCollectionType, \
11 IsPureInterface, TypeOrNothing, FindCommonAnnotations 12 IsPureInterface, TypeOrNothing, FindCommonAnnotations
12 13
13 # Types that are accessible cross-frame in a limited fashion. 14 # Types that are accessible cross-frame in a limited fashion.
14 # In these cases, the base type (e.g., WindowBase) provides restricted access 15 # In these cases, the base type (e.g., WindowBase) provides restricted access
15 # while the subtype (e.g., Window) provides full access to the 16 # while the subtype (e.g., Window) provides full access to the
16 # corresponding objects if there are from the same frame. 17 # corresponding objects if there are from the same frame.
17 _secure_base_types = { 18 _secure_base_types = {
18 'Window': 'WindowBase', 19 'Window': 'WindowBase',
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
169 # FIXME: item should be renamed to operator[], not removed. 170 # FIXME: item should be renamed to operator[], not removed.
170 self.EmitOperation(info, '_item') 171 self.EmitOperation(info, '_item')
171 return 172 return
172 173
173 if declare_only: 174 if declare_only:
174 self.DeclareOperation(info, 175 self.DeclareOperation(info,
175 self.SecureOutputType(info.type_name), method_name) 176 self.SecureOutputType(info.type_name), method_name)
176 else: 177 else:
177 self.EmitOperation(info, method_name) 178 self.EmitOperation(info, method_name)
178 179
179 def _GenerateDispatcherBody(self, 180 def _GenerateOverloadDispatcher(self,
180 operations, 181 signatures,
182 is_void,
181 parameter_names, 183 parameter_names,
182 declaration, 184 declaration,
183 generate_call, 185 generate_call,
184 is_optional, 186 is_optional,
185 can_omit_type_check=lambda type, pos: False): 187 can_omit_type_check=lambda type, pos: False):
186 188
187 body_emitter = self._members_emitter.Emit( 189 body_emitter = self._members_emitter.Emit(
188 '\n' 190 '\n'
189 ' $DECLARATION {\n' 191 ' $DECLARATION {\n'
190 '$!BODY' 192 '$!BODY'
191 ' }\n', 193 ' }\n',
192 DECLARATION=declaration) 194 DECLARATION=declaration)
193 195
194 version = [0] 196 version = [0]
195 def GenerateCall(operation, argument_count, checks): 197 def GenerateCall(signature_index, argument_count, checks):
196 if checks: 198 if checks:
197 (stmts_emitter, call_emitter) = body_emitter.Emit( 199 (stmts_emitter, call_emitter) = body_emitter.Emit(
198 ' if ($CHECKS) {\n$!STMTS$!CALL }\n', 200 ' if ($CHECKS) {\n$!STMTS$!CALL }\n',
199 INDENT=' ', 201 INDENT=' ',
200 CHECKS=' && '.join(checks)) 202 CHECKS=' && '.join(checks))
201 else: 203 else:
202 (stmts_emitter, call_emitter) = body_emitter.Emit( 204 (stmts_emitter, call_emitter) = body_emitter.Emit(
203 '$!STMTS$!CALL', 205 '$!STMTS$!CALL',
204 INDENT=' '); 206 INDENT=' ');
205 207
206 if operation.type.id == 'void': 208 if is_void:
207 call_emitter = call_emitter.Emit('$(INDENT)$!CALL;\n$(INDENT)return;\n') 209 call_emitter = call_emitter.Emit('$(INDENT)$!CALL;\n$(INDENT)return;\n')
208 else: 210 else:
209 call_emitter = call_emitter.Emit('$(INDENT)return $!CALL;\n') 211 call_emitter = call_emitter.Emit('$(INDENT)return $!CALL;\n')
210 212
211 version[0] += 1 213 version[0] += 1
212 generate_call( 214 generate_call(stmts_emitter, call_emitter,
213 stmts_emitter, call_emitter, version[0], operation, argument_count) 215 version[0], signature_index, argument_count)
214 216
215 def GenerateChecksAndCall(operation, argument_count): 217 def GenerateChecksAndCall(signature_index, argument_count):
216 checks = [] 218 checks = []
217 for i in range(0, argument_count): 219 for i in range(0, argument_count):
218 argument = operation.arguments[i] 220 argument = signatures[signature_index][i]
219 parameter_name = parameter_names[i] 221 parameter_name = parameter_names[i]
220 test_type = self._DartType(argument.type.id) 222 test_type = self._DartType(argument.type.id)
221 if test_type in ['dynamic', 'Object']: 223 if test_type in ['dynamic', 'Object']:
222 checks.append('?%s' % parameter_name) 224 checks.append('?%s' % parameter_name)
223 elif not can_omit_type_check(test_type, i): 225 elif not can_omit_type_check(test_type, i):
224 checks.append('(%s is %s || %s == null)' % ( 226 checks.append('(%s is %s || %s == null)' % (
225 parameter_name, test_type, parameter_name)) 227 parameter_name, test_type, parameter_name))
226 # There can be multiple presence checks. We need them all since a later 228 # There can be multiple presence checks. We need them all since a later
227 # optional argument could have been passed by name, leaving 'holes'. 229 # optional argument could have been passed by name, leaving 'holes'.
228 checks.extend(['!?%s' % name for name in parameter_names[argument_count:]] ) 230 checks.extend(['!?%s' % name for name in parameter_names[argument_count:]] )
229 231
230 GenerateCall(operation, argument_count, checks) 232 GenerateCall(signature_index, argument_count, checks)
231 233
232 # TODO: Optimize the dispatch to avoid repeated checks. 234 # TODO: Optimize the dispatch to avoid repeated checks.
233 if len(operations) > 1: 235 if len(signatures) > 1:
234 for operation in operations: 236 for signature_index, signature in enumerate(signatures):
235 for position, argument in enumerate(operation.arguments): 237 for argument_position, argument in enumerate(signature):
236 if is_optional(operation, argument): 238 if is_optional(signature_index, argument):
237 GenerateChecksAndCall(operation, position) 239 GenerateChecksAndCall(signature_index, argument_position)
238 GenerateChecksAndCall(operation, len(operation.arguments)) 240 GenerateChecksAndCall(signature_index, len(signature))
239 body_emitter.Emit( 241 body_emitter.Emit(
240 ' throw new ArgumentError("Incorrect number or type of arguments"); ' 242 ' throw new ArgumentError("Incorrect number or type of arguments"); '
241 '\n'); 243 '\n');
242 else: 244 else:
243 operation = operations[0] 245 signature = signatures[0]
244 argument_count = len(operation.arguments) 246 argument_count = len(signature)
245 for position, argument in list(enumerate(operation.arguments))[::-1]: 247 for argument_position, argument in list(enumerate(signature))[::-1]:
246 if is_optional(operation, argument): 248 if is_optional(0, argument):
247 check = '?%s' % parameter_names[position] 249 check = '?%s' % parameter_names[argument_position]
248 # argument_count instead of position + 1 is used here to cover one 250 # argument_count instead of argument_position + 1 is used here to cove r one
249 # complicated case with the effectively optional argument in the middl e. 251 # complicated case with the effectively optional argument in the middl e.
250 # Consider foo(x, [Optional] y, [Optional=DefaultIsNullString] z) 252 # Consider foo(x, [Optional] y, [Optional=DefaultIsNullString] z)
251 # (as of now it's modelled after HTMLMediaElement.webkitAddKey). 253 # (as of now it's modelled after HTMLMediaElement.webkitAddKey).
252 # y is optional in WebCore, while z is not. 254 # y is optional in WebCore, while z is not.
253 # In this case, if y was actually passed, we'd like to emit foo(x, y, z) invocation, 255 # In this case, if y was actually passed, we'd like to emit foo(x, y, z) invocation,
254 # not foo(x, y). 256 # not foo(x, y).
255 GenerateCall(operation, argument_count, [check]) 257 GenerateCall(0, argument_count, [check])
256 argument_count = position 258 argument_count = argument_position
257 GenerateCall(operation, argument_count, []) 259 GenerateCall(0, argument_count, [])
260
261 def _GenerateDispatcherBody(self,
262 operations,
263 parameter_names,
264 declaration,
265 generate_call,
266 is_optional,
267 can_omit_type_check=lambda type, pos: False):
268
269 def GenerateCall(
270 stmts_emitter, call_emitter, version, signature_index, argument_count):
271 generate_call(
272 stmts_emitter, call_emitter,
273 version, operations[signature_index], argument_count)
274
275 def IsOptional(signature_index, argument):
276 return is_optional(operations[signature_index], argument)
277
278 self._GenerateOverloadDispatcher(
279 [operation.arguments for operation in operations],
280 operations[0].type.id == 'void',
281 parameter_names,
282 declaration,
283 GenerateCall,
284 IsOptional,
285 can_omit_type_check)
258 286
259 def AdditionalImplementedInterfaces(self): 287 def AdditionalImplementedInterfaces(self):
260 # TODO: Include all implemented interfaces, including other Lists. 288 # TODO: Include all implemented interfaces, including other Lists.
261 implements = [] 289 implements = []
262 if self._interface_type_info.is_typed_array(): 290 if self._interface_type_info.is_typed_array():
263 element_type = self._interface_type_info.list_item_type() 291 element_type = self._interface_type_info.list_item_type()
264 implements.append('List<%s>' % self._DartType(element_type)) 292 implements.append('List<%s>' % self._DartType(element_type))
265 if self._interface_type_info.list_item_type(): 293 if self._interface_type_info.list_item_type():
266 item_type_info = self._type_registry.TypeInfo( 294 item_type_info = self._type_registry.TypeInfo(
267 self._interface_type_info.list_item_type()) 295 self._interface_type_info.list_item_type())
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
299 '\n' 327 '\n'
300 ' factory $CTOR.fromBuffer(ArrayBuffer buffer, ' 328 ' factory $CTOR.fromBuffer(ArrayBuffer buffer, '
301 '[int byteOffset, int length]) => \n' 329 '[int byteOffset, int length]) => \n'
302 ' $FACTORY.create$(CTOR)_fromBuffer(buffer, byteOffset, length);\n' , 330 ' $FACTORY.create$(CTOR)_fromBuffer(buffer, byteOffset, length);\n' ,
303 CTOR=self._interface.id, 331 CTOR=self._interface.id,
304 TYPE=self._DartType(typed_array_type), 332 TYPE=self._DartType(typed_array_type),
305 FACTORY=factory_name) 333 FACTORY=factory_name)
306 334
307 def _AddConstructor(self, 335 def _AddConstructor(self,
308 constructor_info, factory_name, factory_constructor_name): 336 constructor_info, factory_name, factory_constructor_name):
337 if self.HasCustomFactory():
338 return
339
309 self._members_emitter.Emit('\n @DocsEditable'); 340 self._members_emitter.Emit('\n @DocsEditable');
310 341
311 if not factory_constructor_name: 342 if not factory_constructor_name:
312 factory_constructor_name = '_create' 343 factory_constructor_name = '_create'
313 factory_parameters = constructor_info.ParametersAsArgumentList() 344 factory_parameters = constructor_info.ParametersAsArgumentList()
314 has_factory_provider = True 345 has_factory_provider = True
315 else: 346 else:
316 factory_parameters = ', '.join(constructor_info.factory_parameters) 347 factory_parameters = ', '.join(constructor_info.factory_parameters)
317 has_factory_provider = False 348 has_factory_provider = False
318 349
319 has_optional = any(param_info.is_optional 350 if constructor_info.pure_dart_constructor:
320 for param_info in constructor_info.param_infos) 351 # TODO: use common dispatcher generation for this case as well.
Emily Fortuna 2013/01/28 23:01:28 nit: TODO should include username.
Anton Muhin 2013/01/29 12:09:28 Done.
352 has_optional = any(param_info.is_optional
353 for param_info in constructor_info.param_infos)
321 354
322 if not has_optional: 355 if not has_optional:
323 self._members_emitter.Emit( 356 self._members_emitter.Emit(
324 '\n'
325 ' factory $CTOR($PARAMS) => '
326 '$FACTORY.$CTOR_FACTORY_NAME($FACTORY_PARAMS);\n',
327 CTOR=constructor_info._ConstructorFullName(self._DartType),
328 PARAMS=constructor_info.ParametersDeclaration(self._DartType),
329 FACTORY=factory_name,
330 CTOR_FACTORY_NAME=factory_constructor_name,
331 FACTORY_PARAMS=factory_parameters)
332 else:
333 if has_factory_provider:
334 dispatcher_emitter = self._members_emitter.Emit(
335 '\n' 357 '\n'
336 ' factory $CTOR($PARAMS) {\n' 358 ' factory $CTOR($PARAMS) => '
337 '$!DISPATCHER' 359 '$FACTORY.$CTOR_FACTORY_NAME($FACTORY_PARAMS);\n',
338 ' return $FACTORY._create($FACTORY_PARAMS);\n'
339 ' }\n',
340 CTOR=constructor_info._ConstructorFullName(self._DartType), 360 CTOR=constructor_info._ConstructorFullName(self._DartType),
341 PARAMS=constructor_info.ParametersDeclaration(self._DartType), 361 PARAMS=constructor_info.ParametersDeclaration(self._DartType),
342 FACTORY=factory_name, 362 FACTORY=factory_name,
343 FACTORY_PARAMS=constructor_info.ParametersAsArgumentList()) 363 CTOR_FACTORY_NAME=factory_constructor_name,
364 FACTORY_PARAMS=factory_parameters)
365 else:
366 if has_factory_provider:
367 dispatcher_emitter = self._members_emitter.Emit(
368 '\n'
369 ' factory $CTOR($PARAMS) {\n'
370 '$!DISPATCHER'
371 ' return $FACTORY._create($FACTORY_PARAMS);\n'
372 ' }\n',
373 CTOR=constructor_info._ConstructorFullName(self._DartType),
374 PARAMS=constructor_info.ParametersDeclaration(self._DartType),
375 FACTORY=factory_name,
376 FACTORY_PARAMS=constructor_info.ParametersAsArgumentList())
344 377
345 for index, param_info in enumerate(constructor_info.param_infos): 378 for index, param_info in enumerate(constructor_info.param_infos):
346 if param_info.is_optional: 379 if param_info.is_optional:
347 dispatcher_emitter.Emit( 380 dispatcher_emitter.Emit(
348 ' if (!?$OPT_PARAM_NAME) {\n' 381 ' if (!?$OPT_PARAM_NAME) {\n'
349 ' return $FACTORY._create($FACTORY_PARAMS);\n' 382 ' return $FACTORY._create($FACTORY_PARAMS);\n'
350 ' }\n', 383 ' }\n',
351 OPT_PARAM_NAME=param_info.name, 384 OPT_PARAM_NAME=param_info.name,
385 FACTORY=factory_name,
386 FACTORY_PARAMS=constructor_info.ParametersAsArgumentList(index))
387 else:
388 inits = self._members_emitter.Emit(
389 '\n'
390 ' factory $CONSTRUCTOR($PARAMS) {\n'
391 ' var e = $FACTORY.$CTOR_FACTORY_NAME($FACTORY_PARAMS);\n'
392 '$!INITS'
393 ' return e;\n'
394 ' }\n',
395 CONSTRUCTOR=constructor_info._ConstructorFullName(self._DartType),
352 FACTORY=factory_name, 396 FACTORY=factory_name,
353 FACTORY_PARAMS=constructor_info.ParametersAsArgumentList(index)) 397 CTOR_FACTORY_NAME=factory_constructor_name,
354 else: 398 PARAMS=constructor_info.ParametersDeclaration(self._DartType),
355 inits = self._members_emitter.Emit( 399 FACTORY_PARAMS=factory_parameters)
356 '\n' 400
357 ' factory $CONSTRUCTOR($PARAMS) {\n' 401 for index, param_info in enumerate(constructor_info.param_infos):
358 ' var e = $FACTORY.$CTOR_FACTORY_NAME($FACTORY_PARAMS);\n' 402 if param_info.is_optional:
359 '$!INITS' 403 inits.Emit(' if ($E != null) e.$E = $E;\n', E=param_info.name)
360 ' return e;\n' 404 else:
361 ' }\n', 405 def GenerateCall(
362 CONSTRUCTOR=constructor_info._ConstructorFullName(self._DartType), 406 stmts_emitter, call_emitter,
407 version, signature_index, argument_count):
408 name = emitter.Format('_create_$VERSION', VERSION=version)
409 call_emitter.Emit('$FACTORY.$NAME($FACTORY_PARAMS)',
363 FACTORY=factory_name, 410 FACTORY=factory_name,
364 CTOR_FACTORY_NAME=factory_constructor_name, 411 NAME=name,
365 PARAMS=constructor_info.ParametersDeclaration(self._DartType), 412 FACTORY_PARAMS= \
366 FACTORY_PARAMS=factory_parameters) 413 constructor_info.ParametersAsArgumentList(argument_count))
414 self.EmitStaticFactoryOverload(
415 constructor_info, name,
416 constructor_info.idl_args[signature_index][:argument_count])
367 417
368 for index, param_info in enumerate(constructor_info.param_infos): 418 def IsOptional(signature_index, argument):
369 if param_info.is_optional: 419 return self.IsConstructorArgumentOptional(argument)
370 inits.Emit(' if ($E != null) e.$E = $E;\n', E=param_info.name)
371 420
372 if not constructor_info.pure_dart_constructor: 421 self._GenerateOverloadDispatcher(
373 self.EmitStaticFactory(constructor_info) 422 constructor_info.idl_args,
423 False,
424 [info.name for info in constructor_info.param_infos],
425 emitter.Format('factory $CTOR($PARAMS)',
426 CTOR=constructor_info._ConstructorFullName(self._DartType),
427 PARAMS=constructor_info.ParametersDeclaration(self._DartType)),
428 GenerateCall,
429 IsOptional)
374 430
375 def EmitHelpers(self, base_class): 431 def EmitHelpers(self, base_class):
376 pass 432 pass
377 433
378 def DeclareAttribute(self, attribute, type_name, attr_name, read_only): 434 def DeclareAttribute(self, attribute, type_name, attr_name, read_only):
379 """ Declares an attribute but does not include the code to invoke it. 435 """ Declares an attribute but does not include the code to invoke it.
380 """ 436 """
381 if read_only: 437 if read_only:
382 template = '\n $TYPE get $NAME;\n' 438 template = '\n $TYPE get $NAME;\n'
383 else: 439 else:
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
473 walk(interface.parents) 529 walk(interface.parents)
474 else: 530 else:
475 walk(interface.parents[1:]) 531 walk(interface.parents[1:])
476 return result 532 return result
477 533
478 def _DartType(self, type_name): 534 def _DartType(self, type_name):
479 return self._type_registry.DartType(type_name) 535 return self._type_registry.DartType(type_name)
480 536
481 def _IsPrivate(self, name): 537 def _IsPrivate(self, name):
482 return name.startswith('_') 538 return name.startswith('_')
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698