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

Side by Side Diff: lib/dom/scripts/systemwrapping.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 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 systems to generate 6 """This module provides shared functionality for the systems to generate
7 wrapping binding from the IDL database.""" 7 wrapping binding from the IDL database."""
8 8
9 import generator
9 import os 10 import os
10 from generator import * 11 from generator import *
11 from systembase import * 12 from systembase import *
12 13
13 class WrappingImplementationSystem(System): 14 class WrappingImplementationSystem(System):
14 15
15 def __init__(self, templates, database, emitters, output_dir): 16 def __init__(self, templates, database, emitters, output_dir):
16 """Prepared for generating wrapping implementation. 17 """Prepared for generating wrapping implementation.
17 18
18 - Creates emitter for JS code. 19 - Creates emitter for JS code.
(...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after
365 ' }\n', 366 ' }\n',
366 TYPE=info.type_name, 367 TYPE=info.type_name,
367 NAME=info.name, 368 NAME=info.name,
368 PARAMS=info.ParametersImplementationDeclaration()) 369 PARAMS=info.ParametersImplementationDeclaration())
369 370
370 # Process in order of ascending number of arguments to ensure missing 371 # Process in order of ascending number of arguments to ensure missing
371 # optional arguments are processed early. 372 # optional arguments are processed early.
372 overloads = sorted(info.overloads, 373 overloads = sorted(info.overloads,
373 key=lambda overload: len(overload.arguments)) 374 key=lambda overload: len(overload.arguments))
374 self._native_version = 0 375 self._native_version = 0
375 fallthrough = self.GenerateDispatch(body, info, ' ', 0, overloads) 376 fallthrough = generator.GenerateDispatch(self, body, info, ' ', 0, overlo ads)
376 if fallthrough: 377 if fallthrough:
377 body.Emit(' throw "Incorrect number or type of arguments";\n'); 378 body.Emit(' throw "Incorrect number or type of arguments";\n');
378 379
379 def AddStaticOperation(self, info): 380 def AddStaticOperation(self, info):
380 pass 381 pass
381 382
382 def GenerateSingleOperation(self, emitter, info, indent, operation): 383 def GenerateSingleOperation(self, emitter, info, indent, operation):
383 """Generates a call to a single operation. 384 """Generates a call to a single operation.
384 385
385 Arguments: 386 Arguments:
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
418 emitter.Emit('$(INDENT)$NATIVENAME($ARGS);\n' 419 emitter.Emit('$(INDENT)$NATIVENAME($ARGS);\n'
419 '$(INDENT)return;\n', 420 '$(INDENT)return;\n',
420 INDENT=indent, 421 INDENT=indent,
421 NATIVENAME=native_name, 422 NATIVENAME=native_name,
422 ARGS=argument_expressions) 423 ARGS=argument_expressions)
423 424
424 self._members_emitter.Emit(' static $TYPE $NAME($PARAMS) native;\n', 425 self._members_emitter.Emit(' static $TYPE $NAME($PARAMS) native;\n',
425 NAME=native_name, 426 NAME=native_name,
426 TYPE=info.type_name, 427 TYPE=info.type_name,
427 PARAMS=', '.join(['receiver'] + arg_names) ) 428 PARAMS=', '.join(['receiver'] + arg_names) )
428
429
430 def GenerateDispatch(self, emitter, info, indent, position, overloads):
431 """Generates a dispatch to one of the overloads.
432
433 Arguments:
434 emitter: an Emitter for the body of a block of code.
435 info: the compound information about the operation and its overloads.
436 indent: an indentation string for generated code.
437 position: the index of the parameter to dispatch on.
438 overloads: a list of the remaining IDLOperations to dispatch.
439
440 Returns True if the dispatch can fall through on failure, False if the code
441 always dispatches.
442 """
443
444 def NullCheck(name):
445 return '%s === null' % name
446
447 def TypeCheck(name, type):
448 return '%s is %s' % (name, type)
449
450 def ShouldGenerateSingleOperation():
451 if position == len(info.param_infos):
452 if len(overloads) > 1:
453 raise Exception('Duplicate operations ' + str(overloads))
454 return True
455
456 # Check if we dispatch on RequiredCppParameter arguments. In this
457 # case all trailing arguments must be RequiredCppParameter and there
458 # is no need in dispatch.
459 # TODO(antonm): better diagnositics.
460 if position >= len(overloads[0].arguments):
461 def IsRequiredCppParameter(arg):
462 return 'RequiredCppParameter' in arg.ext_attrs
463 last_overload = overloads[-1]
464 if (len(last_overload.arguments) > position and
465 IsRequiredCppParameter(last_overload.arguments[position])):
466 for overload in overloads:
467 args = overload.arguments[position:]
468 if not all([IsRequiredCppParameter(arg) for arg in args]):
469 raise Exception('Invalid overload for RequiredCppParameter')
470 return True
471
472 return False
473
474 if ShouldGenerateSingleOperation():
475 self.GenerateSingleOperation(emitter, info, indent, overloads[-1])
476 return False
477
478 # FIXME: Consider a simpler dispatch that iterates over the
479 # overloads and generates an overload specific check. Revisit
480 # when we move to named optional arguments.
481
482 # Partition the overloads to divide and conquer on the dispatch.
483 positive = []
484 negative = []
485 first_overload = overloads[0]
486 param = info.param_infos[position]
487
488 if position < len(first_overload.arguments):
489 # FIXME: This will not work if the second overload has a more
490 # precise type than the first. E.g.,
491 # void foo(Node x);
492 # void foo(Element x);
493 type = DartType(first_overload.arguments[position].type.id)
494 test = TypeCheck(param.name, type)
495 pred = lambda op: len(op.arguments) > position and DartType(op.arguments[p osition].type.id) == type
496 else:
497 type = None
498 test = NullCheck(param.name)
499 pred = lambda op: position >= len(op.arguments)
500
501 for overload in overloads:
502 if pred(overload):
503 positive.append(overload)
504 else:
505 negative.append(overload)
506
507 if positive and negative:
508 (true_code, false_code) = emitter.Emit(
509 '$(INDENT)if ($COND) {\n'
510 '$!TRUE'
511 '$(INDENT)} else {\n'
512 '$!FALSE'
513 '$(INDENT)}\n',
514 COND=test, INDENT=indent)
515 fallthrough1 = self.GenerateDispatch(
516 true_code, info, indent + ' ', position + 1, positive)
517 fallthrough2 = self.GenerateDispatch(
518 false_code, info, indent + ' ', position, negative)
519 return fallthrough1 or fallthrough2
520
521 if negative:
522 raise Exception('Internal error, must be all positive')
523
524 # All overloads require the same test. Do we bother?
525
526 # If the test is the same as the method's formal parameter then checked mode
527 # will have done the test already. (It could be null too but we ignore that
528 # case since all the overload behave the same and we don't know which types
529 # in the IDL are not nullable.)
530 if type == param.dart_type:
531 return self.GenerateDispatch(
532 emitter, info, indent, position + 1, positive)
533
534 # Otherwise the overloads have the same type but the type is a subtype of
535 # the method's synthesized formal parameter. e.g we have overloads f(X) and
536 # f(Y), implemented by the synthesized method f(Z) where X<Z and Y<Z. The
537 # dispatch has removed f(X), leaving only f(Y), but there is no guarantee
538 # that Y = Z-X, so we need to check for Y.
539 true_code = emitter.Emit(
540 '$(INDENT)if ($COND) {\n'
541 '$!TRUE'
542 '$(INDENT)}\n',
543 COND=test, INDENT=indent)
544 self.GenerateDispatch(
545 true_code, info, indent + ' ', position + 1, positive)
546 return True
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698