| 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 |