OLD | NEW |
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 os | 9 import os |
10 from generator import * | 10 from generator import * |
(...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
436 Returns True if the dispatch can fall through on failure, False if the code | 436 Returns True if the dispatch can fall through on failure, False if the code |
437 always dispatches. | 437 always dispatches. |
438 """ | 438 """ |
439 | 439 |
440 def NullCheck(name): | 440 def NullCheck(name): |
441 return '%s === null' % name | 441 return '%s === null' % name |
442 | 442 |
443 def TypeCheck(name, type): | 443 def TypeCheck(name, type): |
444 return '%s is %s' % (name, type) | 444 return '%s is %s' % (name, type) |
445 | 445 |
446 if position == len(info.arg_infos): | 446 def ShouldGenerateSingleOperation(): |
447 if len(overloads) > 1: | 447 if position == len(info.arg_infos): |
448 raise Exception('Duplicate operations ' + str(overloads)) | 448 if len(overloads) > 1: |
449 operation = overloads[0] | 449 raise Exception('Duplicate operations ' + str(overloads)) |
450 self.GenerateSingleOperation(emitter, info, indent, operation) | 450 return True |
| 451 |
| 452 # Check if we dispatch on RequiredCppParameter arguments. In this |
| 453 # case all trailing arguments must be RequiredCppParameter and there |
| 454 # is no need in dispatch. |
| 455 # TODO(antonm): better diagnositics. |
| 456 if position >= len(overloads[0].arguments): |
| 457 def IsRequiredCppParameter(arg): |
| 458 return 'RequiredCppParameter' in arg.ext_attrs |
| 459 last_overload = overloads[-1] |
| 460 if (len(last_overload.arguments) > position and |
| 461 IsRequiredCppParameter(last_overload.arguments[position])): |
| 462 for overload in overloads: |
| 463 args = overload.arguments[position:] |
| 464 if not all([IsRequiredCppParameter(arg) for arg in args]): |
| 465 raise Exception('Invalid overload for RequiredCppParameter') |
| 466 return True |
| 467 |
| 468 return False |
| 469 |
| 470 if ShouldGenerateSingleOperation(): |
| 471 self.GenerateSingleOperation(emitter, info, indent, overloads[-1]) |
451 return False | 472 return False |
452 | 473 |
453 # FIXME: Consider a simpler dispatch that iterates over the | 474 # FIXME: Consider a simpler dispatch that iterates over the |
454 # overloads and generates an overload specific check. Revisit | 475 # overloads and generates an overload specific check. Revisit |
455 # when we move to named optional arguments. | 476 # when we move to named optional arguments. |
456 | 477 |
457 if position == 0: | |
458 # Optional callback arguments are special. C++ counterparts do not have p
roper optional | |
459 # arguments (as in some cases C++ counterparts require ec) and thus 0 ref
ptrs are passed | |
460 # instead of missing arguments. That means the only allowed form is a lis
t of | |
461 # arguments with trailing optional callbacks and we don't need any dispatc
h at all. | |
462 def IsOptionalCallback(arg): return arg.is_optional and 'Callback' in arg.
ext_attrs | |
463 first_optional_callback = None | |
464 for (i, arg) in enumerate(overloads[-1].arguments): | |
465 if IsOptionalCallback(arg): | |
466 first_optional_callback = i | |
467 break | |
468 if first_optional_callback is not None: | |
469 for overload in overloads: | |
470 for arg in overload.arguments[first_optional_callback:]: | |
471 if not IsOptionalCallback(arg): | |
472 raise Exception('Invalid overloading with optional callbacks') | |
473 self.GenerateSingleOperation(emitter, info, indent, overloads[-1]) | |
474 return False | |
475 | |
476 # Partition the overloads to divide and conquer on the dispatch. | 478 # Partition the overloads to divide and conquer on the dispatch. |
477 positive = [] | 479 positive = [] |
478 negative = [] | 480 negative = [] |
479 first_overload = overloads[0] | 481 first_overload = overloads[0] |
480 (param_name, param_type, param_default) = info.arg_infos[position] | 482 (param_name, param_type, param_default) = info.arg_infos[position] |
481 | 483 |
482 if position < len(first_overload.arguments): | 484 if position < len(first_overload.arguments): |
483 # FIXME: This will not work if the second overload has a more | 485 # FIXME: This will not work if the second overload has a more |
484 # precise type than the first. E.g., | 486 # precise type than the first. E.g., |
485 # void foo(Node x); | 487 # void foo(Node x); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
531 # dispatch has removed f(X), leaving only f(Y), but there is no guarantee | 533 # dispatch has removed f(X), leaving only f(Y), but there is no guarantee |
532 # that Y = Z-X, so we need to check for Y. | 534 # that Y = Z-X, so we need to check for Y. |
533 true_code = emitter.Emit( | 535 true_code = emitter.Emit( |
534 '$(INDENT)if ($COND) {\n' | 536 '$(INDENT)if ($COND) {\n' |
535 '$!TRUE' | 537 '$!TRUE' |
536 '$(INDENT)}\n', | 538 '$(INDENT)}\n', |
537 COND=test, INDENT=indent) | 539 COND=test, INDENT=indent) |
538 self.GenerateDispatch( | 540 self.GenerateDispatch( |
539 true_code, info, indent + ' ', position + 1, positive) | 541 true_code, info, indent + ' ', position + 1, positive) |
540 return True | 542 return True |
OLD | NEW |