| 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 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 | |
| OLD | NEW |