Chromium Code Reviews| 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 dart_declaration = '%s operator[](int index)' % dart_element_type | |
|
Anton Muhin
2012/05/11 11:54:32
let's not inline _EmitNativeIndex{G,S}etter
podivilov
2012/05/11 14:18:38
Done.
| |
| 607 self._GenerateNativeBinding('numericIndexGetter', 2, dart_declaration, | |
| 608 'Callback', True) | |
| 609 else: | |
| 610 self._members_emitter.Emit( | |
| 611 '\n' | |
| 612 ' $TYPE operator[](int index) {\n' | |
| 613 ' return item(index);\n' | |
| 614 ' }\n', | |
| 615 TYPE=dart_element_type) | |
| 555 | 616 |
| 556 def _EmitNativeIndexGetter(self, interface, element_type): | 617 if 'CustomIndexedSetter' in self._interface.ext_attrs: |
| 557 dart_declaration = '%s operator[](int index)' % element_type | 618 dart_declaration = 'void operator[]=(int index, %s value)' % dart_element_ type |
| 558 self._GenerateNativeBinding('numericIndexGetter', 2, dart_declaration, | 619 self._GenerateNativeBinding('numericIndexSetter', 3, dart_declaration, |
| 559 'Callback', True) | 620 'Callback', True) |
| 621 else: | |
| 622 self._members_emitter.Emit( | |
| 623 '\n' | |
| 624 ' void operator[]=(int index, $TYPE value) {\n' | |
| 625 ' throw new UnsupportedOperationException("Cannot assign element of immutable List.");\n' | |
| 626 ' }\n', | |
| 627 TYPE=dart_element_type) | |
| 560 | 628 |
| 561 def _EmitNativeIndexSetter(self, interface, element_type): | 629 self._members_emitter.Emit( |
| 562 dart_declaration = 'void operator[]=(int index, %s value)' % element_type | 630 '\n' |
| 563 self._GenerateNativeBinding('numericIndexSetter', 3, dart_declaration, | 631 ' void add($TYPE value) {\n' |
| 564 'Callback', True) | 632 ' throw new UnsupportedOperationException("Cannot add to immutable Li st.");\n' |
| 633 ' }\n' | |
| 634 '\n' | |
| 635 ' void addLast($TYPE value) {\n' | |
| 636 ' throw new UnsupportedOperationException("Cannot add to immutable Li st.");\n' | |
| 637 ' }\n' | |
| 638 '\n' | |
| 639 ' void addAll(Collection<$TYPE> collection) {\n' | |
| 640 ' throw new UnsupportedOperationException("Cannot add to immutable Li st.");\n' | |
| 641 ' }\n' | |
| 642 '\n' | |
| 643 ' void sort(int compare($TYPE a, $TYPE b)) {\n' | |
| 644 ' throw new UnsupportedOperationException("Cannot sort immutable List .");\n' | |
| 645 ' }\n' | |
| 646 '\n' | |
| 647 ' void copyFrom(List<Object> src, int srcStart, ' | |
| 648 'int dstStart, int count) {\n' | |
| 649 ' throw new UnsupportedOperationException("This object is immutable." );\n' | |
| 650 ' }\n' | |
| 651 '\n' | |
| 652 ' int indexOf($TYPE element, [int start = 0]) {\n' | |
| 653 ' return _Lists.indexOf(this, element, start, this.length);\n' | |
| 654 ' }\n' | |
| 655 '\n' | |
| 656 ' int lastIndexOf($TYPE element, [int start = null]) {\n' | |
| 657 ' if (start === null) start = length - 1;\n' | |
| 658 ' return _Lists.lastIndexOf(this, element, start);\n' | |
| 659 ' }\n' | |
| 660 '\n' | |
| 661 ' int clear() {\n' | |
| 662 ' throw new UnsupportedOperationException("Cannot clear immutable Lis t.");\n' | |
| 663 ' }\n' | |
| 664 '\n' | |
| 665 ' $TYPE removeLast() {\n' | |
| 666 ' throw new UnsupportedOperationException("Cannot removeLast on immut able List.");\n' | |
| 667 ' }\n' | |
| 668 '\n' | |
| 669 ' $TYPE last() {\n' | |
| 670 ' return this[length - 1];\n' | |
| 671 ' }\n' | |
| 672 '\n' | |
| 673 ' void forEach(void f($TYPE element)) {\n' | |
| 674 ' _Collections.forEach(this, f);\n' | |
| 675 ' }\n' | |
| 676 '\n' | |
| 677 ' Collection map(f($TYPE element)) {\n' | |
| 678 ' return _Collections.map(this, [], f);\n' | |
| 679 ' }\n' | |
| 680 '\n' | |
| 681 ' Collection<$TYPE> filter(bool f($TYPE element)) {\n' | |
| 682 ' return _Collections.filter(this, new List<$TYPE>(), f);\n' | |
| 683 ' }\n' | |
| 684 '\n' | |
| 685 ' bool every(bool f($TYPE element)) {\n' | |
| 686 ' return _Collections.every(this, f);\n' | |
| 687 ' }\n' | |
| 688 '\n' | |
| 689 ' bool some(bool f($TYPE element)) {\n' | |
| 690 ' return _Collections.some(this, f);\n' | |
| 691 ' }\n' | |
| 692 '\n' | |
| 693 ' void setRange(int start, int length, List<$TYPE> from, [int startFrom ]) {\n' | |
| 694 ' throw new UnsupportedOperationException("Cannot setRange on immutab le List.");\n' | |
| 695 ' }\n' | |
| 696 '\n' | |
| 697 ' void removeRange(int start, int length) {\n' | |
| 698 ' throw new UnsupportedOperationException("Cannot removeRange on immu table List.");\n' | |
| 699 ' }\n' | |
| 700 '\n' | |
| 701 ' void insertRange(int start, int length, [$TYPE initialValue]) {\n' | |
| 702 ' throw new UnsupportedOperationException("Cannot insertRange on immu table List.");\n' | |
| 703 ' }\n' | |
| 704 '\n' | |
| 705 ' List<$TYPE> getRange(int start, int length) {\n' | |
| 706 ' throw new NotImplementedException();\n' | |
| 707 ' }\n' | |
| 708 '\n' | |
| 709 ' bool isEmpty() {\n' | |
| 710 ' return length == 0;\n' | |
| 711 ' }\n' | |
| 712 '\n' | |
| 713 ' Iterator<$TYPE> iterator() {\n' | |
| 714 ' return new _FixedSizeListIterator<$TYPE>(this);\n' | |
| 715 ' }\n', | |
| 716 TYPE=dart_element_type) | |
| 565 | 717 |
| 566 def _AddOperation(self, info): | 718 def _AddOperation(self, info): |
| 567 """ | 719 """ |
| 568 Arguments: | 720 Arguments: |
| 569 info: An OperationInfo object. | 721 info: An OperationInfo object. |
| 570 """ | 722 """ |
| 571 | 723 |
| 572 if 'CheckSecurityForNode' in info.overloads[0].ext_attrs: | 724 if 'CheckSecurityForNode' in info.overloads[0].ext_attrs: |
| 573 # FIXME: exclude from interface as well. | 725 # FIXME: exclude from interface as well. |
| 574 return | 726 return |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 596 | 748 |
| 597 # Process in order of ascending number of arguments to ensure missing | 749 # Process in order of ascending number of arguments to ensure missing |
| 598 # optional arguments are processed early. | 750 # optional arguments are processed early. |
| 599 overloads = sorted(info.overloads, | 751 overloads = sorted(info.overloads, |
| 600 key=lambda overload: len(overload.arguments)) | 752 key=lambda overload: len(overload.arguments)) |
| 601 self._native_version = 0 | 753 self._native_version = 0 |
| 602 fallthrough = self.GenerateDispatch(body, info, ' ', 0, overloads) | 754 fallthrough = self.GenerateDispatch(body, info, ' ', 0, overloads) |
| 603 if fallthrough: | 755 if fallthrough: |
| 604 body.Emit(' throw "Incorrect number or type of arguments";\n'); | 756 body.Emit(' throw "Incorrect number or type of arguments";\n'); |
| 605 | 757 |
| 758 def GenerateDispatch(self, emitter, info, indent, position, overloads): | |
| 759 """Generates a dispatch to one of the overloads. | |
| 760 | |
| 761 Arguments: | |
| 762 emitter: an Emitter for the body of a block of code. | |
| 763 info: the compound information about the operation and its overloads. | |
| 764 indent: an indentation string for generated code. | |
| 765 position: the index of the parameter to dispatch on. | |
| 766 overloads: a list of the remaining IDLOperations to dispatch. | |
| 767 | |
| 768 Returns True if the dispatch can fall through on failure, False if the code | |
| 769 always dispatches. | |
| 770 """ | |
| 771 | |
| 772 def NullCheck(name): | |
| 773 return '%s === null' % name | |
| 774 | |
| 775 def TypeCheck(name, type): | |
| 776 return '%s is %s' % (name, type) | |
| 777 | |
| 778 def ShouldGenerateSingleOperation(): | |
| 779 if position == len(info.param_infos): | |
| 780 if len(overloads) > 1: | |
| 781 raise Exception('Duplicate operations ' + str(overloads)) | |
| 782 return True | |
| 783 | |
| 784 # Check if we dispatch on RequiredCppParameter arguments. In this | |
| 785 # case all trailing arguments must be RequiredCppParameter and there | |
| 786 # is no need in dispatch. | |
| 787 # TODO(antonm): better diagnositics. | |
| 788 if position >= len(overloads[0].arguments): | |
| 789 def IsRequiredCppParameter(arg): | |
| 790 return 'RequiredCppParameter' in arg.ext_attrs | |
| 791 last_overload = overloads[-1] | |
| 792 if (len(last_overload.arguments) > position and | |
| 793 IsRequiredCppParameter(last_overload.arguments[position])): | |
| 794 for overload in overloads: | |
| 795 args = overload.arguments[position:] | |
| 796 if not all([IsRequiredCppParameter(arg) for arg in args]): | |
| 797 raise Exception('Invalid overload for RequiredCppParameter') | |
| 798 return True | |
| 799 | |
| 800 return False | |
| 801 | |
| 802 if ShouldGenerateSingleOperation(): | |
| 803 self.GenerateSingleOperation(emitter, info, indent, overloads[-1]) | |
| 804 return False | |
| 805 | |
| 806 # FIXME: Consider a simpler dispatch that iterates over the | |
| 807 # overloads and generates an overload specific check. Revisit | |
| 808 # when we move to named optional arguments. | |
| 809 | |
| 810 # Partition the overloads to divide and conquer on the dispatch. | |
| 811 positive = [] | |
| 812 negative = [] | |
| 813 first_overload = overloads[0] | |
| 814 param = info.param_infos[position] | |
| 815 | |
| 816 if position < len(first_overload.arguments): | |
| 817 # FIXME: This will not work if the second overload has a more | |
| 818 # precise type than the first. E.g., | |
| 819 # void foo(Node x); | |
| 820 # void foo(Element x); | |
| 821 type = DartType(first_overload.arguments[position].type.id) | |
| 822 test = TypeCheck(param.name, type) | |
| 823 pred = lambda op: len(op.arguments) > position and DartType(op.arguments[p osition].type.id) == type | |
| 824 else: | |
| 825 type = None | |
| 826 test = NullCheck(param.name) | |
| 827 pred = lambda op: position >= len(op.arguments) | |
| 828 | |
| 829 for overload in overloads: | |
| 830 if pred(overload): | |
| 831 positive.append(overload) | |
| 832 else: | |
| 833 negative.append(overload) | |
| 834 | |
| 835 if positive and negative: | |
| 836 (true_code, false_code) = emitter.Emit( | |
| 837 '$(INDENT)if ($COND) {\n' | |
| 838 '$!TRUE' | |
| 839 '$(INDENT)} else {\n' | |
| 840 '$!FALSE' | |
| 841 '$(INDENT)}\n', | |
| 842 COND=test, INDENT=indent) | |
| 843 fallthrough1 = self.GenerateDispatch( | |
| 844 true_code, info, indent + ' ', position + 1, positive) | |
| 845 fallthrough2 = self.GenerateDispatch( | |
| 846 false_code, info, indent + ' ', position, negative) | |
| 847 return fallthrough1 or fallthrough2 | |
| 848 | |
| 849 if negative: | |
| 850 raise Exception('Internal error, must be all positive') | |
| 851 | |
| 852 # All overloads require the same test. Do we bother? | |
| 853 | |
| 854 # If the test is the same as the method's formal parameter then checked mode | |
| 855 # will have done the test already. (It could be null too but we ignore that | |
| 856 # case since all the overload behave the same and we don't know which types | |
| 857 # in the IDL are not nullable.) | |
| 858 if type == param.dart_type: | |
| 859 return self.GenerateDispatch( | |
| 860 emitter, info, indent, position + 1, positive) | |
| 861 | |
| 862 # Otherwise the overloads have the same type but the type is a subtype of | |
| 863 # the method's synthesized formal parameter. e.g we have overloads f(X) and | |
| 864 # f(Y), implemented by the synthesized method f(Z) where X<Z and Y<Z. The | |
| 865 # dispatch has removed f(X), leaving only f(Y), but there is no guarantee | |
| 866 # that Y = Z-X, so we need to check for Y. | |
| 867 true_code = emitter.Emit( | |
| 868 '$(INDENT)if ($COND) {\n' | |
| 869 '$!TRUE' | |
| 870 '$(INDENT)}\n', | |
| 871 COND=test, INDENT=indent) | |
| 872 self.GenerateDispatch( | |
| 873 true_code, info, indent + ' ', position + 1, positive) | |
| 874 return True | |
| 875 | |
| 606 def AddOperation(self, info): | 876 def AddOperation(self, info): |
| 607 self._AddOperation(info) | 877 self._AddOperation(info) |
| 608 | 878 |
| 609 def AddStaticOperation(self, info): | 879 def AddStaticOperation(self, info): |
| 610 self._AddOperation(info) | 880 self._AddOperation(info) |
| 611 | 881 |
| 882 def AddSecondaryOperation(self, interface, info): | |
| 883 self.AddOperation(info) | |
| 884 | |
| 612 def GenerateSingleOperation(self, dispatch_emitter, info, indent, operation): | 885 def GenerateSingleOperation(self, dispatch_emitter, info, indent, operation): |
| 613 """Generates a call to a single operation. | 886 """Generates a call to a single operation. |
| 614 | 887 |
| 615 Arguments: | 888 Arguments: |
| 616 dispatch_emitter: an dispatch_emitter for the body of a block of code. | 889 dispatch_emitter: an dispatch_emitter for the body of a block of code. |
| 617 info: the compound information about the operation and its overloads. | 890 info: the compound information about the operation and its overloads. |
| 618 indent: an indentation string for generated code. | 891 indent: an indentation string for generated code. |
| 619 operation: the IDLOperation to call. | 892 operation: the IDLOperation to call. |
| 620 """ | 893 """ |
| 621 | 894 |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 842 def _InstanceOfNode(database, interface): | 1115 def _InstanceOfNode(database, interface): |
| 843 if interface.id == 'Node': | 1116 if interface.id == 'Node': |
| 844 return True | 1117 return True |
| 845 for parent in interface.parents: | 1118 for parent in interface.parents: |
| 846 if not database.HasInterface(parent.type.id): | 1119 if not database.HasInterface(parent.type.id): |
| 847 continue | 1120 continue |
| 848 parent_interface = database.GetInterface(parent.type.id) | 1121 parent_interface = database.GetInterface(parent.type.id) |
| 849 if _InstanceOfNode(database, parent_interface): | 1122 if _InstanceOfNode(database, parent_interface): |
| 850 return True | 1123 return True |
| 851 return False | 1124 return False |
| OLD | NEW |