Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(899)

Side by Side Diff: lib/dom/scripts/systemhtml.py

Issue 10388089: Remove overload dispatcher from native html implementation. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 system to generate 6 """This module provides shared functionality for the system to generate
7 Dart:html APIs from the IDL database.""" 7 Dart:html APIs from the IDL database."""
8 8
9 from systemfrog import * 9 from systemfrog import *
10 from systeminterface import * 10 from systeminterface import *
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 #TODO(jacobr): inject annotations into the interfaces based on this table and 101 #TODO(jacobr): inject annotations into the interfaces based on this table and
102 # on _html_library_renames. 102 # on _html_library_renames.
103 _injected_doc_fragments = { 103 _injected_doc_fragments = {
104 'Element.query': ' /** @domName Element.querySelector, Document.getElementB yId */', 104 'Element.query': ' /** @domName Element.querySelector, Document.getElementB yId */',
105 } 105 }
106 # Members and classes from the dom that should be removed completelly from 106 # Members and classes from the dom that should be removed completelly from
107 # dart:html. These could be expressed in the IDL instead but expressing this 107 # dart:html. These could be expressed in the IDL instead but expressing this
108 # as a simple table instead is more concise. 108 # as a simple table instead is more concise.
109 # Syntax is: ClassName.(get\.|set\.)?MemberName 109 # Syntax is: ClassName.(get\.|set\.)?MemberName
110 # Using get: and set: is optional and should only be used when a getter needs 110 # Using get: and set: is optional and should only be used when a getter needs
111 # to be suppressed but not the setter, etc. 111 # to be suppressed but not the setter, etc.
112 # TODO(jacobr): cleanup and augment this list. 112 # TODO(jacobr): cleanup and augment this list.
113 _html_library_remove = set([ 113 _html_library_remove = set([
114 'Window.get:document', # Removed as we have a custom implementation. 114 'Window.get:document', # Removed as we have a custom implementation.
115 'NodeList.item', 115 'NodeList.item',
116 "Attr.*", 116 "Attr.*",
117 # "BarProp.*", 117 # "BarProp.*",
118 # "BarInfo.*", 118 # "BarInfo.*",
119 # "Blob.webkitSlice", 119 # "Blob.webkitSlice",
120 # "CDATASection.*", 120 # "CDATASection.*",
121 # "Comment.*", 121 # "Comment.*",
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after
442 _html_explicit_event_classes = set(['DocumentFragment']) 442 _html_explicit_event_classes = set(['DocumentFragment'])
443 443
444 def _OnAttributeToEventName(on_method): 444 def _OnAttributeToEventName(on_method):
445 event_name = on_method.id[2:] 445 event_name = on_method.id[2:]
446 if event_name in _on_attribute_to_event_name_mapping: 446 if event_name in _on_attribute_to_event_name_mapping:
447 return _on_attribute_to_event_name_mapping[event_name] 447 return _on_attribute_to_event_name_mapping[event_name]
448 else: 448 else:
449 return event_name 449 return event_name
450 450
451 def _DomToHtmlEvents(interface_id, events): 451 def _DomToHtmlEvents(interface_id, events):
452 event_names = set(map(_OnAttributeToEventName, events)) 452 event_names = set(map(_OnAttributeToEventName, events))
453 if interface_id in _html_manual_events: 453 if interface_id in _html_manual_events:
454 for manual_event_name in _html_manual_events[interface_id]: 454 for manual_event_name in _html_manual_events[interface_id]:
455 event_names.add(manual_event_name) 455 event_names.add(manual_event_name)
456 456
457 return sorted(event_names, key=lambda name: _html_event_names[name]) 457 return sorted(event_names, key=lambda name: _html_event_names[name])
458 458
459 # ------------------------------------------------------------------------------ 459 # ------------------------------------------------------------------------------
460 class HtmlSystemShared(object): 460 class HtmlSystemShared(object):
461 461
462 def __init__(self, database, generator): 462 def __init__(self, database, generator):
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
520 520
521 # TODO(jacobr): this already exists 521 # TODO(jacobr): this already exists
522 def _TraverseParents(self, interface, callback): 522 def _TraverseParents(self, interface, callback):
523 for parent in interface.parents: 523 for parent in interface.parents:
524 parent_id = parent.type.id 524 parent_id = parent.type.id
525 if self._database.HasInterface(parent_id): 525 if self._database.HasInterface(parent_id):
526 parent_interface = self._database.GetInterface(parent_id) 526 parent_interface = self._database.GetInterface(parent_id)
527 callback(parent_interface) 527 callback(parent_interface)
528 self._TraverseParents(parent_interface, callback) 528 self._TraverseParents(parent_interface, callback)
529 529
530 # TODO(jacobr): this isn't quite right.... 530 # TODO(jacobr): this isn't quite right....
531 def GetParentsEventsClasses(self, interface): 531 def GetParentsEventsClasses(self, interface):
532 # Ugly hack as we don't specify that Document and DocumentFragment inherit 532 # Ugly hack as we don't specify that Document and DocumentFragment inherit
533 # from Element in our IDL. 533 # from Element in our IDL.
534 if interface.id == 'Document' or interface.id == 'DocumentFragment': 534 if interface.id == 'Document' or interface.id == 'DocumentFragment':
535 return ['ElementEvents'] 535 return ['ElementEvents']
536 536
537 interfaces_with_events = set() 537 interfaces_with_events = set()
538 def visit(parent): 538 def visit(parent):
539 if parent.id in self._event_classes: 539 if parent.id in self._event_classes:
540 interfaces_with_events.add(parent) 540 interfaces_with_events.add(parent)
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
760 """ 760 """
761 html_name = self._shared.RenameInHtmlLibrary( 761 html_name = self._shared.RenameInHtmlLibrary(
762 self._interface, info.name) 762 self._interface, info.name)
763 if html_name and not self._shared.IsPrivate(html_name): 763 if html_name and not self._shared.IsPrivate(html_name):
764 self._members_emitter.Emit('\n /** @domName $DOMINTERFACE.$DOMNAME */', 764 self._members_emitter.Emit('\n /** @domName $DOMINTERFACE.$DOMNAME */',
765 DOMINTERFACE=info.overloads[0].doc_js_interface_name, 765 DOMINTERFACE=info.overloads[0].doc_js_interface_name,
766 DOMNAME=info.name) 766 DOMNAME=info.name)
767 767
768 self._members_emitter.Emit('\n' 768 self._members_emitter.Emit('\n'
769 ' $TYPE $NAME($PARAMS);\n', 769 ' $TYPE $NAME($PARAMS);\n',
770 TYPE=info.type_name, 770 TYPE=info.type_name,
771 NAME=html_name, 771 NAME=html_name,
772 PARAMS=info.ParametersInterfaceDeclaration()) 772 PARAMS=info.ParametersInterfaceDeclaration())
773 773
774 def FinishInterface(self): 774 def FinishInterface(self):
775 pass 775 pass
776 776
777 def AddConstant(self, constant): 777 def AddConstant(self, constant):
778 self._EmitConstant(self._members_emitter, constant) 778 self._EmitConstant(self._members_emitter, constant)
779 779
780 def AddEventAttributes(self, event_attrs): 780 def AddEventAttributes(self, event_attrs):
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
933 TYPE=self._NarrowInputType(element_type)) 933 TYPE=self._NarrowInputType(element_type))
934 934
935 # TODO(sra): Use separate mixins for mutable implementations of List<T>. 935 # TODO(sra): Use separate mixins for mutable implementations of List<T>.
936 # TODO(sra): Use separate mixins for typed array implementations of List<T>. 936 # TODO(sra): Use separate mixins for typed array implementations of List<T>.
937 if self._interface.id != 'NodeList': 937 if self._interface.id != 'NodeList':
938 template_file = 'immutable_list_mixin.darttemplate' 938 template_file = 'immutable_list_mixin.darttemplate'
939 template = self._system._templates.Load(template_file) 939 template = self._system._templates.Load(template_file)
940 self._members_emitter.Emit(template, E=DartType(element_type)) 940 self._members_emitter.Emit(template, E=DartType(element_type))
941 941
942 def AddAttribute(self, getter, setter): 942 def AddAttribute(self, getter, setter):
943 943
944 html_getter_name = self._shared.RenameInHtmlLibrary( 944 html_getter_name = self._shared.RenameInHtmlLibrary(
945 self._interface, DartDomNameOfAttribute(getter), 'get:', 945 self._interface, DartDomNameOfAttribute(getter), 'get:',
946 implementation_class=True) 946 implementation_class=True)
947 html_setter_name = self._shared.RenameInHtmlLibrary( 947 html_setter_name = self._shared.RenameInHtmlLibrary(
948 self._interface, DartDomNameOfAttribute(getter), 'set:', 948 self._interface, DartDomNameOfAttribute(getter), 'set:',
949 implementation_class=True) 949 implementation_class=True)
950 950
951 if not html_getter_name: 951 if not html_getter_name:
952 getter = None 952 getter = None
953 if not html_setter_name: 953 if not html_setter_name:
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
1037 info: An OperationInfo object. 1037 info: An OperationInfo object.
1038 """ 1038 """
1039 html_name = self._shared.RenameInHtmlLibrary( 1039 html_name = self._shared.RenameInHtmlLibrary(
1040 self._interface, info.name, implementation_class=True) 1040 self._interface, info.name, implementation_class=True)
1041 if not html_name: 1041 if not html_name:
1042 return 1042 return
1043 1043
1044 # Do we need a native body? 1044 # Do we need a native body?
1045 if html_name != info.declared_name: 1045 if html_name != info.declared_name:
1046 return_type = self._NarrowOutputType(info.type_name) 1046 return_type = self._NarrowOutputType(info.type_name)
1047 1047
1048 operation_emitter = self._members_emitter.Emit('$!SCOPE', 1048 operation_emitter = self._members_emitter.Emit('$!SCOPE',
1049 TYPE=return_type, 1049 TYPE=return_type,
1050 HTML_NAME=html_name, 1050 HTML_NAME=html_name,
1051 NAME=info.declared_name, 1051 NAME=info.declared_name,
1052 PARAMS=info.ParametersImplementationDeclaration( 1052 PARAMS=info.ParametersImplementationDeclaration(
1053 lambda type_name: self._NarrowInputType(type_name))) 1053 lambda type_name: self._NarrowInputType(type_name)))
1054 1054
1055 operation_emitter.Emit( 1055 operation_emitter.Emit(
1056 '\n' 1056 '\n'
1057 ' $TYPE $(HTML_NAME)($PARAMS) native "$NAME";\n') 1057 ' $TYPE $(HTML_NAME)($PARAMS) native "$NAME";\n')
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
1222 template: template that output is generated into. 1222 template: template that output is generated into.
1223 interface: an IDLInterface instance. It is assumed that all types have 1223 interface: an IDLInterface instance. It is assumed that all types have
1224 been converted to Dart types (e.g. int, String), unless they are in 1224 been converted to Dart types (e.g. int, String), unless they are in
1225 the same package as the interface. 1225 the same package as the interface.
1226 super_interface: A string or None, the name of the common interface that 1226 super_interface: A string or None, the name of the common interface that
1227 this interface implements, if any. 1227 this interface implements, if any.
1228 dart_code: an Emitter for the file containing the Dart implementation 1228 dart_code: an Emitter for the file containing the Dart implementation
1229 class. 1229 class.
1230 base_members: a set of names of members defined in a base class. This is 1230 base_members: a set of names of members defined in a base class. This is
1231 used to avoid static member 'overriding' in the generated Dart code. 1231 used to avoid static member 'overriding' in the generated Dart code.
1232 shared: functionaly shared across all Html generators. 1232 shared: functionaly shared across all Html generators.
1233 """ 1233 """
1234 self._system = system 1234 self._system = system
1235 self._interface = interface 1235 self._interface = interface
1236 self._super_interface = super_interface 1236 self._super_interface = super_interface
1237 self._dart_code = dart_code 1237 self._dart_code = dart_code
1238 self._base_members = base_members 1238 self._base_members = base_members
1239 self._current_secondary_parent = None 1239 self._current_secondary_parent = None
1240 self._shared = shared 1240 self._shared = shared
1241 self._template = template 1241 self._template = template
1242 1242
(...skipping 30 matching lines...) Expand all
1273 base = None 1273 base = None
1274 if interface.parents: 1274 if interface.parents:
1275 supertype = interface.parents[0].type.id 1275 supertype = interface.parents[0].type.id
1276 if not IsDartListType(supertype): 1276 if not IsDartListType(supertype):
1277 base = self._ImplClassName(supertype) 1277 base = self._ImplClassName(supertype)
1278 if IsDartCollectionType(supertype): 1278 if IsDartCollectionType(supertype):
1279 # List methods are injected in AddIndexer. 1279 # List methods are injected in AddIndexer.
1280 pass 1280 pass
1281 else: 1281 else:
1282 base = self._ImplClassName(supertype) 1282 base = self._ImplClassName(supertype)
1283 1283
1284 # TODO(jacobr): this is fragile. There isn't a guarantee that dart:dom 1284 # TODO(jacobr): this is fragile. There isn't a guarantee that dart:dom
1285 # will continue to exactly match the IDL names. 1285 # will continue to exactly match the IDL names.
1286 dom_name = interface.javascript_binding_name 1286 dom_name = interface.javascript_binding_name
1287 self._system._wrap_cases.append( 1287 self._system._wrap_cases.append(
1288 " case '%s': return new %s._wrap(domObject);" % 1288 " case '%s': return new %s._wrap(domObject);" %
1289 (dom_name, self._class_name)) 1289 (dom_name, self._class_name))
1290 1290
1291 extends = ' extends ' + base if base else ' extends _DOMTypeBase' 1291 extends = ' extends ' + base if base else ' extends _DOMTypeBase'
1292 1292
1293 # TODO: Include all implemented interfaces, including other Lists. 1293 # TODO: Include all implemented interfaces, including other Lists.
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
1557 """ 1557 """
1558 Arguments: 1558 Arguments:
1559 info: An OperationInfo object. 1559 info: An OperationInfo object.
1560 """ 1560 """
1561 html_name = self._shared.RenameInHtmlLibrary( 1561 html_name = self._shared.RenameInHtmlLibrary(
1562 self._interface, info.name, implementation_class=True) 1562 self._interface, info.name, implementation_class=True)
1563 1563
1564 if not html_name: 1564 if not html_name:
1565 return 1565 return
1566 1566
1567 body = self._members_emitter.Emit( 1567 arguments = self._UnwrappedParameters(info, len(info.param_infos))
1568 function_call = '%s.%s(%s)' % (self.DomObjectName(), info.name, arguments)
1569 if info.type_name != 'void':
1570 # We could place the logic for handling Document directly in _wrap
1571 # but we chose to place it here so that bugs in the wrapper and
1572 # wrapperless implementations are more consistent.
1573 function_call = '_wrap(%s)' % function_call
1574
1575 self._members_emitter.Emit(
1568 '\n' 1576 '\n'
1569 ' $TYPE $HTML_NAME($PARAMS) {\n' 1577 ' $TYPE $HTML_NAME($PARAMS) => $FUNCTION_CALL;\n',
1570 '$!BODY'
1571 ' }\n',
1572 TYPE=info.type_name, 1578 TYPE=info.type_name,
1573 HTML_NAME=html_name, 1579 HTML_NAME=html_name,
1574 PARAMS=info.ParametersImplementationDeclaration()) 1580 PARAMS=info.ParametersImplementationDeclaration(),
1575 1581 FUNCTION_CALL=function_call)
1576 # Process in order of ascending number of arguments to ensure missing
1577 # optional arguments are processed early.
1578 overloads = sorted(info.overloads,
1579 key=lambda overload: len(overload.arguments))
1580 self._native_version = 0
1581 fallthrough = self.GenerateDispatch(body, info, ' ', 0, overloads)
1582 if fallthrough:
1583 body.Emit(' throw "Incorrect number or type of arguments";\n');
1584 1582
1585 def AddStaticOperation(self, info): 1583 def AddStaticOperation(self, info):
1586 pass 1584 pass
1587
1588 def GenerateSingleOperation(self, emitter, info, indent, operation):
1589 """Generates a call to a single operation.
1590
1591 Arguments:
1592 emitter: an Emitter for the body of a block of code.
1593 info: the compound information about the operation and its overloads.
1594 indent: an indentation string for generated code.
1595 operation: the IDLOperation to call.
1596 """
1597 argument_expressions = self._UnwrappedParameters(
1598 info,
1599 len(operation.arguments)) # Just the parameters this far.
1600
1601 if info.type_name != 'void':
1602 # We could place the logic for handling Document directly in _wrap
1603 # but we chose to place it here so that bugs in the wrapper and
1604 # wrapperless implementations are more consistent.
1605 emitter.Emit('$(INDENT)return _wrap($(THIS).$NAME($ARGS));\n',
1606 INDENT=indent,
1607 THIS=self.DomObjectName(),
1608 NAME=info.name,
1609 ARGS=argument_expressions)
1610 else:
1611 emitter.Emit('$(INDENT)$(THIS).$NAME($ARGS);\n'
1612 '$(INDENT)return;\n',
1613 INDENT=indent,
1614 THIS=self.DomObjectName(),
1615 NAME=info.name,
1616 ARGS=argument_expressions)
1617
1618 def GenerateDispatch(self, emitter, info, indent, position, overloads):
1619 """Generates a dispatch to one of the overloads.
1620
1621 Arguments:
1622 emitter: an Emitter for the body of a block of code.
1623 info: the compound information about the operation and its overloads.
1624 indent: an indentation string for generated code.
1625 position: the index of the parameter to dispatch on.
1626 overloads: a list of the remaining IDLOperations to dispatch.
1627
1628 Returns True if the dispatch can fall through on failure, False if the code
1629 always dispatches.
1630 """
1631
1632 def NullCheck(name):
1633 return '%s === null' % name
1634
1635 def TypeCheck(name, type):
1636 return '%s is %s' % (name, type)
1637
1638 if position == len(info.param_infos):
1639 if len(overloads) > 1:
1640 raise Exception('Duplicate operations ' + str(overloads))
1641 operation = overloads[0]
1642 self.GenerateSingleOperation(emitter, info, indent, operation)
1643 return False
1644
1645 # FIXME: Consider a simpler dispatch that iterates over the
1646 # overloads and generates an overload specific check. Revisit
1647 # when we move to named optional arguments.
1648
1649 # Partition the overloads to divide and conquer on the dispatch.
1650 positive = []
1651 negative = []
1652 first_overload = overloads[0]
1653 param = info.param_infos[position]
1654
1655 if position < len(first_overload.arguments):
1656 # FIXME: This will not work if the second overload has a more
1657 # precise type than the first. E.g.,
1658 # void foo(Node x);
1659 # void foo(Element x);
1660 type = DartType(first_overload.arguments[position].type.id)
1661 test = TypeCheck(param.name, type)
1662 pred = lambda op: (len(op.arguments) > position and
1663 DartType(op.arguments[position].type.id) == type)
1664 else:
1665 type = None
1666 test = NullCheck(param.name)
1667 pred = lambda op: position >= len(op.arguments)
1668
1669 for overload in overloads:
1670 if pred(overload):
1671 positive.append(overload)
1672 else:
1673 negative.append(overload)
1674
1675 if positive and negative:
1676 (true_code, false_code) = emitter.Emit(
1677 '$(INDENT)if ($COND) {\n'
1678 '$!TRUE'
1679 '$(INDENT)} else {\n'
1680 '$!FALSE'
1681 '$(INDENT)}\n',
1682 COND=test, INDENT=indent)
1683 fallthrough1 = self.GenerateDispatch(
1684 true_code, info, indent + ' ', position + 1, positive)
1685 fallthrough2 = self.GenerateDispatch(
1686 false_code, info, indent + ' ', position, negative)
1687 return fallthrough1 or fallthrough2
1688
1689 if negative:
1690 raise Exception('Internal error, must be all positive')
1691
1692 # All overloads require the same test. Do we bother?
1693
1694 # If the test is the same as the method's formal parameter then checked mode
1695 # will have done the test already. (It could be null too but we ignore that
1696 # case since all the overload behave the same and we don't know which types
1697 # in the IDL are not nullable.)
1698 if type == param.dart_type:
1699 return self.GenerateDispatch(
1700 emitter, info, indent, position + 1, positive)
1701
1702 # Otherwise the overloads have the same type but the type is a substype of
1703 # the method's synthesized formal parameter. e.g we have overloads f(X) and
1704 # f(Y), implemented by the synthesized method f(Z) where X<Z and Y<Z. The
1705 # dispatch has removed f(X), leaving only f(Y), but there is no guarantee
1706 # that Y = Z-X, so we need to check for Y.
1707 true_code = emitter.Emit(
1708 '$(INDENT)if ($COND) {\n'
1709 '$!TRUE'
1710 '$(INDENT)}\n',
1711 COND=test, INDENT=indent)
1712 self.GenerateDispatch(
1713 true_code, info, indent + ' ', position + 1, positive)
1714 return True
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698