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 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
384 info: the compound information about the operation and its overloads. | 384 info: the compound information about the operation and its overloads. |
385 indent: an indentation string for generated code. | 385 indent: an indentation string for generated code. |
386 operation: the IDLOperation to call. | 386 operation: the IDLOperation to call. |
387 """ | 387 """ |
388 # TODO(sra): Do we need to distinguish calling with missing optional | 388 # TODO(sra): Do we need to distinguish calling with missing optional |
389 # arguments from passing 'null' which is represented as 'undefined'? | 389 # arguments from passing 'null' which is represented as 'undefined'? |
390 def UnwrapArgExpression(name, type): | 390 def UnwrapArgExpression(name, type): |
391 # TODO: Type specific unwrapping. | 391 # TODO: Type specific unwrapping. |
392 return '__dom_unwrap(%s)' % (name) | 392 return '__dom_unwrap(%s)' % (name) |
393 | 393 |
394 def ArgNameAndUnwrapper(arg_info, overload_arg): | 394 def ArgNameAndUnwrapper(param_info, overload_arg): |
395 (name, type, value) = arg_info | 395 return (param_info.name, |
396 return (name, UnwrapArgExpression(name, type)) | 396 UnwrapArgExpression(param_info.name, param_info.dart_type)) |
397 | 397 |
398 names_and_unwrappers = [ArgNameAndUnwrapper(info.arg_infos[i], arg) | 398 names_and_unwrappers = [ArgNameAndUnwrapper(info.param_infos[i], arg) |
399 for (i, arg) in enumerate(operation.arguments)] | 399 for (i, arg) in enumerate(operation.arguments)] |
400 unwrap_args = [unwrap_arg for (_, unwrap_arg) in names_and_unwrappers] | 400 unwrap_args = [unwrap_arg for (_, unwrap_arg) in names_and_unwrappers] |
401 arg_names = [name for (name, _) in names_and_unwrappers] | 401 arg_names = [name for (name, _) in names_and_unwrappers] |
402 | 402 |
403 self._native_version += 1 | 403 self._native_version += 1 |
404 native_name = self._MethodName('_', info.name) | 404 native_name = self._MethodName('_', info.name) |
405 if self._native_version > 1: | 405 if self._native_version > 1: |
406 native_name = '%s_%s' % (native_name, self._native_version) | 406 native_name = '%s_%s' % (native_name, self._native_version) |
407 | 407 |
408 argument_expressions = ', '.join(['this'] + arg_names) | 408 argument_expressions = ', '.join(['this'] + arg_names) |
(...skipping 29 matching lines...) Expand all Loading... |
438 always dispatches. | 438 always dispatches. |
439 """ | 439 """ |
440 | 440 |
441 def NullCheck(name): | 441 def NullCheck(name): |
442 return '%s === null' % name | 442 return '%s === null' % name |
443 | 443 |
444 def TypeCheck(name, type): | 444 def TypeCheck(name, type): |
445 return '%s is %s' % (name, type) | 445 return '%s is %s' % (name, type) |
446 | 446 |
447 def ShouldGenerateSingleOperation(): | 447 def ShouldGenerateSingleOperation(): |
448 if position == len(info.arg_infos): | 448 if position == len(info.param_infos): |
449 if len(overloads) > 1: | 449 if len(overloads) > 1: |
450 raise Exception('Duplicate operations ' + str(overloads)) | 450 raise Exception('Duplicate operations ' + str(overloads)) |
451 return True | 451 return True |
452 | 452 |
453 # Check if we dispatch on RequiredCppParameter arguments. In this | 453 # Check if we dispatch on RequiredCppParameter arguments. In this |
454 # case all trailing arguments must be RequiredCppParameter and there | 454 # case all trailing arguments must be RequiredCppParameter and there |
455 # is no need in dispatch. | 455 # is no need in dispatch. |
456 # TODO(antonm): better diagnositics. | 456 # TODO(antonm): better diagnositics. |
457 if position >= len(overloads[0].arguments): | 457 if position >= len(overloads[0].arguments): |
458 def IsRequiredCppParameter(arg): | 458 def IsRequiredCppParameter(arg): |
(...skipping 14 matching lines...) Expand all Loading... |
473 return False | 473 return False |
474 | 474 |
475 # FIXME: Consider a simpler dispatch that iterates over the | 475 # FIXME: Consider a simpler dispatch that iterates over the |
476 # overloads and generates an overload specific check. Revisit | 476 # overloads and generates an overload specific check. Revisit |
477 # when we move to named optional arguments. | 477 # when we move to named optional arguments. |
478 | 478 |
479 # Partition the overloads to divide and conquer on the dispatch. | 479 # Partition the overloads to divide and conquer on the dispatch. |
480 positive = [] | 480 positive = [] |
481 negative = [] | 481 negative = [] |
482 first_overload = overloads[0] | 482 first_overload = overloads[0] |
483 (param_name, param_type, param_default) = info.arg_infos[position] | 483 param = info.param_infos[position] |
484 | 484 |
485 if position < len(first_overload.arguments): | 485 if position < len(first_overload.arguments): |
486 # FIXME: This will not work if the second overload has a more | 486 # FIXME: This will not work if the second overload has a more |
487 # precise type than the first. E.g., | 487 # precise type than the first. E.g., |
488 # void foo(Node x); | 488 # void foo(Node x); |
489 # void foo(Element x); | 489 # void foo(Element x); |
490 type = DartType(first_overload.arguments[position].type.id) | 490 type = DartType(first_overload.arguments[position].type.id) |
491 test = TypeCheck(param_name, type) | 491 test = TypeCheck(param.name, type) |
492 pred = lambda op: len(op.arguments) > position and DartType(op.arguments[p
osition].type.id) == type | 492 pred = lambda op: len(op.arguments) > position and DartType(op.arguments[p
osition].type.id) == type |
493 else: | 493 else: |
494 type = None | 494 type = None |
495 test = NullCheck(param_name) | 495 test = NullCheck(param.name) |
496 pred = lambda op: position >= len(op.arguments) | 496 pred = lambda op: position >= len(op.arguments) |
497 | 497 |
498 for overload in overloads: | 498 for overload in overloads: |
499 if pred(overload): | 499 if pred(overload): |
500 positive.append(overload) | 500 positive.append(overload) |
501 else: | 501 else: |
502 negative.append(overload) | 502 negative.append(overload) |
503 | 503 |
504 if positive and negative: | 504 if positive and negative: |
505 (true_code, false_code) = emitter.Emit( | 505 (true_code, false_code) = emitter.Emit( |
(...skipping 11 matching lines...) Expand all Loading... |
517 | 517 |
518 if negative: | 518 if negative: |
519 raise Exception('Internal error, must be all positive') | 519 raise Exception('Internal error, must be all positive') |
520 | 520 |
521 # All overloads require the same test. Do we bother? | 521 # All overloads require the same test. Do we bother? |
522 | 522 |
523 # If the test is the same as the method's formal parameter then checked mode | 523 # If the test is the same as the method's formal parameter then checked mode |
524 # will have done the test already. (It could be null too but we ignore that | 524 # will have done the test already. (It could be null too but we ignore that |
525 # case since all the overload behave the same and we don't know which types | 525 # case since all the overload behave the same and we don't know which types |
526 # in the IDL are not nullable.) | 526 # in the IDL are not nullable.) |
527 if type == param_type: | 527 if type == param.dart_type: |
528 return self.GenerateDispatch( | 528 return self.GenerateDispatch( |
529 emitter, info, indent, position + 1, positive) | 529 emitter, info, indent, position + 1, positive) |
530 | 530 |
531 # Otherwise the overloads have the same type but the type is a substype of | 531 # Otherwise the overloads have the same type but the type is a subtype of |
532 # the method's synthesized formal parameter. e.g we have overloads f(X) and | 532 # the method's synthesized formal parameter. e.g we have overloads f(X) and |
533 # f(Y), implemented by the synthesized method f(Z) where X<Z and Y<Z. The | 533 # f(Y), implemented by the synthesized method f(Z) where X<Z and Y<Z. The |
534 # dispatch has removed f(X), leaving only f(Y), but there is no guarantee | 534 # dispatch has removed f(X), leaving only f(Y), but there is no guarantee |
535 # that Y = Z-X, so we need to check for Y. | 535 # that Y = Z-X, so we need to check for Y. |
536 true_code = emitter.Emit( | 536 true_code = emitter.Emit( |
537 '$(INDENT)if ($COND) {\n' | 537 '$(INDENT)if ($COND) {\n' |
538 '$!TRUE' | 538 '$!TRUE' |
539 '$(INDENT)}\n', | 539 '$(INDENT)}\n', |
540 COND=test, INDENT=indent) | 540 COND=test, INDENT=indent) |
541 self.GenerateDispatch( | 541 self.GenerateDispatch( |
542 true_code, info, indent + ' ', position + 1, positive) | 542 true_code, info, indent + ' ', position + 1, positive) |
543 return True | 543 return True |
OLD | NEW |