| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 interface HVisitor<R> { | 5 interface HVisitor<R> { |
| 6 R visitAdd(HAdd node); | 6 R visitAdd(HAdd node); |
| 7 R visitBailoutTarget(HBailoutTarget node); | 7 R visitBailoutTarget(HBailoutTarget node); |
| 8 R visitBitAnd(HBitAnd node); | 8 R visitBitAnd(HBitAnd node); |
| 9 R visitBitNot(HBitNot node); | 9 R visitBitNot(HBitNot node); |
| 10 R visitBitOr(HBitOr node); | 10 R visitBitOr(HBitOr node); |
| (...skipping 1567 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1578 /** | 1578 /** |
| 1579 * Finds the quote type for a string given a part of it containing the | 1579 * Finds the quote type for a string given a part of it containing the |
| 1580 * starting quote. Returns flags, but doesn't include HAS_LEFT_QUOTE | 1580 * starting quote. Returns flags, but doesn't include HAS_LEFT_QUOTE |
| 1581 * or HAS_RIGHT_QUOTE. | 1581 * or HAS_RIGHT_QUOTE. |
| 1582 */ | 1582 */ |
| 1583 static int flagsFromLeftQuote(SourceString sourceString) { | 1583 static int flagsFromLeftQuote(SourceString sourceString) { |
| 1584 Iterator<int> source = sourceString.iterator(); | 1584 Iterator<int> source = sourceString.iterator(); |
| 1585 int flags = 0; | 1585 int flags = 0; |
| 1586 int start = 0; | 1586 int start = 0; |
| 1587 int quoteChar = source.next(); | 1587 int quoteChar = source.next(); |
| 1588 if (quoteChar == '@'.charCodeAt(0)) { | 1588 if (quoteChar == $AT) { |
| 1589 flags |= RAW; | 1589 flags |= RAW; |
| 1590 start = 1; | 1590 start = 1; |
| 1591 quoteChar = source.next(); | 1591 quoteChar = source.next(); |
| 1592 } | 1592 } |
| 1593 if (quoteChar == '\''.charCodeAt(0)) { | 1593 if (quoteChar == $SQ) { |
| 1594 flags |= SINGLE_QUOTED; | 1594 flags |= SINGLE_QUOTED; |
| 1595 } else { | 1595 } else { |
| 1596 assert(quoteChar == '"'.charCodeAt(0)); | 1596 assert(quoteChar == $DQ); |
| 1597 } | 1597 } |
| 1598 // String has one quote. Check it if has three. | 1598 // String has one quote. Check it if has three. |
| 1599 // If it only have two, the string must be an empty string literal, | 1599 // If it only have two, the string must be an empty string literal, |
| 1600 // and end after the second quote. | 1600 // and end after the second quote. |
| 1601 if (source.hasNext() && source.next() == quoteChar && source.hasNext()) { | 1601 if (source.hasNext() && source.next() == quoteChar && source.hasNext()) { |
| 1602 assert(source.next() == quoteChar); | 1602 assert(source.next() == quoteChar); |
| 1603 flags |= MULTI_LINE; | 1603 flags |= MULTI_LINE; |
| 1604 } | 1604 } |
| 1605 return flags; | 1605 return flags; |
| 1606 } | 1606 } |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1627 if ((flags & HAS_BOTH_QUOTES) == 0) return wrappedString; | 1627 if ((flags & HAS_BOTH_QUOTES) == 0) return wrappedString; |
| 1628 return wrappedString.copyWithoutQuotes(leftQuoteLength, | 1628 return wrappedString.copyWithoutQuotes(leftQuoteLength, |
| 1629 rightQuoteLength); | 1629 rightQuoteLength); |
| 1630 } | 1630 } |
| 1631 | 1631 |
| 1632 bool get hasLeftQuote() => (flags & HAS_LEFT_QUOTE) != 0; | 1632 bool get hasLeftQuote() => (flags & HAS_LEFT_QUOTE) != 0; |
| 1633 bool get hasRightQuote() => (flags & HAS_RIGHT_QUOTE) != 0; | 1633 bool get hasRightQuote() => (flags & HAS_RIGHT_QUOTE) != 0; |
| 1634 bool get isMultiLine() => (flags & MULTI_LINE) != 0; | 1634 bool get isMultiLine() => (flags & MULTI_LINE) != 0; |
| 1635 bool get isRaw() => (flags & RAW) != 0; | 1635 bool get isRaw() => (flags & RAW) != 0; |
| 1636 String get quoteChar() => ((flags & SINGLE_QUOTED) != 0) ? "'" : '"'; | 1636 String get quoteChar() => ((flags & SINGLE_QUOTED) != 0) ? "'" : '"'; |
| 1637 int get quoteCharCode() => ((flags & SINGLE_QUOTED) != 0) ? $SQ : $DQ; |
| 1637 | 1638 |
| 1638 int get leftQuoteLength() => | 1639 int get leftQuoteLength() => |
| 1639 hasLeftQuote ? (isRaw ? 1 : 0) + (isMultiLine ? 3 : 1) : 0; | 1640 hasLeftQuote ? (isRaw ? 1 : 0) + (isMultiLine ? 3 : 1) : 0; |
| 1640 int get rightQuoteLength() => | 1641 int get rightQuoteLength() => |
| 1641 hasRightQuote ? (isMultiLine ? 3 : 1) : 0; | 1642 hasRightQuote ? (isMultiLine ? 3 : 1) : 0; |
| 1642 static int leftQuoteLengthFromFlags(int flags) { | 1643 static int leftQuoteLengthFromFlags(int flags) { |
| 1643 if ((flags & HAS_LEFT_QUOTE) == 0) return 0; | 1644 if ((flags & HAS_LEFT_QUOTE) == 0) return 0; |
| 1644 return (flags & (RAW | MULTI_LINE)) + 1; | 1645 return (flags & (RAW | MULTI_LINE)) + 1; |
| 1645 } | 1646 } |
| 1646 static int rightQuoteLengthFromFlags(int flags) { | 1647 static int rightQuoteLengthFromFlags(int flags) { |
| 1647 if ((flags & HAS_RIGHT_QUOTE) == 0) return 0; | 1648 if ((flags & HAS_RIGHT_QUOTE) == 0) return 0; |
| 1648 return (flags & MULTI_LINE) + 1; | 1649 return (flags & MULTI_LINE) + 1; |
| 1649 } | 1650 } |
| 1650 | 1651 |
| 1651 bool isEmpty() => unquotedSource().isEmpty(); | 1652 bool isEmpty() => unquotedSource().isEmpty(); |
| 1652 | 1653 |
| 1654 static int hexValue(int hexDigit) { |
| 1655 // hexDigit is one of '0'..'9', 'A'..'F' and 'a'..'f'. |
| 1656 if (hexDigit <= $9) { |
| 1657 return hexDigit - $0; |
| 1658 } |
| 1659 // Make letters lowercase. |
| 1660 hexDigit |= $a ^ $A; |
| 1661 hexDigit -= $a - 10; |
| 1662 assert(10 <= hexDigit && hexDigit <= 15); |
| 1663 return hexDigit; |
| 1664 } |
| 1665 |
| 1666 static bool isHexDigit(int characterCode) { |
| 1667 if ($0 <= characterCode && characterCode <= $9) return true; |
| 1668 characterCode |= $a ^ $A; |
| 1669 return ($a <= characterCode && characterCode <= $f); |
| 1670 } |
| 1671 |
| 1672 static int readUnicodeEscape(Iterator<int> iter, |
| 1673 void cancel(String s)) { |
| 1674 if (!iter.hasNext()) cancel("Incomplete unicode escape."); |
| 1675 int code = iter.next(); |
| 1676 if (code == $OPEN_CURLY_BRACKET) { |
| 1677 // In Dart, '\u{'x{0..7}'}' is a valid escape, but not in |
| 1678 // JS. Convert to a \uxxxx escape. |
| 1679 int value = 0; |
| 1680 int length = 0; |
| 1681 if (!iter.hasNext()) cancel("Incomplete unicode escape."); |
| 1682 int hexDigit = iter.next(); |
| 1683 do { |
| 1684 if (!isHexDigit(hexDigit)) { |
| 1685 cancel("Invalid character in unicode escape"); |
| 1686 } |
| 1687 value = value * 16 + hexValue(hexDigit); |
| 1688 length++; |
| 1689 if (length > 7) { |
| 1690 cancel("Invalid unicode escape length."); |
| 1691 } |
| 1692 if (!iter.hasNext()) cancel("Incomplete unicode escape."); |
| 1693 hexDigit = iter.next(); |
| 1694 } while (hexDigit !== $CLOSE_CURLY_BRACKET); // until '}'. |
| 1695 return value; |
| 1696 } |
| 1697 // Simple four-digit unicode escape. |
| 1698 int value = 0; |
| 1699 for (int i = 0; i < 4; i++) { |
| 1700 if (i > 0) { |
| 1701 if (!iter.hasNext()) cancel("Incomplete unicode escape."); |
| 1702 code = iter.next(); |
| 1703 } |
| 1704 if (!isHexDigit(code)) cancel("Invalid character in unicode escape"); |
| 1705 value = value * 16 + hexValue(code); |
| 1706 } |
| 1707 return value; |
| 1708 } |
| 1709 |
| 1710 /** |
| 1711 * Write the contents of the quoted string to a [StringBuffer] in |
| 1712 * a form that is valid as JavaScript string literal content. |
| 1713 * The string is assumed quoted by [quote] characters. |
| 1714 * This method doesn't try to make the shortest string, but rather |
| 1715 * to be as close to the original string as possible. |
| 1716 */ |
| 1717 void writeEscaped(StringBuffer buffer, int quote, void cancel(String s)) { |
| 1718 bool raw = this.isRaw; |
| 1719 Iterator<int> iter = |
| 1720 wrappedString.copyWithoutQuotes(leftQuoteLength, |
| 1721 rightQuoteLength).iterator(); |
| 1722 while (iter.hasNext()) { |
| 1723 int code = iter.next(); |
| 1724 if (code == quote) { |
| 1725 // We need to add a backslash before quotes, both in normal |
| 1726 // and in raw strings. |
| 1727 buffer.add(@'\'); |
| 1728 buffer.add(code == $SQ ? "'" : '"'); |
| 1729 } else if (code == $LF) { |
| 1730 // Newlines in strings only occour in multiline strings. |
| 1731 // They need to be written using escapes in JS.. |
| 1732 assert(isMultiLine); |
| 1733 buffer.add(@'\n'); |
| 1734 } else if (code == $CR) { |
| 1735 assert(isMultiLine); |
| 1736 buffer.add(@'\r'); |
| 1737 } else if (code == $LS || code == $PS) { |
| 1738 // These Unicode line terminators are invalid in JS strings. |
| 1739 buffer.add(code == $LS ? @'\u2028' : @'\u2029'); |
| 1740 } else if (code != $BACKSLASH) { |
| 1741 buffer.add(new String.fromCharCodes([code])); |
| 1742 } else if (raw) { |
| 1743 buffer.add(@'\\'); |
| 1744 } else { |
| 1745 code = iter.next(); |
| 1746 // TODO(lrn): Reading \x and \u escapes also validates the |
| 1747 // escape sequences. This should be done at an earlier step |
| 1748 // to catch errors even in dead code. |
| 1749 switch (code) { |
| 1750 case $u: |
| 1751 int value = readUnicodeEscape(iter, cancel); |
| 1752 if (value >= 0xD800 && value <= 0xDFFF || value > 0x10ffff) { |
| 1753 cancel('Invalid unicode scalar value.'); |
| 1754 } |
| 1755 if (value > 0xffff) { |
| 1756 cancel('Unhandled Unicode value: $value - outside the BMP.'); |
| 1757 } |
| 1758 buffer.add(@'\u'); |
| 1759 for (int j = 12; j >= 0; j -= 4) { |
| 1760 int digit = (value >> j) & 0xf; |
| 1761 buffer.add("0123456789abcdef"[digit]); |
| 1762 } |
| 1763 break; |
| 1764 case $x: |
| 1765 buffer.add(@'\x'); |
| 1766 List<int> codes = <int>[]; |
| 1767 for (int i = 0; i < 2; i++) { |
| 1768 if (!iter.hasNext()) cancel("Incomplete hex escape"); |
| 1769 code = iter.next(); |
| 1770 if (!isHexDigit(code)) { |
| 1771 cancel("Invalid hex digit: " + |
| 1772 "${new String.fromCharCodes([code])}"); |
| 1773 } |
| 1774 codes.add(code); |
| 1775 } |
| 1776 buffer.add(new String.fromCharCodes(codes)); |
| 1777 break; |
| 1778 // Character escapes that identical in meaning in JS. |
| 1779 case $b: buffer.add(@'\b'); break; |
| 1780 case $f: buffer.add(@'\f'); break; |
| 1781 case $n: buffer.add(@'\n'); break; |
| 1782 case $r: buffer.add(@'\r'); break; |
| 1783 case $t: buffer.add(@'\t'); break; |
| 1784 case $v: buffer.add(@'\v'); break; |
| 1785 // Identity escapes that must be escaped in JS strings. |
| 1786 case $BACKSLASH: buffer.add(@'\\'); break; |
| 1787 case $LF: buffer.add(@'\n'); break; |
| 1788 case $CR: buffer.add(@'\r'); break; |
| 1789 case $LS: buffer.add(@'\u2028'); break; |
| 1790 case $PS: buffer.add(@'\u2029'); break; |
| 1791 // Quotes may or may not need the escape. |
| 1792 case $SQ: |
| 1793 case $DQ: |
| 1794 // Only escape quotes if they match the generated string quotes. |
| 1795 if (code == quote) buffer.add(@'\'); |
| 1796 buffer.add(code === $SQ ? "'" : '"'); |
| 1797 break; |
| 1798 default: |
| 1799 // All other escaped characters are identity escapes, |
| 1800 // and don't need a backslash in JS. |
| 1801 buffer.add(new String.fromCharCodes([code])); |
| 1802 break; |
| 1803 } |
| 1804 } |
| 1805 } |
| 1806 } |
| 1807 |
| 1653 /** | 1808 /** |
| 1654 * Does a conservative test for equality between two quoted strings. | 1809 * Does a conservative test for equality between two quoted strings. |
| 1655 * Returns true if the two definitly have the same string. | 1810 * Returns true if the two definitly have the same string. |
| 1656 * Returns false if the strings are different, or if it's not possible | 1811 * Returns false if the strings are different, or if it's not possible |
| 1657 * to (quickly) determine whether they are equal. | 1812 * to (quickly) determine whether they are equal. |
| 1658 */ | 1813 */ |
| 1659 bool definitlyEquals(QuotedString other) { | 1814 bool definitlyEquals(QuotedString other) { |
| 1660 return flags == other.flags && wrappedString == other.wrappedString; | 1815 return flags == other.flags && wrappedString == other.wrappedString; |
| 1661 } | 1816 } |
| 1662 | 1817 |
| (...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2107 | 2262 |
| 2108 HInstruction get expression() => inputs[0]; | 2263 HInstruction get expression() => inputs[0]; |
| 2109 | 2264 |
| 2110 HType computeType() => HType.BOOLEAN; | 2265 HType computeType() => HType.BOOLEAN; |
| 2111 bool hasExpectedType() => true; | 2266 bool hasExpectedType() => true; |
| 2112 | 2267 |
| 2113 accept(HVisitor visitor) => visitor.visitIs(this); | 2268 accept(HVisitor visitor) => visitor.visitIs(this); |
| 2114 | 2269 |
| 2115 toString() => "$expression is $typeExpression"; | 2270 toString() => "$expression is $typeExpression"; |
| 2116 } | 2271 } |
| OLD | NEW |