From 924a8fff6bc517519eb91ca73adf06505b3f5a87 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 14 Feb 2017 14:24:25 +0000 Subject: Fix exponentional notation in number literals --- Changelog.md | 1 + libsolidity/ast/Types.cpp | 31 +++++++++++++++++++++++++++---- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/Changelog.md b/Changelog.md index 212d84fa..4135a3b7 100644 --- a/Changelog.md +++ b/Changelog.md @@ -5,6 +5,7 @@ Features: * Introduce ``.transfer(value)`` for sending Ether. * Code generator: Support ``revert()`` to abort with rolling back, but not consuming all gas. * Inline assembly: Support ``revert`` (EIP140) as an opcode. + * Parser: Support scientific notation in numbers (e.g. ``2e8`` and ``200e-2``). * Type system: Support explicit conversion of external function to address. Bugfixes: diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index d2793b6d..aecf830d 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -576,11 +576,31 @@ tuple RationalNumberType::isValidLiteral(Literal const& _literal rational x; try { - rational numerator; - rational denominator(1); - + auto expPoint = find(_literal.value().begin(), _literal.value().end(), 'e'); + if (expPoint == _literal.value().end()) + expPoint = find(_literal.value().begin(), _literal.value().end(), 'E'); auto radixPoint = find(_literal.value().begin(), _literal.value().end(), '.'); - if (radixPoint != _literal.value().end()) + + if (expPoint != _literal.value().end()) + { + if ( + !all_of(_literal.value().begin(), expPoint, ::isdigit) || + !all_of(expPoint + 1, _literal.value().end(), ::isdigit) + ) + return make_tuple(false, rational(0)); + + bigint exp = bigint(string(expPoint + 1, _literal.value().end())); + + if (exp > numeric_limits::max() || exp < numeric_limits::min()) + return make_tuple(false, rational(0)); + + x = bigint(string(_literal.value().begin(), expPoint)); + x *= boost::multiprecision::pow( + bigint(10), + exp.convert_to() + ); + } + else if (radixPoint != _literal.value().end()) { if ( !all_of(radixPoint + 1, _literal.value().end(), ::isdigit) || @@ -594,6 +614,9 @@ tuple RationalNumberType::isValidLiteral(Literal const& _literal [](char const& a) { return a == '0'; } ); + rational numerator; + rational denominator(1); + denominator = bigint(string(fractionalBegin, _literal.value().end())); denominator /= boost::multiprecision::pow( bigint(10), -- cgit v1.2.3 From 6014c3fe16e2d4c42c1bd710661885a5f787a715 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 14 Feb 2017 14:58:04 +0000 Subject: Add tests for scientific notation --- test/libsolidity/SolidityEndToEndTest.cpp | 17 +++++++++++++++ test/libsolidity/SolidityNameAndTypeResolution.cpp | 24 ---------------------- test/libsolidity/SolidityParser.cpp | 14 +++++++++++++ test/libsolidity/SolidityScanner.cpp | 17 ++++++++++++++- 4 files changed, 47 insertions(+), 25 deletions(-) diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index baed3f1e..21d9074d 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -9176,6 +9176,23 @@ BOOST_AUTO_TEST_CASE(revert) BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(42))); } +BOOST_AUTO_TEST_CASE(scientific_notation) +{ + char const* sourceCode = R"( + contract C { + function f() returns (uint) { + return 2e10 wei; + } + function g() returns (uint) { + return 200e-2 wei; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(20000000000))); + BOOST_CHECK(callContractFunction("g()") == encodeArgs(u256(2))); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index dda7105c..fc5966af 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -2682,18 +2682,6 @@ BOOST_AUTO_TEST_CASE(literal_strings) CHECK_SUCCESS(text); } -BOOST_AUTO_TEST_CASE(invalid_integer_literal_exp) -{ - char const* text = R"( - contract Foo { - function f() { - var x = 1e2; - } - } - )"; - CHECK_ERROR(text, TypeError, ""); -} - BOOST_AUTO_TEST_CASE(memory_structs_with_mappings) { char const* text = R"( @@ -4843,18 +4831,6 @@ BOOST_AUTO_TEST_CASE(external_function_type_to_uint) CHECK_ERROR(text, TypeError, "Explicit type conversion not allowed"); } -BOOST_AUTO_TEST_CASE(invalid_fixed_point_literal) -{ - char const* text = R"( - contract A { - function a() { - .8E0; - } - } - )"; - CHECK_ERROR(text, TypeError, ""); -} - BOOST_AUTO_TEST_CASE(shift_constant_left_negative_rvalue) { char const* text = R"( diff --git a/test/libsolidity/SolidityParser.cpp b/test/libsolidity/SolidityParser.cpp index e5362e78..cfc76ae0 100644 --- a/test/libsolidity/SolidityParser.cpp +++ b/test/libsolidity/SolidityParser.cpp @@ -1479,6 +1479,20 @@ BOOST_AUTO_TEST_CASE(function_type_state_variable) BOOST_CHECK(successParse(text)); } +BOOST_AUTO_TEST_CASE(scientific_notation) +{ + char const* text = R"( + contract test { + uint256 a = 2e10; + uint256 b = 2E10; + uint256 c = 200e-2; + uint256 d = 2E10 wei; + } + )"; + BOOST_CHECK(successParse(text)); +} + + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/SolidityScanner.cpp b/test/libsolidity/SolidityScanner.cpp index 3a5c6f24..020bce7f 100644 --- a/test/libsolidity/SolidityScanner.cpp +++ b/test/libsolidity/SolidityScanner.cpp @@ -115,9 +115,21 @@ BOOST_AUTO_TEST_CASE(octal_numbers) BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Number); } +BOOST_AUTO_TEST_CASE(scientific_notation) +{ + Scanner scanner(CharStream("var x = 2e10;")); + BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Var); + BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier); + BOOST_CHECK_EQUAL(scanner.next(), Token::Assign); + BOOST_CHECK_EQUAL(scanner.next(), Token::Number); + BOOST_CHECK_EQUAL(scanner.currentLiteral(), "2e10"); + BOOST_CHECK_EQUAL(scanner.next(), Token::Semicolon); + BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); +} + BOOST_AUTO_TEST_CASE(negative_numbers) { - Scanner scanner(CharStream("var x = -.2 + -0x78 + -7.3 + 8.9;")); + Scanner scanner(CharStream("var x = -.2 + -0x78 + -7.3 + 8.9 + 2e-2;")); BOOST_CHECK_EQUAL(scanner.currentToken(), Token::Var); BOOST_CHECK_EQUAL(scanner.next(), Token::Identifier); BOOST_CHECK_EQUAL(scanner.next(), Token::Assign); @@ -135,6 +147,9 @@ BOOST_AUTO_TEST_CASE(negative_numbers) BOOST_CHECK_EQUAL(scanner.next(), Token::Add); BOOST_CHECK_EQUAL(scanner.next(), Token::Number); BOOST_CHECK_EQUAL(scanner.currentLiteral(), "8.9"); + BOOST_CHECK_EQUAL(scanner.next(), Token::Add); + BOOST_CHECK_EQUAL(scanner.next(), Token::Number); + BOOST_CHECK_EQUAL(scanner.currentLiteral(), "2e-2"); BOOST_CHECK_EQUAL(scanner.next(), Token::Semicolon); BOOST_CHECK_EQUAL(scanner.next(), Token::EOS); } -- cgit v1.2.3 From 1083e6da683b9624b1bb6cc2b3cc3831504dfc57 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 14 Feb 2017 16:36:22 +0000 Subject: Support negative exponent --- libsolidity/ast/Types.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index aecf830d..39760353 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -584,8 +584,7 @@ tuple RationalNumberType::isValidLiteral(Literal const& _literal if (expPoint != _literal.value().end()) { if ( - !all_of(_literal.value().begin(), expPoint, ::isdigit) || - !all_of(expPoint + 1, _literal.value().end(), ::isdigit) + !all_of(_literal.value().begin(), expPoint, ::isdigit) ) return make_tuple(false, rational(0)); @@ -595,10 +594,16 @@ tuple RationalNumberType::isValidLiteral(Literal const& _literal return make_tuple(false, rational(0)); x = bigint(string(_literal.value().begin(), expPoint)); - x *= boost::multiprecision::pow( - bigint(10), - exp.convert_to() - ); + if (exp < 0) + x /= boost::multiprecision::pow( + bigint(10), + abs(exp).convert_to() + ); + else + x *= boost::multiprecision::pow( + bigint(10), + exp.convert_to() + ); } else if (radixPoint != _literal.value().end()) { -- cgit v1.2.3 From dfc8f890bf706d844e5af3b8ca10268ce630bdd7 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 14 Feb 2017 17:25:04 +0000 Subject: Support older version of boost --- libsolidity/ast/Types.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 39760353..f1b47ebe 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -595,10 +595,13 @@ tuple RationalNumberType::isValidLiteral(Literal const& _literal x = bigint(string(_literal.value().begin(), expPoint)); if (exp < 0) + { + exp *= -1; x /= boost::multiprecision::pow( bigint(10), - abs(exp).convert_to() + exp.convert_to() ); + } else x *= boost::multiprecision::pow( bigint(10), -- cgit v1.2.3 From 07045d492fa3ab52b1f04db795c75bb27cbc6cb5 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 15 Mar 2017 11:12:41 +0000 Subject: Do not try parsing hex numbers as scientific notation --- libsolidity/ast/Types.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index f1b47ebe..6234a04d 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -581,7 +582,7 @@ tuple RationalNumberType::isValidLiteral(Literal const& _literal expPoint = find(_literal.value().begin(), _literal.value().end(), 'E'); auto radixPoint = find(_literal.value().begin(), _literal.value().end(), '.'); - if (expPoint != _literal.value().end()) + if (!boost::starts_with(_literal.value(), "0x") && (expPoint != _literal.value().end())) { if ( !all_of(_literal.value().begin(), expPoint, ::isdigit) -- cgit v1.2.3 From a2b9f52ca4a70289ba5d9892d58c61659af07d40 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 15 Mar 2017 11:16:44 +0000 Subject: Disallow radix points in hex literals --- libsolidity/ast/Types.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 6234a04d..52d61d13 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -582,7 +582,12 @@ tuple RationalNumberType::isValidLiteral(Literal const& _literal expPoint = find(_literal.value().begin(), _literal.value().end(), 'E'); auto radixPoint = find(_literal.value().begin(), _literal.value().end(), '.'); - if (!boost::starts_with(_literal.value(), "0x") && (expPoint != _literal.value().end())) + if (boost::starts_with(_literal.value(), "0x")) + { + // process as hex + x = bigint(_literal.value()); + } + else if (expPoint != _literal.value().end()) { if ( !all_of(_literal.value().begin(), expPoint, ::isdigit) -- cgit v1.2.3 From dde87de4cf3d2e0cae8f8bc81e3208a9ff1ca645 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 15 Mar 2017 12:50:34 +0000 Subject: Rename x to value --- libsolidity/ast/Types.cpp | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 52d61d13..71528bbd 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -574,7 +574,7 @@ TypePointer FixedPointType::binaryOperatorResult(Token::Value _operator, TypePoi tuple RationalNumberType::isValidLiteral(Literal const& _literal) { - rational x; + rational value; try { auto expPoint = find(_literal.value().begin(), _literal.value().end(), 'e'); @@ -585,7 +585,7 @@ tuple RationalNumberType::isValidLiteral(Literal const& _literal if (boost::starts_with(_literal.value(), "0x")) { // process as hex - x = bigint(_literal.value()); + value = bigint(_literal.value()); } else if (expPoint != _literal.value().end()) { @@ -599,17 +599,18 @@ tuple RationalNumberType::isValidLiteral(Literal const& _literal if (exp > numeric_limits::max() || exp < numeric_limits::min()) return make_tuple(false, rational(0)); - x = bigint(string(_literal.value().begin(), expPoint)); + value = bigint(string(_literal.value().begin(), expPoint)); + if (exp < 0) { exp *= -1; - x /= boost::multiprecision::pow( + value /= boost::multiprecision::pow( bigint(10), exp.convert_to() ); } else - x *= boost::multiprecision::pow( + value *= boost::multiprecision::pow( bigint(10), exp.convert_to() ); @@ -637,10 +638,10 @@ tuple RationalNumberType::isValidLiteral(Literal const& _literal distance(radixPoint + 1, _literal.value().end()) ); numerator = bigint(string(_literal.value().begin(), radixPoint)); - x = numerator + denominator; + value = numerator + denominator; } else - x = bigint(_literal.value()); + value = bigint(_literal.value()); } catch (...) { @@ -653,33 +654,33 @@ tuple RationalNumberType::isValidLiteral(Literal const& _literal case Literal::SubDenomination::Second: break; case Literal::SubDenomination::Szabo: - x *= bigint("1000000000000"); + value *= bigint("1000000000000"); break; case Literal::SubDenomination::Finney: - x *= bigint("1000000000000000"); + value *= bigint("1000000000000000"); break; case Literal::SubDenomination::Ether: - x *= bigint("1000000000000000000"); + value *= bigint("1000000000000000000"); break; case Literal::SubDenomination::Minute: - x *= bigint("60"); + value *= bigint("60"); break; case Literal::SubDenomination::Hour: - x *= bigint("3600"); + value *= bigint("3600"); break; case Literal::SubDenomination::Day: - x *= bigint("86400"); + value *= bigint("86400"); break; case Literal::SubDenomination::Week: - x *= bigint("604800"); + value *= bigint("604800"); break; case Literal::SubDenomination::Year: - x *= bigint("31536000"); + value *= bigint("31536000"); break; } - return make_tuple(true, x); + return make_tuple(true, value); } bool RationalNumberType::isImplicitlyConvertibleTo(Type const& _convertTo) const -- cgit v1.2.3 From e923f27ea88601e8b62ef2c7d8be42ec23c5a849 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 15 Mar 2017 11:18:29 +0000 Subject: Split out parseRational from isValidLiteral --- libsolidity/ast/Types.cpp | 87 ++++++++++++++++++++++++++++++----------------- libsolidity/ast/Types.h | 3 ++ 2 files changed, 58 insertions(+), 32 deletions(-) diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 71528bbd..9a1888eb 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -572,6 +572,49 @@ TypePointer FixedPointType::binaryOperatorResult(Token::Value _operator, TypePoi return commonType; } +tuple RationalNumberType::parseRational(string const& _value) +{ + rational value; + try + { + auto radixPoint = find(_value.begin(), _value.end(), '.'); + + if (radixPoint != _value.end()) + { + if ( + !all_of(radixPoint + 1, _value.end(), ::isdigit) || + !all_of(_value.begin(), radixPoint, ::isdigit) + ) + return make_tuple(false, rational(0)); + + // Only decimal notation allowed here, leading zeros would switch to octal. + auto fractionalBegin = find_if_not( + radixPoint + 1, + _value.end(), + [](char const& a) { return a == '0'; } + ); + + rational numerator; + rational denominator(1); + + denominator = bigint(string(fractionalBegin, _value.end())); + denominator /= boost::multiprecision::pow( + bigint(10), + distance(radixPoint + 1, _value.end()) + ); + numerator = bigint(string(_value.begin(), radixPoint)); + value = numerator + denominator; + } + else + value = bigint(_value); + return make_tuple(true, value); + } + catch (...) + { + return make_tuple(false, rational(0)); + } +} + tuple RationalNumberType::isValidLiteral(Literal const& _literal) { rational value; @@ -580,7 +623,6 @@ tuple RationalNumberType::isValidLiteral(Literal const& _literal auto expPoint = find(_literal.value().begin(), _literal.value().end(), 'e'); if (expPoint == _literal.value().end()) expPoint = find(_literal.value().begin(), _literal.value().end(), 'E'); - auto radixPoint = find(_literal.value().begin(), _literal.value().end(), '.'); if (boost::starts_with(_literal.value(), "0x")) { @@ -589,17 +631,17 @@ tuple RationalNumberType::isValidLiteral(Literal const& _literal } else if (expPoint != _literal.value().end()) { - if ( - !all_of(_literal.value().begin(), expPoint, ::isdigit) - ) - return make_tuple(false, rational(0)); - + // parse the exponent bigint exp = bigint(string(expPoint + 1, _literal.value().end())); if (exp > numeric_limits::max() || exp < numeric_limits::min()) return make_tuple(false, rational(0)); - value = bigint(string(_literal.value().begin(), expPoint)); + // parse the base + tuple base = parseRational(string(_literal.value().begin(), expPoint)); + if (!get<0>(base)) + return make_tuple(false, rational(0)); + value = get<1>(base); if (exp < 0) { @@ -615,33 +657,14 @@ tuple RationalNumberType::isValidLiteral(Literal const& _literal exp.convert_to() ); } - else if (radixPoint != _literal.value().end()) + else { - if ( - !all_of(radixPoint + 1, _literal.value().end(), ::isdigit) || - !all_of(_literal.value().begin(), radixPoint, ::isdigit) - ) - return make_tuple(false, rational(0)); - //Only decimal notation allowed here, leading zeros would switch to octal. - auto fractionalBegin = find_if_not( - radixPoint + 1, - _literal.value().end(), - [](char const& a) { return a == '0'; } - ); - - rational numerator; - rational denominator(1); - - denominator = bigint(string(fractionalBegin, _literal.value().end())); - denominator /= boost::multiprecision::pow( - bigint(10), - distance(radixPoint + 1, _literal.value().end()) - ); - numerator = bigint(string(_literal.value().begin(), radixPoint)); - value = numerator + denominator; + // parse as rational number + tuple tmp = parseRational(_literal.value()); + if (!get<0>(tmp)) + return tmp; + value = get<1>(tmp); } - else - value = bigint(_literal.value()); } catch (...) { diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 022b67c4..a1142e4f 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -416,6 +416,9 @@ public: private: rational m_value; + + /// @returns true if the literal is a valid rational number. + static std::tuple parseRational(std::string const& _value); }; /** -- cgit v1.2.3 From b0a23fa77d4e5f16b3ab1a56000db45748a05838 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 15 Mar 2017 12:21:58 +0000 Subject: Add tests for fractional numbers in exponential notation --- test/libsolidity/SolidityEndToEndTest.cpp | 4 ++++ test/libsolidity/SolidityParser.cpp | 1 + 2 files changed, 5 insertions(+) diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 21d9074d..ebc9f51e 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -9186,11 +9186,15 @@ BOOST_AUTO_TEST_CASE(scientific_notation) function g() returns (uint) { return 200e-2 wei; } + function h() returns (uint) { + return 2.5e1; + } } )"; compileAndRun(sourceCode, 0, "C"); BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(20000000000))); BOOST_CHECK(callContractFunction("g()") == encodeArgs(u256(2))); + BOOST_CHECK(callContractFunction("h()") == encodeArgs(u256(25))); } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libsolidity/SolidityParser.cpp b/test/libsolidity/SolidityParser.cpp index cfc76ae0..ffb4b6f2 100644 --- a/test/libsolidity/SolidityParser.cpp +++ b/test/libsolidity/SolidityParser.cpp @@ -1487,6 +1487,7 @@ BOOST_AUTO_TEST_CASE(scientific_notation) uint256 b = 2E10; uint256 c = 200e-2; uint256 d = 2E10 wei; + uint256 e = 2.5e10; } )"; BOOST_CHECK(successParse(text)); -- cgit v1.2.3 From b28be08b6d1aeb642fd35e32e2b7627e4eb7cd38 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 15 Mar 2017 13:00:58 +0000 Subject: Add tests for negative base --- test/libsolidity/SolidityEndToEndTest.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index ebc9f51e..16b4cc9e 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -9189,12 +9189,24 @@ BOOST_AUTO_TEST_CASE(scientific_notation) function h() returns (uint) { return 2.5e1; } + function i() returns (int) { + return -2e10; + } + function j() returns (int) { + return -200e-2; + } + function k() returns (int) { + return -2.5e1; + } } )"; compileAndRun(sourceCode, 0, "C"); BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(20000000000))); BOOST_CHECK(callContractFunction("g()") == encodeArgs(u256(2))); BOOST_CHECK(callContractFunction("h()") == encodeArgs(u256(25))); + BOOST_CHECK(callContractFunction("i()") == encodeArgs(u256(-20000000000))); + BOOST_CHECK(callContractFunction("j()") == encodeArgs(u256(-2))); + BOOST_CHECK(callContractFunction("k()") == encodeArgs(u256(-25))); } BOOST_AUTO_TEST_SUITE_END() -- cgit v1.2.3 From 07d775294b0c3270ee9d7bd496837193919c3d94 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Wed, 15 Mar 2017 13:16:16 +0000 Subject: Document scientific notation in integer literals --- docs/types.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/types.rst b/docs/types.rst index f89a8ee5..243a9a0c 100644 --- a/docs/types.rst +++ b/docs/types.rst @@ -202,6 +202,9 @@ Octal literals do not exist in Solidity and leading zeros are invalid. Decimal fraction literals are formed by a ``.`` with at least one number on one side. Examples include ``1.``, ``.1`` and ``1.3``. +Scientific notation is also supported, where the base can have fractions, while the exponent cannot. +Examples include ``2e10``, ``-2e10``, ``2e-10``, ``2.5e1``. + Number literal expressions retain arbitrary precision until they are converted to a non-literal type (i.e. by using them together with a non-literal expression). This means that computations do not overflow and divisions do not truncate -- cgit v1.2.3