| 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 native binding from the IDL database.""" | 7 native binding from the IDL database.""" |
| 8 | 8 |
| 9 import emitter | 9 import emitter |
| 10 import os | 10 import os |
| 11 import systemwrapping | |
| 12 from generator import * | 11 from generator import * |
| 13 from systembase import * | 12 from systembase import * |
| 14 | 13 |
| 15 class NativeImplementationSystem(System): | 14 class NativeImplementationSystem(System): |
| 16 | 15 |
| 17 def __init__(self, templates, database, emitters, auxiliary_dir, output_dir): | 16 def __init__(self, templates, database, emitters, auxiliary_dir, output_dir): |
| 18 super(NativeImplementationSystem, self).__init__( | 17 super(NativeImplementationSystem, self).__init__( |
| 19 templates, database, emitters, output_dir) | 18 templates, database, emitters, output_dir) |
| 20 | 19 |
| 21 self._auxiliary_dir = auxiliary_dir | 20 self._auxiliary_dir = auxiliary_dir |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 return os.path.join(self._output_dir, 'dart', | 198 return os.path.join(self._output_dir, 'dart', |
| 200 '%sFactoryProviderImplementation.dart' % interface_name) | 199 '%sFactoryProviderImplementation.dart' % interface_name) |
| 201 | 200 |
| 202 def _FilePathForCppHeader(self, interface_name): | 201 def _FilePathForCppHeader(self, interface_name): |
| 203 return os.path.join(self._output_dir, 'cpp', 'Dart%s.h' % interface_name) | 202 return os.path.join(self._output_dir, 'cpp', 'Dart%s.h' % interface_name) |
| 204 | 203 |
| 205 def _FilePathForCppImplementation(self, interface_name): | 204 def _FilePathForCppImplementation(self, interface_name): |
| 206 return os.path.join(self._output_dir, 'cpp', 'Dart%s.cpp' % interface_name) | 205 return os.path.join(self._output_dir, 'cpp', 'Dart%s.cpp' % interface_name) |
| 207 | 206 |
| 208 | 207 |
| 209 class NativeImplementationGenerator(systemwrapping.WrappingInterfaceGenerator): | 208 class NativeImplementationGenerator(object): |
| 210 """Generates Dart implementation for one DOM IDL interface.""" | 209 """Generates Dart implementation for one DOM IDL interface.""" |
| 211 | 210 |
| 212 def __init__(self, system, interface, | 211 def __init__(self, system, interface, |
| 213 dart_impl_emitter, cpp_header_emitter, cpp_impl_emitter, | 212 dart_impl_emitter, cpp_header_emitter, cpp_impl_emitter, |
| 214 base_members, templates): | 213 base_members, templates): |
| 215 """Generates Dart and C++ code for the given interface. | 214 """Generates Dart and C++ code for the given interface. |
| 216 | 215 |
| 217 Args: | 216 Args: |
| 218 system: The NativeImplementationSystem. | 217 system: The NativeImplementationSystem. |
| 219 interface: an IDLInterface instance. It is assumed that all types have | 218 interface: an IDLInterface instance. It is assumed that all types have |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 311 invocation = self._GenerateWebCoreInvocation(function_expression, arguments, | 310 invocation = self._GenerateWebCoreInvocation(function_expression, arguments, |
| 312 self._interface.id, self._interface.ext_attrs, raises_dom_exceptions) | 311 self._interface.id, self._interface.ext_attrs, raises_dom_exceptions) |
| 313 self._GenerateNativeCallback(callback_name='constructorCallback', | 312 self._GenerateNativeCallback(callback_name='constructorCallback', |
| 314 parameter_definitions=parameter_definitions_emitter.Fragments(), | 313 parameter_definitions=parameter_definitions_emitter.Fragments(), |
| 315 needs_receiver=False, invocation=invocation, | 314 needs_receiver=False, invocation=invocation, |
| 316 raises_exceptions=raises_exceptions) | 315 raises_exceptions=raises_exceptions) |
| 317 | 316 |
| 318 def _ImplClassName(self, interface_name): | 317 def _ImplClassName(self, interface_name): |
| 319 return interface_name + 'Implementation' | 318 return interface_name + 'Implementation' |
| 320 | 319 |
| 320 def _BaseClassName(self): |
| 321 if not self._interface.parents: |
| 322 return 'DOMWrapperBase' |
| 323 |
| 324 supertype = self._interface.parents[0].type.id |
| 325 |
| 326 # FIXME: We're currently injecting List<..> and EventTarget as |
| 327 # supertypes in dart.idl. We should annotate/preserve as |
| 328 # attributes instead. For now, this hack lets the self._interfaces |
| 329 # inherit, but not the classes. |
| 330 # List methods are injected in AddIndexer. |
| 331 if IsDartListType(supertype) or IsDartCollectionType(supertype): |
| 332 return 'DOMWrapperBase' |
| 333 |
| 334 if supertype == 'EventTarget': |
| 335 # Most implementors of EventTarget specify the EventListener operations |
| 336 # again. If the operations are not specified, try to inherit from the |
| 337 # EventTarget implementation. |
| 338 # |
| 339 # Applies to MessagePort. |
| 340 if not [op for op in self._interface.operations if op.id == 'addEventListe
ner']: |
| 341 return self._ImplClassName(supertype) |
| 342 return 'DOMWrapperBase' |
| 343 |
| 344 return self._ImplClassName(supertype) |
| 345 |
| 321 def _IsConstructable(self): | 346 def _IsConstructable(self): |
| 322 # FIXME: support ConstructorTemplate. | 347 # FIXME: support ConstructorTemplate. |
| 323 return set(['CustomConstructor', 'V8CustomConstructor', 'Constructor', 'Name
dConstructor']) & set(self._interface.ext_attrs) | 348 return set(['CustomConstructor', 'V8CustomConstructor', 'Constructor', 'Name
dConstructor']) & set(self._interface.ext_attrs) |
| 324 | 349 |
| 325 def _EmitFactoryProvider(self, interface_name, constructor_info): | 350 def _EmitFactoryProvider(self, interface_name, constructor_info): |
| 326 factory_provider = '_' + interface_name + 'FactoryProvider' | 351 factory_provider = '_' + interface_name + 'FactoryProvider' |
| 327 implementation_class = interface_name + 'FactoryProviderImplementation' | 352 implementation_class = interface_name + 'FactoryProviderImplementation' |
| 328 implementation_function = 'create' + interface_name | 353 implementation_function = 'create' + interface_name |
| 329 native_implementation_function = '%s_constructor_Callback' % interface_name | 354 native_implementation_function = '%s_constructor_Callback' % interface_name |
| 330 | 355 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 358 ' static $INTERFACE_NAME $IMPL_FUNCTION($PARAMETERS)\n' | 383 ' static $INTERFACE_NAME $IMPL_FUNCTION($PARAMETERS)\n' |
| 359 ' native "$NATIVE_NAME";\n' | 384 ' native "$NATIVE_NAME";\n' |
| 360 '}', | 385 '}', |
| 361 INTERFACE_NAME=interface_name, | 386 INTERFACE_NAME=interface_name, |
| 362 PARAMETERS=constructor_info.ParametersImplementationDeclaration(), | 387 PARAMETERS=constructor_info.ParametersImplementationDeclaration(), |
| 363 IMPL_CLASS=implementation_class, | 388 IMPL_CLASS=implementation_class, |
| 364 IMPL_FUNCTION=implementation_function, | 389 IMPL_FUNCTION=implementation_function, |
| 365 NATIVE_NAME=native_implementation_function) | 390 NATIVE_NAME=native_implementation_function) |
| 366 | 391 |
| 367 def FinishInterface(self): | 392 def FinishInterface(self): |
| 368 base = self._BaseClassName(self._interface) | 393 base = self._BaseClassName() |
| 369 self._dart_impl_emitter.Emit( | 394 self._dart_impl_emitter.Emit( |
| 370 self._templates.Load('dart_implementation.darttemplate'), | 395 self._templates.Load('dart_implementation.darttemplate'), |
| 371 CLASS=self._class_name, BASE=base, INTERFACE=self._interface.id, | 396 CLASS=self._class_name, BASE=base, INTERFACE=self._interface.id, |
| 372 MEMBERS=self._members_emitter.Fragments()) | 397 MEMBERS=self._members_emitter.Fragments()) |
| 373 | 398 |
| 374 self._GenerateCppHeader() | 399 self._GenerateCppHeader() |
| 375 | 400 |
| 376 self._cpp_impl_emitter.Emit( | 401 self._cpp_impl_emitter.Emit( |
| 377 self._templates.Load('cpp_implementation.template'), | 402 self._templates.Load('cpp_implementation.template'), |
| 378 INTERFACE=self._interface.id, | 403 INTERFACE=self._interface.id, |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 451 ' goto fail;\n' | 476 ' goto fail;\n' |
| 452 ' RefPtr<ScriptCallStack> scriptCallStack(DartUtilities::create
ScriptCallStack());\n' | 477 ' RefPtr<ScriptCallStack> scriptCallStack(DartUtilities::create
ScriptCallStack());\n' |
| 453 ' if (!scriptCallStack->size())\n' | 478 ' if (!scriptCallStack->size())\n' |
| 454 ' return;\n', | 479 ' return;\n', |
| 455 INDEX=len(node.arguments)) | 480 INDEX=len(node.arguments)) |
| 456 arguments.extend(['scriptArguments', 'scriptCallStack']) | 481 arguments.extend(['scriptArguments', 'scriptCallStack']) |
| 457 return True | 482 return True |
| 458 | 483 |
| 459 return False | 484 return False |
| 460 | 485 |
| 486 def AddConstant(self, constant): |
| 487 # Constants are already defined on the interface. |
| 488 pass |
| 489 |
| 461 def AddAttribute(self, getter, setter): | 490 def AddAttribute(self, getter, setter): |
| 462 if 'CheckSecurityForNode' in (getter or setter).ext_attrs: | 491 if 'CheckSecurityForNode' in (getter or setter).ext_attrs: |
| 463 # FIXME: exclude from interface as well. | 492 # FIXME: exclude from interface as well. |
| 464 return | 493 return |
| 465 | 494 |
| 466 if getter: | 495 if getter: |
| 467 self._AddGetter(getter) | 496 self._AddGetter(getter) |
| 468 if setter: | 497 if setter: |
| 469 self._AddSetter(setter) | 498 self._AddSetter(setter) |
| 470 | 499 |
| 500 def AddSecondaryAttribute(self, interface, getter, setter): |
| 501 self.AddAttribute(getter, setter) |
| 502 |
| 471 def _AddGetter(self, attr): | 503 def _AddGetter(self, attr): |
| 472 type_info = GetIDLTypeInfo(attr.type.id) | 504 type_info = GetIDLTypeInfo(attr.type.id) |
| 473 dart_declaration = '%s get %s()' % ( | 505 dart_declaration = '%s get %s()' % ( |
| 474 type_info.dart_type(), DartDomNameOfAttribute(attr)) | 506 type_info.dart_type(), DartDomNameOfAttribute(attr)) |
| 475 is_custom = 'Custom' in attr.ext_attrs or 'CustomGetter' in attr.ext_attrs | 507 is_custom = 'Custom' in attr.ext_attrs or 'CustomGetter' in attr.ext_attrs |
| 476 cpp_callback_name = self._GenerateNativeBinding(attr.id, 1, | 508 cpp_callback_name = self._GenerateNativeBinding(attr.id, 1, |
| 477 dart_declaration, 'Getter', is_custom) | 509 dart_declaration, 'Getter', is_custom) |
| 478 if is_custom: | 510 if is_custom: |
| 479 return | 511 return |
| 480 | 512 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 542 arguments.append(argument_expression) | 574 arguments.append(argument_expression) |
| 543 | 575 |
| 544 parameter_definitions = parameter_definitions_emitter.Fragments() | 576 parameter_definitions = parameter_definitions_emitter.Fragments() |
| 545 function_expression = self._GenerateWebCoreFunctionExpression(webcore_functi
on_name, attr) | 577 function_expression = self._GenerateWebCoreFunctionExpression(webcore_functi
on_name, attr) |
| 546 invocation = self._GenerateWebCoreInvocation(function_expression, | 578 invocation = self._GenerateWebCoreInvocation(function_expression, |
| 547 arguments, 'void', attr.ext_attrs, attr.set_raises) | 579 arguments, 'void', attr.ext_attrs, attr.set_raises) |
| 548 | 580 |
| 549 self._GenerateNativeCallback(cpp_callback_name, parameter_definitions_emitte
r.Fragments(), | 581 self._GenerateNativeCallback(cpp_callback_name, parameter_definitions_emitte
r.Fragments(), |
| 550 True, invocation, raises_exceptions=True) | 582 True, invocation, raises_exceptions=True) |
| 551 | 583 |
| 552 def _HasNativeIndexGetter(self, interface): | 584 def AddIndexer(self, element_type): |
| 553 return ('CustomIndexedGetter' in interface.ext_attrs or | 585 """Adds all the methods required to complete implementation of List.""" |
| 554 'NumericIndexedGetter' in interface.ext_attrs) | 586 # We would like to simply inherit the implementation of everything except |
| 587 # get length(), [], and maybe []=. It is possible to extend from a base |
| 588 # array implementation class only when there is no other implementation |
| 589 # inheritance. There might be no implementation inheritance other than |
| 590 # DOMBaseWrapper for many classes, but there might be some where the |
| 591 # array-ness is introduced by a non-root interface: |
| 592 # |
| 593 # interface Y extends X, List<T> ... |
| 594 # |
| 595 # In the non-root case we have to choose between: |
| 596 # |
| 597 # class YImpl extends XImpl { add List<T> methods; } |
| 598 # |
| 599 # and |
| 600 # |
| 601 # class YImpl extends ListBase<T> { copies of transitive XImpl methods; } |
| 602 # |
| 603 dart_element_type = DartType(element_type) |
| 604 if ('CustomIndexedGetter' in self._interface.ext_attrs or |
| 605 'NumericIndexedGetter' in self._interface.ext_attrs): |
| 606 self._EmitNativeIndexGetter(dart_element_type) |
| 607 else: |
| 608 self._members_emitter.Emit( |
| 609 '\n' |
| 610 ' $TYPE operator[](int index) {\n' |
| 611 ' return item(index);\n' |
| 612 ' }\n', |
| 613 TYPE=dart_element_type) |
| 555 | 614 |
| 556 def _EmitNativeIndexGetter(self, interface, element_type): | 615 if 'CustomIndexedSetter' in self._interface.ext_attrs: |
| 616 self._EmitNativeIndexSetter(dart_element_type) |
| 617 else: |
| 618 self._members_emitter.Emit( |
| 619 '\n' |
| 620 ' void operator[]=(int index, $TYPE value) {\n' |
| 621 ' throw new UnsupportedOperationException("Cannot assign element of
immutable List.");\n' |
| 622 ' }\n', |
| 623 TYPE=dart_element_type) |
| 624 |
| 625 self._members_emitter.Emit( |
| 626 '\n' |
| 627 ' void add($TYPE value) {\n' |
| 628 ' throw new UnsupportedOperationException("Cannot add to immutable Li
st.");\n' |
| 629 ' }\n' |
| 630 '\n' |
| 631 ' void addLast($TYPE value) {\n' |
| 632 ' throw new UnsupportedOperationException("Cannot add to immutable Li
st.");\n' |
| 633 ' }\n' |
| 634 '\n' |
| 635 ' void addAll(Collection<$TYPE> collection) {\n' |
| 636 ' throw new UnsupportedOperationException("Cannot add to immutable Li
st.");\n' |
| 637 ' }\n' |
| 638 '\n' |
| 639 ' void sort(int compare($TYPE a, $TYPE b)) {\n' |
| 640 ' throw new UnsupportedOperationException("Cannot sort immutable List
.");\n' |
| 641 ' }\n' |
| 642 '\n' |
| 643 ' void copyFrom(List<Object> src, int srcStart, ' |
| 644 'int dstStart, int count) {\n' |
| 645 ' throw new UnsupportedOperationException("This object is immutable."
);\n' |
| 646 ' }\n' |
| 647 '\n' |
| 648 ' int indexOf($TYPE element, [int start = 0]) {\n' |
| 649 ' return _Lists.indexOf(this, element, start, this.length);\n' |
| 650 ' }\n' |
| 651 '\n' |
| 652 ' int lastIndexOf($TYPE element, [int start = null]) {\n' |
| 653 ' if (start === null) start = length - 1;\n' |
| 654 ' return _Lists.lastIndexOf(this, element, start);\n' |
| 655 ' }\n' |
| 656 '\n' |
| 657 ' int clear() {\n' |
| 658 ' throw new UnsupportedOperationException("Cannot clear immutable Lis
t.");\n' |
| 659 ' }\n' |
| 660 '\n' |
| 661 ' $TYPE removeLast() {\n' |
| 662 ' throw new UnsupportedOperationException("Cannot removeLast on immut
able List.");\n' |
| 663 ' }\n' |
| 664 '\n' |
| 665 ' $TYPE last() {\n' |
| 666 ' return this[length - 1];\n' |
| 667 ' }\n' |
| 668 '\n' |
| 669 ' void forEach(void f($TYPE element)) {\n' |
| 670 ' _Collections.forEach(this, f);\n' |
| 671 ' }\n' |
| 672 '\n' |
| 673 ' Collection map(f($TYPE element)) {\n' |
| 674 ' return _Collections.map(this, [], f);\n' |
| 675 ' }\n' |
| 676 '\n' |
| 677 ' Collection<$TYPE> filter(bool f($TYPE element)) {\n' |
| 678 ' return _Collections.filter(this, new List<$TYPE>(), f);\n' |
| 679 ' }\n' |
| 680 '\n' |
| 681 ' bool every(bool f($TYPE element)) {\n' |
| 682 ' return _Collections.every(this, f);\n' |
| 683 ' }\n' |
| 684 '\n' |
| 685 ' bool some(bool f($TYPE element)) {\n' |
| 686 ' return _Collections.some(this, f);\n' |
| 687 ' }\n' |
| 688 '\n' |
| 689 ' void setRange(int start, int length, List<$TYPE> from, [int startFrom
]) {\n' |
| 690 ' throw new UnsupportedOperationException("Cannot setRange on immutab
le List.");\n' |
| 691 ' }\n' |
| 692 '\n' |
| 693 ' void removeRange(int start, int length) {\n' |
| 694 ' throw new UnsupportedOperationException("Cannot removeRange on immu
table List.");\n' |
| 695 ' }\n' |
| 696 '\n' |
| 697 ' void insertRange(int start, int length, [$TYPE initialValue]) {\n' |
| 698 ' throw new UnsupportedOperationException("Cannot insertRange on immu
table List.");\n' |
| 699 ' }\n' |
| 700 '\n' |
| 701 ' List<$TYPE> getRange(int start, int length) {\n' |
| 702 ' throw new NotImplementedException();\n' |
| 703 ' }\n' |
| 704 '\n' |
| 705 ' bool isEmpty() {\n' |
| 706 ' return length == 0;\n' |
| 707 ' }\n' |
| 708 '\n' |
| 709 ' Iterator<$TYPE> iterator() {\n' |
| 710 ' return new _FixedSizeListIterator<$TYPE>(this);\n' |
| 711 ' }\n', |
| 712 TYPE=dart_element_type) |
| 713 |
| 714 def _EmitNativeIndexGetter(self, element_type): |
| 557 dart_declaration = '%s operator[](int index)' % element_type | 715 dart_declaration = '%s operator[](int index)' % element_type |
| 558 self._GenerateNativeBinding('numericIndexGetter', 2, dart_declaration, | 716 self._GenerateNativeBinding('numericIndexGetter', 2, dart_declaration, |
| 559 'Callback', True) | 717 'Callback', True) |
| 560 | 718 |
| 561 def _EmitNativeIndexSetter(self, interface, element_type): | 719 def _EmitNativeIndexSetter(self, element_type): |
| 562 dart_declaration = 'void operator[]=(int index, %s value)' % element_type | 720 dart_declaration = 'void operator[]=(int index, %s value)' % element_type |
| 563 self._GenerateNativeBinding('numericIndexSetter', 3, dart_declaration, | 721 self._GenerateNativeBinding('numericIndexSetter', 3, dart_declaration, |
| 564 'Callback', True) | 722 'Callback', True) |
| 565 | 723 |
| 566 def _AddOperation(self, info): | 724 def _AddOperation(self, info): |
| 567 """ | 725 """ |
| 568 Arguments: | 726 Arguments: |
| 569 info: An OperationInfo object. | 727 info: An OperationInfo object. |
| 570 """ | 728 """ |
| 571 | 729 |
| (...skipping 24 matching lines...) Expand all Loading... |
| 596 | 754 |
| 597 # Process in order of ascending number of arguments to ensure missing | 755 # Process in order of ascending number of arguments to ensure missing |
| 598 # optional arguments are processed early. | 756 # optional arguments are processed early. |
| 599 overloads = sorted(info.overloads, | 757 overloads = sorted(info.overloads, |
| 600 key=lambda overload: len(overload.arguments)) | 758 key=lambda overload: len(overload.arguments)) |
| 601 self._native_version = 0 | 759 self._native_version = 0 |
| 602 fallthrough = self.GenerateDispatch(body, info, ' ', 0, overloads) | 760 fallthrough = self.GenerateDispatch(body, info, ' ', 0, overloads) |
| 603 if fallthrough: | 761 if fallthrough: |
| 604 body.Emit(' throw "Incorrect number or type of arguments";\n'); | 762 body.Emit(' throw "Incorrect number or type of arguments";\n'); |
| 605 | 763 |
| 764 def GenerateDispatch(self, emitter, info, indent, position, overloads): |
| 765 """Generates a dispatch to one of the overloads. |
| 766 |
| 767 Arguments: |
| 768 emitter: an Emitter for the body of a block of code. |
| 769 info: the compound information about the operation and its overloads. |
| 770 indent: an indentation string for generated code. |
| 771 position: the index of the parameter to dispatch on. |
| 772 overloads: a list of the remaining IDLOperations to dispatch. |
| 773 |
| 774 Returns True if the dispatch can fall through on failure, False if the code |
| 775 always dispatches. |
| 776 """ |
| 777 |
| 778 def NullCheck(name): |
| 779 return '%s === null' % name |
| 780 |
| 781 def TypeCheck(name, type): |
| 782 return '%s is %s' % (name, type) |
| 783 |
| 784 def ShouldGenerateSingleOperation(): |
| 785 if position == len(info.param_infos): |
| 786 if len(overloads) > 1: |
| 787 raise Exception('Duplicate operations ' + str(overloads)) |
| 788 return True |
| 789 |
| 790 # Check if we dispatch on RequiredCppParameter arguments. In this |
| 791 # case all trailing arguments must be RequiredCppParameter and there |
| 792 # is no need in dispatch. |
| 793 # TODO(antonm): better diagnositics. |
| 794 if position >= len(overloads[0].arguments): |
| 795 def IsRequiredCppParameter(arg): |
| 796 return 'RequiredCppParameter' in arg.ext_attrs |
| 797 last_overload = overloads[-1] |
| 798 if (len(last_overload.arguments) > position and |
| 799 IsRequiredCppParameter(last_overload.arguments[position])): |
| 800 for overload in overloads: |
| 801 args = overload.arguments[position:] |
| 802 if not all([IsRequiredCppParameter(arg) for arg in args]): |
| 803 raise Exception('Invalid overload for RequiredCppParameter') |
| 804 return True |
| 805 |
| 806 return False |
| 807 |
| 808 if ShouldGenerateSingleOperation(): |
| 809 self.GenerateSingleOperation(emitter, info, indent, overloads[-1]) |
| 810 return False |
| 811 |
| 812 # FIXME: Consider a simpler dispatch that iterates over the |
| 813 # overloads and generates an overload specific check. Revisit |
| 814 # when we move to named optional arguments. |
| 815 |
| 816 # Partition the overloads to divide and conquer on the dispatch. |
| 817 positive = [] |
| 818 negative = [] |
| 819 first_overload = overloads[0] |
| 820 param = info.param_infos[position] |
| 821 |
| 822 if position < len(first_overload.arguments): |
| 823 # FIXME: This will not work if the second overload has a more |
| 824 # precise type than the first. E.g., |
| 825 # void foo(Node x); |
| 826 # void foo(Element x); |
| 827 type = DartType(first_overload.arguments[position].type.id) |
| 828 test = TypeCheck(param.name, type) |
| 829 pred = lambda op: len(op.arguments) > position and DartType(op.arguments[p
osition].type.id) == type |
| 830 else: |
| 831 type = None |
| 832 test = NullCheck(param.name) |
| 833 pred = lambda op: position >= len(op.arguments) |
| 834 |
| 835 for overload in overloads: |
| 836 if pred(overload): |
| 837 positive.append(overload) |
| 838 else: |
| 839 negative.append(overload) |
| 840 |
| 841 if positive and negative: |
| 842 (true_code, false_code) = emitter.Emit( |
| 843 '$(INDENT)if ($COND) {\n' |
| 844 '$!TRUE' |
| 845 '$(INDENT)} else {\n' |
| 846 '$!FALSE' |
| 847 '$(INDENT)}\n', |
| 848 COND=test, INDENT=indent) |
| 849 fallthrough1 = self.GenerateDispatch( |
| 850 true_code, info, indent + ' ', position + 1, positive) |
| 851 fallthrough2 = self.GenerateDispatch( |
| 852 false_code, info, indent + ' ', position, negative) |
| 853 return fallthrough1 or fallthrough2 |
| 854 |
| 855 if negative: |
| 856 raise Exception('Internal error, must be all positive') |
| 857 |
| 858 # All overloads require the same test. Do we bother? |
| 859 |
| 860 # If the test is the same as the method's formal parameter then checked mode |
| 861 # will have done the test already. (It could be null too but we ignore that |
| 862 # case since all the overload behave the same and we don't know which types |
| 863 # in the IDL are not nullable.) |
| 864 if type == param.dart_type: |
| 865 return self.GenerateDispatch( |
| 866 emitter, info, indent, position + 1, positive) |
| 867 |
| 868 # Otherwise the overloads have the same type but the type is a subtype of |
| 869 # the method's synthesized formal parameter. e.g we have overloads f(X) and |
| 870 # f(Y), implemented by the synthesized method f(Z) where X<Z and Y<Z. The |
| 871 # dispatch has removed f(X), leaving only f(Y), but there is no guarantee |
| 872 # that Y = Z-X, so we need to check for Y. |
| 873 true_code = emitter.Emit( |
| 874 '$(INDENT)if ($COND) {\n' |
| 875 '$!TRUE' |
| 876 '$(INDENT)}\n', |
| 877 COND=test, INDENT=indent) |
| 878 self.GenerateDispatch( |
| 879 true_code, info, indent + ' ', position + 1, positive) |
| 880 return True |
| 881 |
| 606 def AddOperation(self, info): | 882 def AddOperation(self, info): |
| 607 self._AddOperation(info) | 883 self._AddOperation(info) |
| 608 | 884 |
| 609 def AddStaticOperation(self, info): | 885 def AddStaticOperation(self, info): |
| 610 self._AddOperation(info) | 886 self._AddOperation(info) |
| 611 | 887 |
| 888 def AddSecondaryOperation(self, interface, info): |
| 889 self.AddOperation(info) |
| 890 |
| 612 def GenerateSingleOperation(self, dispatch_emitter, info, indent, operation): | 891 def GenerateSingleOperation(self, dispatch_emitter, info, indent, operation): |
| 613 """Generates a call to a single operation. | 892 """Generates a call to a single operation. |
| 614 | 893 |
| 615 Arguments: | 894 Arguments: |
| 616 dispatch_emitter: an dispatch_emitter for the body of a block of code. | 895 dispatch_emitter: an dispatch_emitter for the body of a block of code. |
| 617 info: the compound information about the operation and its overloads. | 896 info: the compound information about the operation and its overloads. |
| 618 indent: an indentation string for generated code. | 897 indent: an indentation string for generated code. |
| 619 operation: the IDLOperation to call. | 898 operation: the IDLOperation to call. |
| 620 """ | 899 """ |
| 621 | 900 |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 842 def _InstanceOfNode(database, interface): | 1121 def _InstanceOfNode(database, interface): |
| 843 if interface.id == 'Node': | 1122 if interface.id == 'Node': |
| 844 return True | 1123 return True |
| 845 for parent in interface.parents: | 1124 for parent in interface.parents: |
| 846 if not database.HasInterface(parent.type.id): | 1125 if not database.HasInterface(parent.type.id): |
| 847 continue | 1126 continue |
| 848 parent_interface = database.GetInterface(parent.type.id) | 1127 parent_interface = database.GetInterface(parent.type.id) |
| 849 if _InstanceOfNode(database, parent_interface): | 1128 if _InstanceOfNode(database, parent_interface): |
| 850 return True | 1129 return True |
| 851 return False | 1130 return False |
| OLD | NEW |