| Index: frog/leg/ssa/nodes.dart
|
| diff --git a/frog/leg/ssa/nodes.dart b/frog/leg/ssa/nodes.dart
|
| index a797aef036016140af31eb94a672cc051f6d1b3c..f24a44cd94f142261e2ef7d3d44e7464b6d93998 100644
|
| --- a/frog/leg/ssa/nodes.dart
|
| +++ b/frog/leg/ssa/nodes.dart
|
| @@ -1556,281 +1556,6 @@ class HLoopBranch extends HConditionalBranch {
|
| }
|
| }
|
|
|
| -/**
|
| - * A wrapper around a SourceString that stores extra information about
|
| - * the (potentially implicit) quoting style of the original string.
|
| - * For most strings, the quotes are included in the [wrappedString], but
|
| - * parts of strings from a string interpolation might be missing one or
|
| - * both quotes.
|
| - */
|
| -class QuotedString {
|
| - // Bits of flag values.
|
| - static final int NO_FLAGS = 0;
|
| - static final int RAW = 1 << 0;
|
| - static final int MULTI_LINE = 1 << 1;
|
| - static final int HAS_LEFT_QUOTE = 1 << 2;
|
| - static final int HAS_RIGHT_QUOTE = 1 << 3;
|
| - static final int HAS_BOTH_QUOTES = HAS_LEFT_QUOTE | HAS_RIGHT_QUOTE;
|
| - // Whether the string uses single quotes ('). Default is double quotes (").
|
| - static final int SINGLE_QUOTED = 1 << 4;
|
| -
|
| - final SourceString wrappedString;
|
| - final int flags;
|
| -
|
| - /**
|
| - * Finds the quote type for a string given a part of it containing the
|
| - * starting quote. Returns flags, but doesn't include HAS_LEFT_QUOTE
|
| - * or HAS_RIGHT_QUOTE.
|
| - */
|
| - static int flagsFromLeftQuote(SourceString sourceString) {
|
| - Iterator<int> source = sourceString.iterator();
|
| - int flags = 0;
|
| - int start = 0;
|
| - int quoteChar = source.next();
|
| - if (quoteChar == $AT) {
|
| - flags |= RAW;
|
| - start = 1;
|
| - quoteChar = source.next();
|
| - }
|
| - if (quoteChar == $SQ) {
|
| - flags |= SINGLE_QUOTED;
|
| - } else {
|
| - 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,
|
| - // and end after the second quote.
|
| - if (source.hasNext() && source.next() == quoteChar && source.hasNext()) {
|
| - assert(source.next() == quoteChar);
|
| - flags |= MULTI_LINE;
|
| - }
|
| - return flags;
|
| - }
|
| -
|
| - const QuotedString(this.wrappedString, this.flags);
|
| -
|
| - // TODO(lrn): Make flags RAW for a literal string when we support it.
|
| - QuotedString.literal(String string) :
|
| - this(new SourceString(string), NO_FLAGS);
|
| -
|
| - /**
|
| - * Crates a [QuotedString] from a [SourceString] that contains
|
| - * both its quotes.
|
| - */
|
| - factory QuotedString.explicit(SourceString string) {
|
| - int flags = flagsFromLeftQuote(string);
|
| - int leftQuotes = leftQuoteLengthFromFlags(flags | HAS_LEFT_QUOTE);
|
| - int rightQuotes = rightQuoteLengthFromFlags(flags | HAS_RIGHT_QUOTE);
|
| - SourceString unquoted = string.copyWithoutQuotes(leftQuotes, rightQuotes);
|
| - return new QuotedString(unquoted, flags);
|
| - }
|
| -
|
| - SourceString unquotedSource() {
|
| - if ((flags & HAS_BOTH_QUOTES) == 0) return wrappedString;
|
| - return wrappedString.copyWithoutQuotes(leftQuoteLength,
|
| - rightQuoteLength);
|
| - }
|
| -
|
| - bool get hasLeftQuote() => (flags & HAS_LEFT_QUOTE) != 0;
|
| - bool get hasRightQuote() => (flags & HAS_RIGHT_QUOTE) != 0;
|
| - 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;
|
| - int get rightQuoteLength() =>
|
| - hasRightQuote ? (isMultiLine ? 3 : 1) : 0;
|
| - static int leftQuoteLengthFromFlags(int flags) {
|
| - if ((flags & HAS_LEFT_QUOTE) == 0) return 0;
|
| - return (flags & (RAW | MULTI_LINE)) + 1;
|
| - }
|
| - static int rightQuoteLengthFromFlags(int flags) {
|
| - if ((flags & HAS_RIGHT_QUOTE) == 0) return 0;
|
| - return (flags & MULTI_LINE) + 1;
|
| - }
|
| -
|
| - 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;
|
| - hexDigit -= $a - 10;
|
| - assert(10 <= hexDigit && hexDigit <= 15);
|
| - return hexDigit;
|
| - }
|
| -
|
| - static bool isHexDigit(int characterCode) {
|
| - if ($0 <= characterCode && characterCode <= $9) return true;
|
| - characterCode |= $a ^ $A;
|
| - return ($a <= characterCode && characterCode <= $f);
|
| - }
|
| -
|
| - static int readUnicodeEscape(Iterator<int> iter,
|
| - void cancel(String s)) {
|
| - if (!iter.hasNext()) cancel("Incomplete unicode escape.");
|
| - 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 length = 0;
|
| - if (!iter.hasNext()) cancel("Incomplete unicode escape.");
|
| - int hexDigit = iter.next();
|
| - do {
|
| - if (!isHexDigit(hexDigit)) {
|
| - cancel("Invalid character in unicode escape");
|
| - }
|
| - value = value * 16 + hexValue(hexDigit);
|
| - length++;
|
| - if (length > 7) {
|
| - cancel("Invalid unicode escape length.");
|
| - }
|
| - if (!iter.hasNext()) cancel("Incomplete unicode escape.");
|
| - hexDigit = iter.next();
|
| - } while (hexDigit !== $CLOSE_CURLY_BRACKET); // until '}'.
|
| - return value;
|
| - }
|
| - // Simple four-digit unicode escape.
|
| - int value = 0;
|
| - for (int i = 0; i < 4; i++) {
|
| - if (i > 0) {
|
| - if (!iter.hasNext()) cancel("Incomplete unicode escape.");
|
| - code = iter.next();
|
| - }
|
| - if (!isHexDigit(code)) cancel("Invalid character in unicode escape");
|
| - value = value * 16 + hexValue(code);
|
| - }
|
| - return value;
|
| - }
|
| -
|
| - /**
|
| - * 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, void cancel(String s)) {
|
| - 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();
|
| - // TODO(lrn): Reading \x and \u escapes also validates the
|
| - // escape sequences. This should be done at an earlier step
|
| - // to catch errors even in dead code.
|
| - switch (code) {
|
| - case $u:
|
| - int value = readUnicodeEscape(iter, cancel);
|
| - if (value >= 0xD800 && value <= 0xDFFF || value > 0x10ffff) {
|
| - cancel('Invalid unicode scalar value.');
|
| - }
|
| - if (value > 0xffff) {
|
| - cancel('Unhandled Unicode value: $value - outside the BMP.');
|
| - }
|
| - buffer.add(@'\u');
|
| - for (int j = 12; j >= 0; j -= 4) {
|
| - int digit = (value >> j) & 0xf;
|
| - buffer.add("0123456789abcdef"[digit]);
|
| - }
|
| - break;
|
| - case $x:
|
| - buffer.add(@'\x');
|
| - List<int> codes = <int>[];
|
| - for (int i = 0; i < 2; i++) {
|
| - if (!iter.hasNext()) cancel("Incomplete hex escape");
|
| - code = iter.next();
|
| - if (!isHexDigit(code)) {
|
| - cancel("Invalid hex digit: " +
|
| - "${new String.fromCharCodes([code])}");
|
| - }
|
| - codes.add(code);
|
| - }
|
| - buffer.add(new String.fromCharCodes(codes));
|
| - 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.
|
| - * Returns false if the strings are different, or if it's not possible
|
| - * to (quickly) determine whether they are equal.
|
| - */
|
| - bool definitlyEquals(QuotedString other) {
|
| - return flags == other.flags && wrappedString == other.wrappedString;
|
| - }
|
| -
|
| - void printOn(StringBuffer buffer) {
|
| - int start = leftQuoteLength;
|
| - int end = rightQuoteLength;
|
| - if (start == 1 && end == 1) {
|
| - wrappedString.printOn(buffer);
|
| - } else {
|
| - String quote = quoteChar;
|
| - buffer.add(quote);
|
| - wrappedString.copyWithoutQuotes(start, end).printOn(buffer);
|
| - buffer.add(quote);
|
| - }
|
| - }
|
| -}
|
| -
|
| class HLiteral extends HInstruction {
|
| final value;
|
| HLiteral(this.value, HType type) : super(<HInstruction>[]) {
|
|
|