From 13e7012e1ec2d69f8af4432320553742ac4ba8ec Mon Sep 17 00:00:00 2001 From: hrkrshnn Date: Tue, 13 Oct 2020 13:20:32 +0200 Subject: [PATCH] Parser: Exponentiation is right associative --- Changelog.md | 1 + docs/080-breaking-changes.rst | 2 + liblangutil/Token.cpp | 10 ---- liblangutil/Token.h | 23 +++++++- libsolidity/parsing/Parser.cpp | 8 ++- .../arithmetics/exp_associativity.sol | 41 ++++++++++++++ .../types/rational_number_exp_limit_fail.sol | 56 +++++++++---------- 7 files changed, 101 insertions(+), 40 deletions(-) create mode 100644 test/libsolidity/semanticTests/arithmetics/exp_associativity.sol diff --git a/Changelog.md b/Changelog.md index 0c421f6c0..095e10962 100644 --- a/Changelog.md +++ b/Changelog.md @@ -3,6 +3,7 @@ Breaking Changes: * Type System: Unary negation can only be used on signed integers, not on unsigned integers. * Type System: Disallow explicit conversions from negative literals and literals larger than ``type(uint160).max`` to ``address`` type. + * Parser: Exponentiation is right associative. ``a**b**c`` is parsed as ``a**(b**c)``. ### 0.7.4 (unreleased) diff --git a/docs/080-breaking-changes.rst b/docs/080-breaking-changes.rst index 60bd365fa..ac1d377f5 100644 --- a/docs/080-breaking-changes.rst +++ b/docs/080-breaking-changes.rst @@ -15,3 +15,5 @@ This section lists changes where you have to modify your code and it does something else afterwards. * Explicit conversions from negative literals and literals larger than ``type(uint160).max`` to ``address`` are now disallowed. +* Exponentiation is right associative, i.e., the expression ``a**b**c`` is parsed as ``a**(b**c)``. + Before 0.8.0, it was parsed as ``(a**b)**c``. diff --git a/liblangutil/Token.cpp b/liblangutil/Token.cpp index bbcfe1590..31f3f2db6 100644 --- a/liblangutil/Token.cpp +++ b/liblangutil/Token.cpp @@ -115,16 +115,6 @@ std::string friendlyName(Token tok) return std::string(ret); } -#define T(name, string, precedence) precedence, -int precedence(Token tok) -{ - int8_t const static precs[TokenTraits::count()] = - { - TOKEN_LIST(T, T) - }; - return precs[static_cast(tok)]; -} -#undef T int parseSize(string::const_iterator _begin, string::const_iterator _end) { diff --git a/liblangutil/Token.h b/liblangutil/Token.h index 8e61b84d4..183d23887 100644 --- a/liblangutil/Token.h +++ b/liblangutil/Token.h @@ -337,7 +337,28 @@ namespace TokenTraits // @returns the precedence > 0 for binary and compare // operators; returns 0 otherwise. - int precedence(Token tok); + constexpr int precedence(Token tok) + { + int8_t constexpr precs[TokenTraits::count()] = + { + #define T(name, string, precedence) precedence, + TOKEN_LIST(T, T) + #undef T + }; + return precs[static_cast(tok)]; + } + + constexpr bool hasExpHighestPrecedence() + { + constexpr int expPrecedence = TokenTraits::precedence(Token::Exp); + static_assert(expPrecedence == 14, "Exp precedence changed."); + + #define T(name, string, precedence) ((Token::name == Token::Exp) || precedence < expPrecedence) && + return + TOKEN_LIST(T, T) + true; + #undef T + } std::tuple fromIdentifierOrKeyword(std::string const& _literal); diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp index 053a6718b..c69c4c3eb 100644 --- a/libsolidity/parsing/Parser.cpp +++ b/libsolidity/parsing/Parser.cpp @@ -1606,7 +1606,13 @@ ASTPointer Parser::parseBinaryExpression( { Token op = m_scanner->currentToken(); m_scanner->next(); - ASTPointer right = parseBinaryExpression(precedence + 1); + + static_assert(TokenTraits::hasExpHighestPrecedence(), "Exp does not have the highest precedence"); + + // Parse a**b**c as a**(b**c) + ASTPointer right = (op == Token::Exp) ? + parseBinaryExpression(precedence) : + parseBinaryExpression(precedence + 1); nodeFactory.setEndPositionFromNode(right); expression = nodeFactory.createNode(expression, op, right); } diff --git a/test/libsolidity/semanticTests/arithmetics/exp_associativity.sol b/test/libsolidity/semanticTests/arithmetics/exp_associativity.sol new file mode 100644 index 000000000..4b2341949 --- /dev/null +++ b/test/libsolidity/semanticTests/arithmetics/exp_associativity.sol @@ -0,0 +1,41 @@ +contract C { + // (2**3)**4 = 4096 + // 2**(3**4) = 2417851639229258349412352 + function test_hardcode1(uint a, uint b, uint c) public returns (uint256) { + return a**b**c; + } + + // (3**2)**2)**2 = 6561 + // 3**(2**(2**2) = 43046721 + function test_hardcode2(uint a, uint b, uint c, uint d) public returns (uint256) { + return a**b**c**d; + } + + function test_invariant(uint a, uint b, uint c) public returns (bool) { + return a**b**c == a**(b**c); + } + + function test_literal_mix(uint a, uint b) public returns (bool) { + return + (a**2**b == a**(2**b)) && + (2**a**b == 2**(a**b)) && + (a**b**2 == a**(b**2)); + } + + function test_other_operators(uint a, uint b) public returns (bool) { + return + (a**b/25 == (a**b)/25) && + (a**b*3**b == (a**b)*(3**b)) && + (b**a**a/b**a**b == (b**(a**a))/(b**(a**b))); + } +} + +// ==== +// compileViaYul: also +// ---- +// test_hardcode1(uint256,uint256,uint256): 2, 3, 4 -> 2417851639229258349412352 +// test_hardcode2(uint256,uint256,uint256,uint256): 3, 2, 2, 2 -> 43046721 +// test_invariant(uint256,uint256,uint256): 2, 3, 4 -> true +// test_invariant(uint256,uint256,uint256): 3, 4, 2 -> true +// test_literal_mix(uint256,uint256): 2, 3 -> true +// test_other_operators(uint256,uint256): 2, 4 -> true diff --git a/test/libsolidity/syntaxTests/types/rational_number_exp_limit_fail.sol b/test/libsolidity/syntaxTests/types/rational_number_exp_limit_fail.sol index 39be18a28..4a9fc7349 100644 --- a/test/libsolidity/syntaxTests/types/rational_number_exp_limit_fail.sol +++ b/test/libsolidity/syntaxTests/types/rational_number_exp_limit_fail.sol @@ -1,8 +1,8 @@ contract c { function f() public pure { int a; - a = 4 ** 4 ** 2 ** 4 ** 4 ** 4 ** 4; - a = -4 ** 4 ** 2 ** 4 ** 4 ** 4 ** 4 ** 4; + a = (((((4 ** 4) ** 2) ** 4) ** 4) ** 4) ** 4; + a = -(((4 ** 4 ** 2 ** 4 ** 4) ** 4) ** 4) ** 4; a = 4 ** (-(2 ** 4 ** 4 ** 4 ** 4 ** 4)); a = 2 ** 1E1233; a = -2 ** 1E1233; @@ -19,29 +19,29 @@ contract c { } } // ---- -// TypeError 2271: (71-102): Operator ** not compatible with types int_const 1797...(301 digits omitted)...7216 and int_const 4. Precision of rational constants is limited to 4096 bits. -// TypeError 7407: (71-102): Type int_const 1797...(301 digits omitted)...7216 is not implicitly convertible to expected type int256. Literal is too large to fit in int256. -// TypeError 2271: (116-148): Operator ** not compatible with types int_const 1797...(301 digits omitted)...7216 and int_const 4. Precision of rational constants is limited to 4096 bits. -// TypeError 2271: (116-153): Operator ** not compatible with types int_const 1797...(301 digits omitted)...7216 and int_const 4. Precision of rational constants is limited to 4096 bits. -// TypeError 7407: (116-153): Type int_const 1797...(301 digits omitted)...7216 is not implicitly convertible to expected type int256. Literal is too large to fit in int256. -// TypeError 2271: (167-203): Operator ** not compatible with types int_const 4 and int_const -179...(302 digits omitted)...7216 -// TypeError 2271: (217-228): Operator ** not compatible with types int_const 2 and int_const 1000...(1226 digits omitted)...0000 -// TypeError 2271: (242-254): Operator ** not compatible with types int_const -2 and int_const 1000...(1226 digits omitted)...0000 -// TypeError 2271: (268-280): Operator ** not compatible with types int_const 2 and int_const -100...(1227 digits omitted)...0000 -// TypeError 2271: (294-307): Operator ** not compatible with types int_const -2 and int_const -100...(1227 digits omitted)...0000 -// TypeError 2271: (321-332): Operator ** not compatible with types int_const 1000...(1226 digits omitted)...0000 and int_const 2. Precision of rational constants is limited to 4096 bits. -// TypeError 7407: (321-332): Type int_const 1000...(1226 digits omitted)...0000 is not implicitly convertible to expected type int256. Literal is too large to fit in int256. -// TypeError 2271: (346-358): Operator ** not compatible with types int_const -100...(1227 digits omitted)...0000 and int_const 2. Precision of rational constants is limited to 4096 bits. -// TypeError 7407: (346-358): Type int_const -100...(1227 digits omitted)...0000 is not implicitly convertible to expected type int256. Literal is too large to fit in int256. -// TypeError 2271: (372-384): Operator ** not compatible with types int_const 1000...(1226 digits omitted)...0000 and int_const -2. Precision of rational constants is limited to 4096 bits. -// TypeError 7407: (372-384): Type int_const 1000...(1226 digits omitted)...0000 is not implicitly convertible to expected type int256. Literal is too large to fit in int256. -// TypeError 2271: (398-411): Operator ** not compatible with types int_const -100...(1227 digits omitted)...0000 and int_const -2. Precision of rational constants is limited to 4096 bits. -// TypeError 7407: (398-411): Type int_const -100...(1227 digits omitted)...0000 is not implicitly convertible to expected type int256. Literal is too large to fit in int256. -// TypeError 2271: (425-441): Operator ** not compatible with types int_const 1000...(1226 digits omitted)...0000 and int_const 1000...(1226 digits omitted)...0000 -// TypeError 7407: (425-441): Type int_const 1000...(1226 digits omitted)...0000 is not implicitly convertible to expected type int256. Literal is too large to fit in int256. -// TypeError 2271: (455-472): Operator ** not compatible with types int_const 1000...(1226 digits omitted)...0000 and int_const -100...(1227 digits omitted)...0000 -// TypeError 7407: (455-472): Type int_const 1000...(1226 digits omitted)...0000 is not implicitly convertible to expected type int256. Literal is too large to fit in int256. -// TypeError 2271: (486-503): Operator ** not compatible with types int_const -100...(1227 digits omitted)...0000 and int_const 1000...(1226 digits omitted)...0000 -// TypeError 7407: (486-503): Type int_const -100...(1227 digits omitted)...0000 is not implicitly convertible to expected type int256. Literal is too large to fit in int256. -// TypeError 2271: (517-535): Operator ** not compatible with types int_const -100...(1227 digits omitted)...0000 and int_const -100...(1227 digits omitted)...0000 -// TypeError 7407: (517-535): Type int_const -100...(1227 digits omitted)...0000 is not implicitly convertible to expected type int256. Literal is too large to fit in int256. +// TypeError 2271: (71-112): Operator ** not compatible with types int_const 1797...(301 digits omitted)...7216 and int_const 4. Precision of rational constants is limited to 4096 bits. +// TypeError 7407: (71-112): Type int_const 1797...(301 digits omitted)...7216 is not implicitly convertible to expected type int256. Literal is too large to fit in int256. +// TypeError 2271: (135-151): Operator ** not compatible with types int_const 4 and int_const 1157...(70 digits omitted)...9936 +// TypeError 7407: (126-169): Type int_const 1340...(147 digits omitted)...4096 is not implicitly convertible to expected type int256. Literal is too large to fit in int256. +// TypeError 2271: (201-217): Operator ** not compatible with types int_const 4 and int_const 1340...(147 digits omitted)...4096 +// TypeError 2271: (183-219): Operator ** not compatible with types int_const 4 and int_const -115...(71 digits omitted)...9936 +// TypeError 2271: (233-244): Operator ** not compatible with types int_const 2 and int_const 1000...(1226 digits omitted)...0000 +// TypeError 2271: (258-270): Operator ** not compatible with types int_const -2 and int_const 1000...(1226 digits omitted)...0000 +// TypeError 2271: (284-296): Operator ** not compatible with types int_const 2 and int_const -100...(1227 digits omitted)...0000 +// TypeError 2271: (310-323): Operator ** not compatible with types int_const -2 and int_const -100...(1227 digits omitted)...0000 +// TypeError 2271: (337-348): Operator ** not compatible with types int_const 1000...(1226 digits omitted)...0000 and int_const 2. Precision of rational constants is limited to 4096 bits. +// TypeError 7407: (337-348): Type int_const 1000...(1226 digits omitted)...0000 is not implicitly convertible to expected type int256. Literal is too large to fit in int256. +// TypeError 2271: (362-374): Operator ** not compatible with types int_const -100...(1227 digits omitted)...0000 and int_const 2. Precision of rational constants is limited to 4096 bits. +// TypeError 7407: (362-374): Type int_const -100...(1227 digits omitted)...0000 is not implicitly convertible to expected type int256. Literal is too large to fit in int256. +// TypeError 2271: (388-400): Operator ** not compatible with types int_const 1000...(1226 digits omitted)...0000 and int_const -2. Precision of rational constants is limited to 4096 bits. +// TypeError 7407: (388-400): Type int_const 1000...(1226 digits omitted)...0000 is not implicitly convertible to expected type int256. Literal is too large to fit in int256. +// TypeError 2271: (414-427): Operator ** not compatible with types int_const -100...(1227 digits omitted)...0000 and int_const -2. Precision of rational constants is limited to 4096 bits. +// TypeError 7407: (414-427): Type int_const -100...(1227 digits omitted)...0000 is not implicitly convertible to expected type int256. Literal is too large to fit in int256. +// TypeError 2271: (441-457): Operator ** not compatible with types int_const 1000...(1226 digits omitted)...0000 and int_const 1000...(1226 digits omitted)...0000 +// TypeError 7407: (441-457): Type int_const 1000...(1226 digits omitted)...0000 is not implicitly convertible to expected type int256. Literal is too large to fit in int256. +// TypeError 2271: (471-488): Operator ** not compatible with types int_const 1000...(1226 digits omitted)...0000 and int_const -100...(1227 digits omitted)...0000 +// TypeError 7407: (471-488): Type int_const 1000...(1226 digits omitted)...0000 is not implicitly convertible to expected type int256. Literal is too large to fit in int256. +// TypeError 2271: (502-519): Operator ** not compatible with types int_const -100...(1227 digits omitted)...0000 and int_const 1000...(1226 digits omitted)...0000 +// TypeError 7407: (502-519): Type int_const -100...(1227 digits omitted)...0000 is not implicitly convertible to expected type int256. Literal is too large to fit in int256. +// TypeError 2271: (533-551): Operator ** not compatible with types int_const -100...(1227 digits omitted)...0000 and int_const -100...(1227 digits omitted)...0000 +// TypeError 7407: (533-551): Type int_const -100...(1227 digits omitted)...0000 is not implicitly convertible to expected type int256. Literal is too large to fit in int256.