Commit 83d9e6e7 authored by rossberg@chromium.org's avatar rossberg@chromium.org

Add support for explicit octal and binary integer literals

http://people.mozilla.org/~jorendorff/es6-draft.html#sec-7.8.3

ES6 extends the numeric literals to support explicit support
for binary and octal literals using the following syntax:

  0b10101
  0o777

This is currently behind the flag, --harmony-numeric-literals

BUG=2783
R=rossberg@chromium.org

Review URL: https://codereview.chromium.org/19300002

Patch from Erik Arvidsson <arv@chromium.org>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15772 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent d750a6dc
......@@ -71,6 +71,18 @@ inline bool IsHexDigit(uc32 c) {
}
inline bool IsOctalDigit(uc32 c) {
// ECMA-262, 6th, 7.8.3
return IsInRange(c, '0', '7');
}
inline bool IsBinaryDigit(uc32 c) {
// ECMA-262, 6th, 7.8.3
return c == '0' || c == '1';
}
inline bool IsRegExpWord(uc16 c) {
return IsInRange(AsciiAlphaToLower(c), 'a', 'z')
|| IsDecimalDigit(c)
......
......@@ -40,6 +40,8 @@ inline bool IsCarriageReturn(uc32 c);
inline bool IsLineFeed(uc32 c);
inline bool IsDecimalDigit(uc32 c);
inline bool IsHexDigit(uc32 c);
inline bool IsOctalDigit(uc32 c);
inline bool IsBinaryDigit(uc32 c);
inline bool IsRegExpWord(uc32 c);
inline bool IsRegExpNewline(uc32 c);
......
......@@ -515,6 +515,32 @@ double InternalStringToDouble(UnicodeCache* unicode_cache,
end,
false,
allow_trailing_junk);
// It could be an explicit octal value.
} else if ((flags & ALLOW_OCTAL) && (*current == 'o' || *current == 'O')) {
++current;
if (current == end || !isDigit(*current, 8) || sign != NONE) {
return JunkStringValue(); // "0o".
}
return InternalStringToIntDouble<3>(unicode_cache,
current,
end,
false,
allow_trailing_junk);
// It could be a binary value.
} else if ((flags & ALLOW_BINARY) && (*current == 'b' || *current == 'B')) {
++current;
if (current == end || !isBinaryDigit(*current) || sign != NONE) {
return JunkStringValue(); // "0b".
}
return InternalStringToIntDouble<1>(unicode_cache,
current,
end,
false,
allow_trailing_junk);
}
// Ignore leading zeros in the integer part.
......@@ -524,7 +550,7 @@ double InternalStringToDouble(UnicodeCache* unicode_cache,
}
}
bool octal = leading_zero && (flags & ALLOW_OCTALS) != 0;
bool octal = leading_zero && (flags & ALLOW_IMPLICIT_OCTAL) != 0;
// Copy significant digits of the integer part (if any) to the buffer.
while (*current >= '0' && *current <= '9') {
......
......@@ -52,6 +52,11 @@ inline bool isDigit(int x, int radix) {
}
inline bool isBinaryDigit(int x) {
return x == '0' || x == '1';
}
// The fast double-to-(unsigned-)int conversion routine does not guarantee
// rounding towards zero.
// For NaN and values outside the int range, return INT_MIN or INT_MAX.
......@@ -108,8 +113,10 @@ inline uint32_t DoubleToUint32(double x) {
enum ConversionFlags {
NO_FLAGS = 0,
ALLOW_HEX = 1,
ALLOW_OCTALS = 2,
ALLOW_TRAILING_JUNK = 4
ALLOW_OCTAL = 2,
ALLOW_IMPLICIT_OCTAL = 4,
ALLOW_BINARY = 8,
ALLOW_TRAILING_JUNK = 16
};
......
......@@ -171,6 +171,8 @@ DEFINE_bool(harmony_array_buffer, false,
DEFINE_implication(harmony_typed_arrays, harmony_array_buffer)
DEFINE_bool(harmony_generators, false, "enable harmony generators")
DEFINE_bool(harmony_iteration, false, "enable harmony iteration (for-of)")
DEFINE_bool(harmony_numeric_literals, false,
"enable harmony numeric literals (0o77, 0b11)")
DEFINE_bool(harmony, false, "enable all harmony features (except typeof)")
DEFINE_implication(harmony, harmony_scoping)
DEFINE_implication(harmony, harmony_modules)
......@@ -180,6 +182,7 @@ DEFINE_implication(harmony, harmony_collections)
DEFINE_implication(harmony, harmony_observation)
DEFINE_implication(harmony, harmony_generators)
DEFINE_implication(harmony, harmony_iteration)
DEFINE_implication(harmony, harmony_numeric_literals)
DEFINE_implication(harmony_modules, harmony_scoping)
DEFINE_implication(harmony_observation, harmony_collections)
// TODO[dslomov] add harmony => harmony_typed_arrays
......
......@@ -563,6 +563,7 @@ Parser::Parser(CompilationInfo* info)
set_allow_lazy(false); // Must be explicitly enabled.
set_allow_generators(FLAG_harmony_generators);
set_allow_for_of(FLAG_harmony_iteration);
set_allow_harmony_numeric_literals(FLAG_harmony_numeric_literals);
}
......@@ -3573,7 +3574,8 @@ Expression* Parser::ParsePrimaryExpression(bool* ok) {
ASSERT(scanner().is_literal_ascii());
double value = StringToDouble(isolate()->unicode_cache(),
scanner().literal_ascii_string(),
ALLOW_HEX | ALLOW_OCTALS);
ALLOW_HEX | ALLOW_OCTAL |
ALLOW_IMPLICIT_OCTAL | ALLOW_BINARY);
result = factory()->NewNumberLiteral(value);
break;
}
......@@ -4026,7 +4028,8 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
ASSERT(scanner().is_literal_ascii());
double value = StringToDouble(isolate()->unicode_cache(),
scanner().literal_ascii_string(),
ALLOW_HEX | ALLOW_OCTALS);
ALLOW_HEX | ALLOW_OCTAL |
ALLOW_IMPLICIT_OCTAL | ALLOW_BINARY);
key = factory()->NewNumberLiteral(value);
break;
}
......@@ -4581,6 +4584,8 @@ preparser::PreParser::PreParseResult Parser::LazyParseFunctionLiteral(
reusable_preparser_->set_allow_lazy(true);
reusable_preparser_->set_allow_generators(allow_generators());
reusable_preparser_->set_allow_for_of(allow_for_of());
reusable_preparser_->set_allow_harmony_numeric_literals(
allow_harmony_numeric_literals());
}
preparser::PreParser::PreParseResult result =
reusable_preparser_->PreParseLazyFunction(top_scope_->language_mode(),
......@@ -5850,6 +5855,7 @@ ScriptDataImpl* PreParserApi::PreParse(Utf16CharacterStream* source) {
preparser.set_allow_generators(FLAG_harmony_generators);
preparser.set_allow_for_of(FLAG_harmony_iteration);
preparser.set_allow_harmony_scoping(FLAG_harmony_scoping);
preparser.set_allow_harmony_numeric_literals(FLAG_harmony_numeric_literals);
scanner.Initialize(source);
preparser::PreParser::PreParseResult result = preparser.PreParseProgram();
if (result == preparser::PreParser::kPreParseStackOverflow) {
......
......@@ -438,6 +438,9 @@ class Parser BASE_EMBEDDED {
bool allow_harmony_scoping() { return scanner().HarmonyScoping(); }
bool allow_generators() const { return allow_generators_; }
bool allow_for_of() const { return allow_for_of_; }
bool allow_harmony_numeric_literals() {
return scanner().HarmonyNumericLiterals();
}
void set_allow_natives_syntax(bool allow) { allow_natives_syntax_ = allow; }
void set_allow_lazy(bool allow) { allow_lazy_ = allow; }
......@@ -447,6 +450,9 @@ class Parser BASE_EMBEDDED {
}
void set_allow_generators(bool allow) { allow_generators_ = allow; }
void set_allow_for_of(bool allow) { allow_for_of_ = allow; }
void set_allow_harmony_numeric_literals(bool allow) {
scanner().SetHarmonyNumericLiterals(allow);
}
// Parses the source code represented by the compilation info and sets its
// function literal. Returns false (and deallocates any allocated AST
......
......@@ -1724,7 +1724,8 @@ int DuplicateFinder::AddNumber(i::Vector<const char> key, int value) {
return AddAsciiSymbol(key, value);
}
int flags = i::ALLOW_HEX | i::ALLOW_OCTALS;
int flags = i::ALLOW_HEX | i::ALLOW_OCTAL | i::ALLOW_IMPLICIT_OCTAL |
i::ALLOW_BINARY;
double double_value = StringToDouble(unicode_constants_, key, flags, 0.0);
int length;
const char* string;
......
......@@ -141,6 +141,9 @@ class PreParser {
bool allow_harmony_scoping() const { return scanner_->HarmonyScoping(); }
bool allow_generators() const { return allow_generators_; }
bool allow_for_of() const { return allow_for_of_; }
bool allow_harmony_numeric_literals() const {
return scanner_->HarmonyNumericLiterals();
}
void set_allow_natives_syntax(bool allow) { allow_natives_syntax_ = allow; }
void set_allow_lazy(bool allow) { allow_lazy_ = allow; }
......@@ -150,6 +153,9 @@ class PreParser {
}
void set_allow_generators(bool allow) { allow_generators_ = allow; }
void set_allow_for_of(bool allow) { allow_for_of_ = allow; }
void set_allow_harmony_numeric_literals(bool allow) {
scanner_->SetHarmonyNumericLiterals(allow);
}
// Pre-parse the program from the character stream; returns true on
// success (even if parsing failed, the pre-parse data successfully
......
......@@ -5959,8 +5959,14 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToNumber) {
}
// Slower case.
int flags = ALLOW_HEX;
if (FLAG_harmony_numeric_literals) {
// The current spec draft has not updated "ToNumber Applied to the String
// Type", https://bugs.ecmascript.org/show_bug.cgi?id=1584
flags |= ALLOW_OCTAL | ALLOW_BINARY;
}
return isolate->heap()->NumberFromDouble(
StringToDouble(isolate->unicode_cache(), subject, ALLOW_HEX));
StringToDouble(isolate->unicode_cache(), subject, flags));
}
......
......@@ -42,7 +42,8 @@ Scanner::Scanner(UnicodeCache* unicode_cache)
: unicode_cache_(unicode_cache),
octal_pos_(Location::invalid()),
harmony_scoping_(false),
harmony_modules_(false) { }
harmony_modules_(false),
harmony_numeric_literals_(false) { }
void Scanner::Initialize(Utf16CharacterStream* source) {
......@@ -719,7 +720,7 @@ void Scanner::ScanDecimalDigits() {
Token::Value Scanner::ScanNumber(bool seen_period) {
ASSERT(IsDecimalDigit(c0_)); // the first digit of the number or the fraction
enum { DECIMAL, HEX, OCTAL } kind = DECIMAL;
enum { DECIMAL, HEX, OCTAL, IMPLICIT_OCTAL, BINARY } kind = DECIMAL;
LiteralScope literal(this);
if (seen_period) {
......@@ -733,7 +734,8 @@ Token::Value Scanner::ScanNumber(bool seen_period) {
int start_pos = source_pos(); // For reporting octal positions.
AddLiteralCharAdvance();
// either 0, 0exxx, 0Exxx, 0.xxx, an octal number, or a hex number
// either 0, 0exxx, 0Exxx, 0.xxx, a hex number, a binary number or
// an octal number.
if (c0_ == 'x' || c0_ == 'X') {
// hex number
kind = HEX;
......@@ -745,9 +747,29 @@ Token::Value Scanner::ScanNumber(bool seen_period) {
while (IsHexDigit(c0_)) {
AddLiteralCharAdvance();
}
} else if (harmony_numeric_literals_ && (c0_ == 'o' || c0_ == 'O')) {
kind = OCTAL;
AddLiteralCharAdvance();
if (!IsOctalDigit(c0_)) {
// we must have at least one octal digit after 'o'/'O'
return Token::ILLEGAL;
}
while (IsOctalDigit(c0_)) {
AddLiteralCharAdvance();
}
} else if (harmony_numeric_literals_ && (c0_ == 'b' || c0_ == 'B')) {
kind = BINARY;
AddLiteralCharAdvance();
if (!IsBinaryDigit(c0_)) {
// we must have at least one binary digit after 'b'/'B'
return Token::ILLEGAL;
}
while (IsBinaryDigit(c0_)) {
AddLiteralCharAdvance();
}
} else if ('0' <= c0_ && c0_ <= '7') {
// (possible) octal number
kind = OCTAL;
kind = IMPLICIT_OCTAL;
while (true) {
if (c0_ == '8' || c0_ == '9') {
kind = DECIMAL;
......@@ -776,7 +798,7 @@ Token::Value Scanner::ScanNumber(bool seen_period) {
// scan exponent, if any
if (c0_ == 'e' || c0_ == 'E') {
ASSERT(kind != HEX); // 'e'/'E' must be scanned as part of the hex number
if (kind == OCTAL) return Token::ILLEGAL; // no exponent for octals allowed
if (kind != DECIMAL) return Token::ILLEGAL;
// scan exponent
AddLiteralCharAdvance();
if (c0_ == '+' || c0_ == '-')
......
......@@ -408,7 +408,12 @@ class Scanner {
void SetHarmonyModules(bool modules) {
harmony_modules_ = modules;
}
bool HarmonyNumericLiterals() const {
return harmony_numeric_literals_;
}
void SetHarmonyNumericLiterals(bool numeric_literals) {
harmony_numeric_literals_ = numeric_literals;
}
// Returns true if there was a line terminator before the peek'ed token,
// possibly inside a multi-line comment.
......@@ -557,6 +562,8 @@ class Scanner {
bool harmony_scoping_;
// Whether we scan 'module', 'import', 'export' as keywords.
bool harmony_modules_;
// Whether we scan 0o777 and 0b111 as numbers.
bool harmony_numeric_literals_;
};
} } // namespace v8::internal
......
......@@ -37,12 +37,14 @@ using namespace v8::internal;
TEST(Hex) {
UnicodeCache uc;
CHECK_EQ(0.0, StringToDouble(&uc, "0x0", ALLOW_HEX | ALLOW_OCTALS));
CHECK_EQ(0.0, StringToDouble(&uc, "0X0", ALLOW_HEX | ALLOW_OCTALS));
CHECK_EQ(1.0, StringToDouble(&uc, "0x1", ALLOW_HEX | ALLOW_OCTALS));
CHECK_EQ(16.0, StringToDouble(&uc, "0x10", ALLOW_HEX | ALLOW_OCTALS));
CHECK_EQ(255.0, StringToDouble(&uc, "0xff", ALLOW_HEX | ALLOW_OCTALS));
CHECK_EQ(175.0, StringToDouble(&uc, "0xAF", ALLOW_HEX | ALLOW_OCTALS));
CHECK_EQ(0.0, StringToDouble(&uc, "0x0", ALLOW_HEX | ALLOW_IMPLICIT_OCTAL));
CHECK_EQ(0.0, StringToDouble(&uc, "0X0", ALLOW_HEX | ALLOW_IMPLICIT_OCTAL));
CHECK_EQ(1.0, StringToDouble(&uc, "0x1", ALLOW_HEX | ALLOW_IMPLICIT_OCTAL));
CHECK_EQ(16.0, StringToDouble(&uc, "0x10", ALLOW_HEX | ALLOW_IMPLICIT_OCTAL));
CHECK_EQ(255.0, StringToDouble(&uc, "0xff",
ALLOW_HEX | ALLOW_IMPLICIT_OCTAL));
CHECK_EQ(175.0, StringToDouble(&uc, "0xAF",
ALLOW_HEX | ALLOW_IMPLICIT_OCTAL));
CHECK_EQ(0.0, StringToDouble(&uc, "0x0", ALLOW_HEX));
CHECK_EQ(0.0, StringToDouble(&uc, "0X0", ALLOW_HEX));
......@@ -55,12 +57,32 @@ TEST(Hex) {
TEST(Octal) {
UnicodeCache uc;
CHECK_EQ(0.0, StringToDouble(&uc, "0", ALLOW_HEX | ALLOW_OCTALS));
CHECK_EQ(0.0, StringToDouble(&uc, "00", ALLOW_HEX | ALLOW_OCTALS));
CHECK_EQ(1.0, StringToDouble(&uc, "01", ALLOW_HEX | ALLOW_OCTALS));
CHECK_EQ(7.0, StringToDouble(&uc, "07", ALLOW_HEX | ALLOW_OCTALS));
CHECK_EQ(8.0, StringToDouble(&uc, "010", ALLOW_HEX | ALLOW_OCTALS));
CHECK_EQ(63.0, StringToDouble(&uc, "077", ALLOW_HEX | ALLOW_OCTALS));
CHECK_EQ(0.0, StringToDouble(&uc, "0o0", ALLOW_OCTAL | ALLOW_IMPLICIT_OCTAL));
CHECK_EQ(0.0, StringToDouble(&uc, "0O0", ALLOW_OCTAL | ALLOW_IMPLICIT_OCTAL));
CHECK_EQ(1.0, StringToDouble(&uc, "0o1", ALLOW_OCTAL | ALLOW_IMPLICIT_OCTAL));
CHECK_EQ(7.0, StringToDouble(&uc, "0o7", ALLOW_OCTAL | ALLOW_IMPLICIT_OCTAL));
CHECK_EQ(8.0, StringToDouble(&uc, "0o10",
ALLOW_OCTAL | ALLOW_IMPLICIT_OCTAL));
CHECK_EQ(63.0, StringToDouble(&uc, "0o77",
ALLOW_OCTAL | ALLOW_IMPLICIT_OCTAL));
CHECK_EQ(0.0, StringToDouble(&uc, "0o0", ALLOW_OCTAL));
CHECK_EQ(0.0, StringToDouble(&uc, "0O0", ALLOW_OCTAL));
CHECK_EQ(1.0, StringToDouble(&uc, "0o1", ALLOW_OCTAL));
CHECK_EQ(7.0, StringToDouble(&uc, "0o7", ALLOW_OCTAL));
CHECK_EQ(8.0, StringToDouble(&uc, "0o10", ALLOW_OCTAL));
CHECK_EQ(63.0, StringToDouble(&uc, "0o77", ALLOW_OCTAL));
}
TEST(ImplicitOctal) {
UnicodeCache uc;
CHECK_EQ(0.0, StringToDouble(&uc, "0", ALLOW_HEX | ALLOW_IMPLICIT_OCTAL));
CHECK_EQ(0.0, StringToDouble(&uc, "00", ALLOW_HEX | ALLOW_IMPLICIT_OCTAL));
CHECK_EQ(1.0, StringToDouble(&uc, "01", ALLOW_HEX | ALLOW_IMPLICIT_OCTAL));
CHECK_EQ(7.0, StringToDouble(&uc, "07", ALLOW_HEX | ALLOW_IMPLICIT_OCTAL));
CHECK_EQ(8.0, StringToDouble(&uc, "010", ALLOW_HEX | ALLOW_IMPLICIT_OCTAL));
CHECK_EQ(63.0, StringToDouble(&uc, "077", ALLOW_HEX | ALLOW_IMPLICIT_OCTAL));
CHECK_EQ(0.0, StringToDouble(&uc, "0", ALLOW_HEX));
CHECK_EQ(0.0, StringToDouble(&uc, "00", ALLOW_HEX));
......@@ -71,26 +93,53 @@ TEST(Octal) {
const double x = 010000000000; // Power of 2, no rounding errors.
CHECK_EQ(x * x * x * x * x, StringToDouble(&uc, "01" "0000000000" "0000000000"
"0000000000" "0000000000" "0000000000", ALLOW_OCTALS));
"0000000000" "0000000000" "0000000000", ALLOW_IMPLICIT_OCTAL));
}
TEST(MalformedOctal) {
TEST(Binary) {
UnicodeCache uc;
CHECK_EQ(8.0, StringToDouble(&uc, "08", ALLOW_HEX | ALLOW_OCTALS));
CHECK_EQ(81.0, StringToDouble(&uc, "081", ALLOW_HEX | ALLOW_OCTALS));
CHECK_EQ(78.0, StringToDouble(&uc, "078", ALLOW_HEX | ALLOW_OCTALS));
CHECK(std::isnan(StringToDouble(&uc, "07.7", ALLOW_HEX | ALLOW_OCTALS)));
CHECK(std::isnan(StringToDouble(&uc, "07.8", ALLOW_HEX | ALLOW_OCTALS)));
CHECK(std::isnan(StringToDouble(&uc, "07e8", ALLOW_HEX | ALLOW_OCTALS)));
CHECK(std::isnan(StringToDouble(&uc, "07e7", ALLOW_HEX | ALLOW_OCTALS)));
CHECK_EQ(0.0, StringToDouble(&uc, "0b0",
ALLOW_BINARY | ALLOW_IMPLICIT_OCTAL));
CHECK_EQ(0.0, StringToDouble(&uc, "0B0",
ALLOW_BINARY | ALLOW_IMPLICIT_OCTAL));
CHECK_EQ(1.0, StringToDouble(&uc, "0b1",
ALLOW_BINARY | ALLOW_IMPLICIT_OCTAL));
CHECK_EQ(2.0, StringToDouble(&uc, "0b10",
ALLOW_BINARY | ALLOW_IMPLICIT_OCTAL));
CHECK_EQ(3.0, StringToDouble(&uc, "0b11",
ALLOW_BINARY | ALLOW_IMPLICIT_OCTAL));
CHECK_EQ(0.0, StringToDouble(&uc, "0b0", ALLOW_BINARY));
CHECK_EQ(0.0, StringToDouble(&uc, "0B0", ALLOW_BINARY));
CHECK_EQ(1.0, StringToDouble(&uc, "0b1", ALLOW_BINARY));
CHECK_EQ(2.0, StringToDouble(&uc, "0b10", ALLOW_BINARY));
CHECK_EQ(3.0, StringToDouble(&uc, "0b11", ALLOW_BINARY));
}
CHECK_EQ(8.7, StringToDouble(&uc, "08.7", ALLOW_HEX | ALLOW_OCTALS));
CHECK_EQ(8e7, StringToDouble(&uc, "08e7", ALLOW_HEX | ALLOW_OCTALS));
CHECK_EQ(0.001, StringToDouble(&uc, "0.001", ALLOW_HEX | ALLOW_OCTALS));
CHECK_EQ(0.713, StringToDouble(&uc, "0.713", ALLOW_HEX | ALLOW_OCTALS));
TEST(MalformedOctal) {
UnicodeCache uc;
CHECK_EQ(8.0, StringToDouble(&uc, "08", ALLOW_HEX | ALLOW_IMPLICIT_OCTAL));
CHECK_EQ(81.0, StringToDouble(&uc, "081", ALLOW_HEX | ALLOW_IMPLICIT_OCTAL));
CHECK_EQ(78.0, StringToDouble(&uc, "078", ALLOW_HEX | ALLOW_IMPLICIT_OCTAL));
CHECK(std::isnan(StringToDouble(&uc, "07.7",
ALLOW_HEX | ALLOW_IMPLICIT_OCTAL)));
CHECK(std::isnan(StringToDouble(&uc, "07.8",
ALLOW_HEX | ALLOW_IMPLICIT_OCTAL)));
CHECK(std::isnan(StringToDouble(&uc, "07e8",
ALLOW_HEX | ALLOW_IMPLICIT_OCTAL)));
CHECK(std::isnan(StringToDouble(&uc, "07e7",
ALLOW_HEX | ALLOW_IMPLICIT_OCTAL)));
CHECK_EQ(8.7, StringToDouble(&uc, "08.7", ALLOW_HEX | ALLOW_IMPLICIT_OCTAL));
CHECK_EQ(8e7, StringToDouble(&uc, "08e7", ALLOW_HEX | ALLOW_IMPLICIT_OCTAL));
CHECK_EQ(0.001, StringToDouble(&uc, "0.001",
ALLOW_HEX | ALLOW_IMPLICIT_OCTAL));
CHECK_EQ(0.713, StringToDouble(&uc, "0.713",
ALLOW_HEX | ALLOW_IMPLICIT_OCTAL));
CHECK_EQ(8.0, StringToDouble(&uc, "08", ALLOW_HEX));
CHECK_EQ(81.0, StringToDouble(&uc, "081", ALLOW_HEX));
......@@ -112,12 +161,12 @@ TEST(MalformedOctal) {
TEST(TrailingJunk) {
UnicodeCache uc;
CHECK_EQ(8.0, StringToDouble(&uc, "8q", ALLOW_TRAILING_JUNK));
CHECK_EQ(63.0,
StringToDouble(&uc, "077qqq", ALLOW_OCTALS | ALLOW_TRAILING_JUNK));
CHECK_EQ(10.0,
StringToDouble(&uc, "10e", ALLOW_OCTALS | ALLOW_TRAILING_JUNK));
CHECK_EQ(10.0,
StringToDouble(&uc, "10e-", ALLOW_OCTALS | ALLOW_TRAILING_JUNK));
CHECK_EQ(63.0, StringToDouble(&uc, "077qqq",
ALLOW_IMPLICIT_OCTAL | ALLOW_TRAILING_JUNK));
CHECK_EQ(10.0, StringToDouble(&uc, "10e",
ALLOW_IMPLICIT_OCTAL | ALLOW_TRAILING_JUNK));
CHECK_EQ(10.0, StringToDouble(&uc, "10e-",
ALLOW_IMPLICIT_OCTAL | ALLOW_TRAILING_JUNK));
}
......@@ -144,12 +193,14 @@ TEST(IntegerStrLiteral) {
CHECK(std::isnan(StringToDouble(&uc, " - 1 ", NO_FLAGS)));
CHECK(std::isnan(StringToDouble(&uc, " + 1 ", NO_FLAGS)));
CHECK_EQ(0.0, StringToDouble(&uc, "0e0", ALLOW_HEX | ALLOW_OCTALS));
CHECK_EQ(0.0, StringToDouble(&uc, "0e1", ALLOW_HEX | ALLOW_OCTALS));
CHECK_EQ(0.0, StringToDouble(&uc, "0e-1", ALLOW_HEX | ALLOW_OCTALS));
CHECK_EQ(0.0, StringToDouble(&uc, "0e-100000", ALLOW_HEX | ALLOW_OCTALS));
CHECK_EQ(0.0, StringToDouble(&uc, "0e+100000", ALLOW_HEX | ALLOW_OCTALS));
CHECK_EQ(0.0, StringToDouble(&uc, "0.", ALLOW_HEX | ALLOW_OCTALS));
CHECK_EQ(0.0, StringToDouble(&uc, "0e0", ALLOW_HEX | ALLOW_IMPLICIT_OCTAL));
CHECK_EQ(0.0, StringToDouble(&uc, "0e1", ALLOW_HEX | ALLOW_IMPLICIT_OCTAL));
CHECK_EQ(0.0, StringToDouble(&uc, "0e-1", ALLOW_HEX | ALLOW_IMPLICIT_OCTAL));
CHECK_EQ(0.0, StringToDouble(&uc, "0e-100000",
ALLOW_HEX | ALLOW_IMPLICIT_OCTAL));
CHECK_EQ(0.0, StringToDouble(&uc, "0e+100000",
ALLOW_HEX | ALLOW_IMPLICIT_OCTAL));
CHECK_EQ(0.0, StringToDouble(&uc, "0.", ALLOW_HEX | ALLOW_IMPLICIT_OCTAL));
}
......
......@@ -1086,6 +1086,7 @@ enum ParserFlag {
kAllowModules,
kAllowGenerators,
kAllowForOf,
kAllowHarmonyNumericLiterals,
kParserFlagCount
};
......@@ -1103,7 +1104,9 @@ static bool checkParserFlag(unsigned flags, ParserFlag flag) {
kAllowHarmonyScoping)); \
parser.set_allow_modules(checkParserFlag(flags, kAllowModules)); \
parser.set_allow_generators(checkParserFlag(flags, kAllowGenerators)); \
parser.set_allow_for_of(checkParserFlag(flags, kAllowForOf));
parser.set_allow_for_of(checkParserFlag(flags, kAllowForOf)); \
parser.set_allow_harmony_numeric_literals( \
checkParserFlag(flags, kAllowHarmonyNumericLiterals));
void TestParserSyncWithFlags(i::Handle<i::String> source, unsigned flags) {
i::Isolate* isolate = i::Isolate::Current();
......
// Copyright 2013 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// This is to ensure that we do not support 0b and 0o in Number when
// the --harmony-numeric-literals flag is not set.
function TestOctalLiteralUsingNumberFunction() {
assertEquals(NaN, Number('0o0'));
}
TestOctalLiteralUsingNumberFunction();
function TestBinaryLiteralUsingNumberFunction() {
assertEquals(NaN, Number('0b0'));
}
TestBinaryLiteralUsingNumberFunction();
// Copyright 2013 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --harmony-numeric-literals
function TestOctalLiteral() {
assertEquals(0, 0o0);
assertEquals(0, 0O0);
assertEquals(1, 0o1);
assertEquals(7, 0o7);
assertEquals(8, 0o10);
assertEquals(63, 0o77);
}
TestOctalLiteral();
function TestOctalLiteralUsingNumberFunction() {
assertEquals(0, Number('0o0'));
assertEquals(0, Number('0O0'));
assertEquals(1, Number('0o1'));
assertEquals(7, Number('0o7'));
assertEquals(8, Number('0o10'));
assertEquals(63, Number('0o77'));
}
TestOctalLiteralUsingNumberFunction();
function TestBinaryLiteral() {
assertEquals(0, 0b0);
assertEquals(0, 0B0);
assertEquals(1, 0b1);
assertEquals(2, 0b10);
assertEquals(3, 0b11);
}
TestBinaryLiteral();
function TestBinaryLiteralUsingNumberFunction() {
assertEquals(0, Number('0b0'));
assertEquals(0, Number('0B0'));
assertEquals(1, Number('0b1'));
assertEquals(2, Number('0b10'));
assertEquals(3, Number('0b11'));
}
TestBinaryLiteralUsingNumberFunction();
// parseInt should (probably) not support 0b and 0o.
// https://bugs.ecmascript.org/show_bug.cgi?id=1585
function TestParseIntDoesNotSupportOctalNorBinary() {
assertEquals(0, parseInt('0o77'));
assertEquals(0, parseInt('0o77', 8));
assertEquals(0, parseInt('0b11'));
assertEquals(0, parseInt('0b11', 2));
}
TestParseIntDoesNotSupportOctalNorBinary();
function TestParseFloatDoesNotSupportOctalNorBinary() {
assertEquals(0, parseFloat('0o77'));
assertEquals(0, parseFloat('0b11'));
}
TestParseFloatDoesNotSupportOctalNorBinary();
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment