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 |