Chromium Code Reviews| Index: frog/leg/ssa/nodes.dart |
| diff --git a/frog/leg/ssa/nodes.dart b/frog/leg/ssa/nodes.dart |
| index 27a8588cf14a1836f168c41508cb89034627a944..5449c5719425d5652fa2714358b8f4afe5ffe22e 100644 |
| --- a/frog/leg/ssa/nodes.dart |
| +++ b/frog/leg/ssa/nodes.dart |
| @@ -1585,15 +1585,15 @@ class HLoopBranch extends HConditionalBranch { |
| int flags = 0; |
| int start = 0; |
| int quoteChar = source.next(); |
| - if (quoteChar == '@'.charCodeAt(0)) { |
| + if (quoteChar == $AT) { |
| flags |= RAW; |
| start = 1; |
| quoteChar = source.next(); |
| } |
| - if (quoteChar == '\''.charCodeAt(0)) { |
| + if (quoteChar == $SQ) { |
| flags |= SINGLE_QUOTED; |
| } else { |
| - assert(quoteChar == '"'.charCodeAt(0)); |
| + assert(quoteChar == $DQ); |
| } |
| // String has one quote. Check it if has three. |
| // If it only have two, the string must be an empty string literal, |
| @@ -1634,6 +1634,7 @@ class HLoopBranch extends HConditionalBranch { |
| bool get isMultiLine() => (flags & MULTI_LINE) != 0; |
| bool get isRaw() => (flags & RAW) != 0; |
| String get quoteChar() => ((flags & SINGLE_QUOTED) != 0) ? "'" : '"'; |
| + int get quoteCharCode() => ((flags & SINGLE_QUOTED) != 0) ? $SQ : $DQ; |
| int get leftQuoteLength() => |
| hasLeftQuote ? (isRaw ? 1 : 0) + (isMultiLine ? 3 : 1) : 0; |
| @@ -1650,6 +1651,122 @@ class HLoopBranch extends HConditionalBranch { |
| bool isEmpty() => unquotedSource().isEmpty(); |
| + static int hexValue(int hexDigit) { |
| + // hexDigit is one of '0'..'9', 'A'..'F' and 'a'..'f'. |
| + if (hexDigit <= $9) { |
| + return hexDigit - $0; |
| + } |
| + // Make letters lowercase. |
| + hexDigit |= $a - $A; |
|
floitsch
2012/01/16 14:29:50
This "trick" depends on an ascii property where lo
Lasse Reichstein Nielsen
2012/01/17 08:50:51
I assume Unicode. There are no other encodings. FI
|
| + hexDigit -= $a - 10; |
| + assert(10 <= hexDigit && hexDigit <= 15); |
| + return hexDigit; |
| + } |
| + |
| + |
| + static void writeUnicodeEscape(Iterator<int> iter, StringBuffer buffer) { |
| + buffer.add(@'\u'); |
| + int code = iter.next(); |
| + if (code == $OPEN_CURLY_BRACKET) { |
| + // In Dart, '\u{'x{0..7}'}' is a valid escape, but not in |
| + // JS. Convert to a \uxxxx escape. |
| + int value = 0; |
| + int hexDigit = iter.next(); |
| + do { |
| + value = value * 16 + hexValue(hexDigit); |
| + hexDigit = iter.next(); |
| + } while (hexDigit !== $CLOSE_CURLY_BRACKET); // until '}'. |
|
floitsch
2012/01/16 14:29:50
remove comment.
Lasse Reichstein Nielsen
2012/01/17 08:50:51
Done.
|
| + // JavaScript only supports characters in the BMP. |
| + // TODO(lrn): Handle characters outside the BMP, e.g., |
| + // by having a slow-case string class. |
| + if (value > 0xffff) value = 0xfffd; |
|
floitsch
2012/01/16 14:29:50
I would prefer bailing out (compiler.cancel).
Lasse Reichstein Nielsen
2012/01/17 08:50:51
Done.
|
| + |
| + for (int j = 12; j >= 0; j -= 4) { |
| + int digit = (value >> j) & 0xf; |
| + buffer.add("0123456789abcdef"[digit]); |
| + } |
| + return; |
| + } |
| + for (int i = 0; i < 4; i++) { |
| + if (i > 0) code = iter.next(); |
| + buffer.add(new String.fromCharCodes([code])); |
| + } |
| + } |
| + |
| + /** |
| + * Write the contents of the quoted string to a [StringBuffer] in |
| + * a form that is valid as JavaScript string literal content. |
| + * The string is assumed quoted by [quote] characters. |
| + * This method doesn't try to make the shortest string, but rather |
| + * to be as close to the original string as possible. |
| + */ |
| + void writeEscaped(StringBuffer buffer, int quote) { |
| + bool raw = this.isRaw; |
| + Iterator<int> iter = |
| + wrappedString.copyWithoutQuotes(leftQuoteLength, |
| + rightQuoteLength).iterator(); |
| + while (iter.hasNext()) { |
| + int code = iter.next(); |
| + if (code == quote) { |
| + // We need to add a backslash before quotes, both in normal |
| + // and in raw strings. |
| + buffer.add(@'\'); |
| + buffer.add(code == $SQ ? "'" : '"'); |
| + } else if (code == $LF) { |
| + // Newlines in strings only occour in multiline strings. |
| + // They need to be written using escapes in JS.. |
| + assert(isMultiLine); |
| + buffer.add(@'\n'); |
| + } else if (code == $CR) { |
| + assert(isMultiLine); |
| + buffer.add(@'\r'); |
| + } else if (code == $LS || code == $PS) { |
| + // These Unicode line terminators are invalid in JS strings. |
| + buffer.add(code == $LS ? @'\u2028' : @'\u2029'); |
| + } else if (code != $BACKSLASH) { |
| + buffer.add(new String.fromCharCodes([code])); |
| + } else if (raw) { |
| + buffer.add(@'\\'); |
| + } else { |
| + code = iter.next(); |
| + switch (code) { |
| + case $u: |
| + writeUnicodeEscape(iter, buffer); |
| + break; |
| + case $x: |
| + buffer.add(@'\x'); |
| + // Remaining character will be copied literally. |
| + break; |
| + // Character escapes that identical in meaning in JS. |
| + case $b: buffer.add(@'\b'); break; |
| + case $f: buffer.add(@'\f'); break; |
| + case $n: buffer.add(@'\n'); break; |
| + case $r: buffer.add(@'\r'); break; |
| + case $t: buffer.add(@'\t'); break; |
| + case $v: buffer.add(@'\v'); break; |
| + // Identity escapes that must be escaped in JS strings. |
| + case $BACKSLASH: buffer.add(@'\\'); break; |
| + case $LF: buffer.add(@'\n'); break; |
| + case $CR: buffer.add(@'\r'); break; |
| + case $LS: buffer.add(@'\u2028'); break; |
| + case $PS: buffer.add(@'\u2029'); break; |
| + // Quotes may or may not need the escape. |
| + case $SQ: |
| + case $DQ: |
| + // Only escape quotes if they match the generated string quotes. |
| + if (code == quote) buffer.add(@'\'); |
| + buffer.add(code == $SQ ? "'" : '"'); |
| + break; |
| + default: |
| + // All other escaped characters are identity escapes, |
| + // and don't need a backslash in JS. |
| + buffer.add(new String.fromCharCodes([code])); |
| + break; |
| + } |
| + } |
| + } |
| + } |
| + |
| /** |
| * Does a conservative test for equality between two quoted strings. |
| * Returns true if the two definitly have the same string. |