| 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 import generator |
| 9 from systemfrog import * | 10 from systemfrog import * |
| 10 from systeminterface import * | 11 from systeminterface import * |
| 11 | 12 |
| 12 # Members from the standard dom that should not be exposed publicly in dart:html | 13 # Members from the standard dom that should not be exposed publicly in dart:html |
| 13 # but need to be exposed internally to implement dart:html on top of a standard | 14 # but need to be exposed internally to implement dart:html on top of a standard |
| 14 # browser. | 15 # browser. |
| 15 _private_html_members = set([ | 16 _private_html_members = set([ |
| 16 'Document.createElement', | 17 'Document.createElement', |
| 17 'Document.createElementNS', | 18 'Document.createElementNS', |
| 18 'Document.createEvent', | 19 'Document.createEvent', |
| (...skipping 1547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1566 ' }\n', | 1567 ' }\n', |
| 1567 TYPE=info.type_name, | 1568 TYPE=info.type_name, |
| 1568 HTML_NAME=html_name, | 1569 HTML_NAME=html_name, |
| 1569 PARAMS=info.ParametersImplementationDeclaration()) | 1570 PARAMS=info.ParametersImplementationDeclaration()) |
| 1570 | 1571 |
| 1571 # Process in order of ascending number of arguments to ensure missing | 1572 # Process in order of ascending number of arguments to ensure missing |
| 1572 # optional arguments are processed early. | 1573 # optional arguments are processed early. |
| 1573 overloads = sorted(info.overloads, | 1574 overloads = sorted(info.overloads, |
| 1574 key=lambda overload: len(overload.arguments)) | 1575 key=lambda overload: len(overload.arguments)) |
| 1575 self._native_version = 0 | 1576 self._native_version = 0 |
| 1576 fallthrough = self.GenerateDispatch(body, info, ' ', 0, overloads) | 1577 fallthrough = generator.GenerateDispatch(self, body, info, ' ', 0, overlo
ads) |
| 1577 if fallthrough: | 1578 if fallthrough: |
| 1578 body.Emit(' throw "Incorrect number or type of arguments";\n'); | 1579 body.Emit(' throw "Incorrect number or type of arguments";\n'); |
| 1579 | 1580 |
| 1580 def AddStaticOperation(self, info): | 1581 def AddStaticOperation(self, info): |
| 1581 pass | 1582 pass |
| 1582 | 1583 |
| 1583 def GenerateSingleOperation(self, emitter, info, indent, operation): | 1584 def GenerateSingleOperation(self, emitter, info, indent, operation): |
| 1584 """Generates a call to a single operation. | 1585 """Generates a call to a single operation. |
| 1585 | 1586 |
| 1586 Arguments: | 1587 Arguments: |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1602 THIS=self.DomObjectName(), | 1603 THIS=self.DomObjectName(), |
| 1603 NAME=info.name, | 1604 NAME=info.name, |
| 1604 ARGS=argument_expressions) | 1605 ARGS=argument_expressions) |
| 1605 else: | 1606 else: |
| 1606 emitter.Emit('$(INDENT)$(THIS).$NAME($ARGS);\n' | 1607 emitter.Emit('$(INDENT)$(THIS).$NAME($ARGS);\n' |
| 1607 '$(INDENT)return;\n', | 1608 '$(INDENT)return;\n', |
| 1608 INDENT=indent, | 1609 INDENT=indent, |
| 1609 THIS=self.DomObjectName(), | 1610 THIS=self.DomObjectName(), |
| 1610 NAME=info.name, | 1611 NAME=info.name, |
| 1611 ARGS=argument_expressions) | 1612 ARGS=argument_expressions) |
| 1612 | |
| 1613 def GenerateDispatch(self, emitter, info, indent, position, overloads): | |
| 1614 """Generates a dispatch to one of the overloads. | |
| 1615 | |
| 1616 Arguments: | |
| 1617 emitter: an Emitter for the body of a block of code. | |
| 1618 info: the compound information about the operation and its overloads. | |
| 1619 indent: an indentation string for generated code. | |
| 1620 position: the index of the parameter to dispatch on. | |
| 1621 overloads: a list of the remaining IDLOperations to dispatch. | |
| 1622 | |
| 1623 Returns True if the dispatch can fall through on failure, False if the code | |
| 1624 always dispatches. | |
| 1625 """ | |
| 1626 | |
| 1627 def NullCheck(name): | |
| 1628 return '%s === null' % name | |
| 1629 | |
| 1630 def TypeCheck(name, type): | |
| 1631 return '%s is %s' % (name, type) | |
| 1632 | |
| 1633 if position == len(info.param_infos): | |
| 1634 if len(overloads) > 1: | |
| 1635 raise Exception('Duplicate operations ' + str(overloads)) | |
| 1636 operation = overloads[0] | |
| 1637 self.GenerateSingleOperation(emitter, info, indent, operation) | |
| 1638 return False | |
| 1639 | |
| 1640 # FIXME: Consider a simpler dispatch that iterates over the | |
| 1641 # overloads and generates an overload specific check. Revisit | |
| 1642 # when we move to named optional arguments. | |
| 1643 | |
| 1644 # Partition the overloads to divide and conquer on the dispatch. | |
| 1645 positive = [] | |
| 1646 negative = [] | |
| 1647 first_overload = overloads[0] | |
| 1648 param = info.param_infos[position] | |
| 1649 | |
| 1650 if position < len(first_overload.arguments): | |
| 1651 # FIXME: This will not work if the second overload has a more | |
| 1652 # precise type than the first. E.g., | |
| 1653 # void foo(Node x); | |
| 1654 # void foo(Element x); | |
| 1655 type = DartType(first_overload.arguments[position].type.id) | |
| 1656 test = TypeCheck(param.name, type) | |
| 1657 pred = lambda op: (len(op.arguments) > position and | |
| 1658 DartType(op.arguments[position].type.id) == type) | |
| 1659 else: | |
| 1660 type = None | |
| 1661 test = NullCheck(param.name) | |
| 1662 pred = lambda op: position >= len(op.arguments) | |
| 1663 | |
| 1664 for overload in overloads: | |
| 1665 if pred(overload): | |
| 1666 positive.append(overload) | |
| 1667 else: | |
| 1668 negative.append(overload) | |
| 1669 | |
| 1670 if positive and negative: | |
| 1671 (true_code, false_code) = emitter.Emit( | |
| 1672 '$(INDENT)if ($COND) {\n' | |
| 1673 '$!TRUE' | |
| 1674 '$(INDENT)} else {\n' | |
| 1675 '$!FALSE' | |
| 1676 '$(INDENT)}\n', | |
| 1677 COND=test, INDENT=indent) | |
| 1678 fallthrough1 = self.GenerateDispatch( | |
| 1679 true_code, info, indent + ' ', position + 1, positive) | |
| 1680 fallthrough2 = self.GenerateDispatch( | |
| 1681 false_code, info, indent + ' ', position, negative) | |
| 1682 return fallthrough1 or fallthrough2 | |
| 1683 | |
| 1684 if negative: | |
| 1685 raise Exception('Internal error, must be all positive') | |
| 1686 | |
| 1687 # All overloads require the same test. Do we bother? | |
| 1688 | |
| 1689 # If the test is the same as the method's formal parameter then checked mode | |
| 1690 # will have done the test already. (It could be null too but we ignore that | |
| 1691 # case since all the overload behave the same and we don't know which types | |
| 1692 # in the IDL are not nullable.) | |
| 1693 if type == param.dart_type: | |
| 1694 return self.GenerateDispatch( | |
| 1695 emitter, info, indent, position + 1, positive) | |
| 1696 | |
| 1697 # Otherwise the overloads have the same type but the type is a substype of | |
| 1698 # the method's synthesized formal parameter. e.g we have overloads f(X) and | |
| 1699 # f(Y), implemented by the synthesized method f(Z) where X<Z and Y<Z. The | |
| 1700 # dispatch has removed f(X), leaving only f(Y), but there is no guarantee | |
| 1701 # that Y = Z-X, so we need to check for Y. | |
| 1702 true_code = emitter.Emit( | |
| 1703 '$(INDENT)if ($COND) {\n' | |
| 1704 '$!TRUE' | |
| 1705 '$(INDENT)}\n', | |
| 1706 COND=test, INDENT=indent) | |
| 1707 self.GenerateDispatch( | |
| 1708 true_code, info, indent + ' ', position + 1, positive) | |
| 1709 return True | |
| OLD | NEW |