mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Right-aligns hex numbers and introduces alignment built-ins.
This commit is contained in:
@@ -33,6 +33,45 @@ using namespace dev::solidity::test;
|
||||
using namespace std;
|
||||
using namespace soltest;
|
||||
|
||||
namespace
|
||||
{
|
||||
enum class DeclaredAlignment
|
||||
{
|
||||
Left,
|
||||
Right,
|
||||
None,
|
||||
};
|
||||
|
||||
inline bytes alignLeft(bytes _bytes)
|
||||
{
|
||||
return std::move(_bytes) + bytes(32 - _bytes.size(), 0);
|
||||
}
|
||||
|
||||
inline bytes alignRight(bytes _bytes)
|
||||
{
|
||||
return bytes(32 - _bytes.size(), 0) + std::move(_bytes);
|
||||
}
|
||||
|
||||
inline bytes applyAlign(DeclaredAlignment _alignment, ABIType& _abiType, bytes _converted)
|
||||
{
|
||||
if (_alignment != DeclaredAlignment::None)
|
||||
_abiType.alignDeclared = true;
|
||||
|
||||
switch (_alignment)
|
||||
{
|
||||
case DeclaredAlignment::Left:
|
||||
_abiType.align = ABIType::AlignLeft;
|
||||
return alignLeft(std::move(_converted));
|
||||
case DeclaredAlignment::Right:
|
||||
_abiType.align = ABIType::AlignRight;
|
||||
return alignRight(std::move(_converted));
|
||||
default:
|
||||
_abiType.align = ABIType::AlignRight;
|
||||
return alignRight(std::move(_converted));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vector<dev::solidity::test::FunctionCall> TestFileParser::parseFunctionCalls()
|
||||
{
|
||||
vector<FunctionCall> calls;
|
||||
@@ -137,9 +176,16 @@ string TestFileParser::parseFunctionSignature()
|
||||
|
||||
u256 TestFileParser::parseFunctionCallValue()
|
||||
{
|
||||
u256 value = convertNumber(parseDecimalNumber());
|
||||
expect(Token::Ether);
|
||||
return value;
|
||||
try
|
||||
{
|
||||
u256 value{parseDecimalNumber()};
|
||||
expect(Token::Ether);
|
||||
return value;
|
||||
}
|
||||
catch (std::exception const&)
|
||||
{
|
||||
throw Error(Error::Type::ParserError, "Ether value encoding invalid.");
|
||||
}
|
||||
}
|
||||
|
||||
FunctionCallArgs TestFileParser::parseFunctionCallArguments()
|
||||
@@ -192,51 +238,75 @@ Parameter TestFileParser::parseParameter()
|
||||
|
||||
tuple<bytes, ABIType, string> TestFileParser::parseABITypeLiteral()
|
||||
{
|
||||
ABIType abiType{ABIType::None, ABIType::AlignNone, 0};
|
||||
DeclaredAlignment alignment{DeclaredAlignment::None};
|
||||
bytes result{toBigEndian(u256{0})};
|
||||
string rawString;
|
||||
bool isSigned = false;
|
||||
|
||||
if (accept(Token::Left, true))
|
||||
{
|
||||
rawString += formatToken(Token::Left);
|
||||
expect(Token::LParen);
|
||||
rawString += formatToken(Token::LParen);
|
||||
alignment = DeclaredAlignment::Left;
|
||||
}
|
||||
if (accept(Token::Right, true))
|
||||
{
|
||||
rawString += formatToken(Token::Right);
|
||||
expect(Token::LParen);
|
||||
rawString += formatToken(Token::LParen);
|
||||
alignment = DeclaredAlignment::Right;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
u256 number{0};
|
||||
ABIType abiType{ABIType::None, ABIType::AlignRight, 0};
|
||||
string rawString;
|
||||
|
||||
if (accept(Token::Sub))
|
||||
if (accept(Token::Sub, true))
|
||||
{
|
||||
abiType = ABIType{ABIType::SignedDec, ABIType::AlignRight, 32};
|
||||
expect(Token::Sub);
|
||||
rawString += formatToken(Token::Sub);
|
||||
isSigned = true;
|
||||
}
|
||||
if (accept(Token::Boolean))
|
||||
{
|
||||
if (isSigned)
|
||||
throw Error(Error::Type::ParserError, "Invalid boolean literal.");
|
||||
abiType = ABIType{ABIType::Boolean, ABIType::AlignRight, 32};
|
||||
string parsed = parseBoolean();
|
||||
rawString += parsed;
|
||||
result = applyAlign(alignment, abiType, convertBoolean(parsed));
|
||||
}
|
||||
else if (accept(Token::HexNumber))
|
||||
{
|
||||
if (isSigned)
|
||||
throw Error(Error::Type::ParserError, "Invalid hex number literal.");
|
||||
abiType = ABIType{ABIType::Hex, ABIType::AlignRight, 32};
|
||||
string parsed = parseHexNumber();
|
||||
rawString += parsed;
|
||||
result = applyAlign(alignment, abiType, convertHexNumber(parsed));
|
||||
}
|
||||
else if (accept(Token::Number))
|
||||
{
|
||||
auto type = isSigned ? ABIType::SignedDec : ABIType::UnsignedDec;
|
||||
abiType = ABIType{type, ABIType::AlignRight, 32};
|
||||
string parsed = parseDecimalNumber();
|
||||
rawString += parsed;
|
||||
number = convertNumber(parsed) * -1;
|
||||
if (isSigned)
|
||||
parsed = "-" + parsed;
|
||||
result = applyAlign(alignment, abiType, convertNumber(parsed));
|
||||
}
|
||||
else
|
||||
else if (accept(Token::Failure, true))
|
||||
{
|
||||
if (accept(Token::Boolean))
|
||||
{
|
||||
abiType = ABIType{ABIType::Boolean, ABIType::AlignRight, 32};
|
||||
string parsed = parseBoolean();
|
||||
rawString += parsed;
|
||||
return make_tuple(toBigEndian(u256{convertBoolean(parsed)}), abiType, rawString);
|
||||
}
|
||||
else if (accept(Token::HexNumber))
|
||||
{
|
||||
abiType = ABIType{ABIType::Hex, ABIType::AlignLeft, 32};
|
||||
string parsed = parseHexNumber();
|
||||
rawString += parsed;
|
||||
return make_tuple(convertHexNumber(parsed), abiType, rawString);
|
||||
}
|
||||
else if (accept(Token::Number))
|
||||
{
|
||||
abiType = ABIType{ABIType::UnsignedDec, ABIType::AlignRight, 32};
|
||||
string parsed = parseDecimalNumber();
|
||||
rawString += parsed;
|
||||
number = convertNumber(parsed);
|
||||
}
|
||||
else if (accept(Token::Failure, true))
|
||||
{
|
||||
abiType = ABIType{ABIType::Failure, ABIType::AlignRight, 0};
|
||||
return make_tuple(bytes{}, abiType, rawString);
|
||||
}
|
||||
if (isSigned)
|
||||
throw Error(Error::Type::ParserError, "Invalid failure literal.");
|
||||
abiType = ABIType{ABIType::Failure, ABIType::AlignRight, 0};
|
||||
result = bytes{};
|
||||
}
|
||||
return make_tuple(toBigEndian(number), abiType, rawString);
|
||||
if (alignment != DeclaredAlignment::None)
|
||||
{
|
||||
expect(Token::RParen);
|
||||
rawString += formatToken(Token::RParen);
|
||||
}
|
||||
return make_tuple(result, abiType, rawString);
|
||||
}
|
||||
catch (std::exception const&)
|
||||
{
|
||||
@@ -298,21 +368,21 @@ string TestFileParser::parseHexNumber()
|
||||
return literal;
|
||||
}
|
||||
|
||||
bool TestFileParser::convertBoolean(string const& _literal)
|
||||
bytes TestFileParser::convertBoolean(string const& _literal)
|
||||
{
|
||||
if (_literal == "true")
|
||||
return true;
|
||||
return bytes{true};
|
||||
else if (_literal == "false")
|
||||
return false;
|
||||
return bytes{false};
|
||||
else
|
||||
throw Error(Error::Type::ParserError, "Boolean literal invalid.");
|
||||
}
|
||||
|
||||
u256 TestFileParser::convertNumber(string const& _literal)
|
||||
bytes TestFileParser::convertNumber(string const& _literal)
|
||||
{
|
||||
try
|
||||
{
|
||||
return u256{_literal};
|
||||
return toCompactBigEndian(u256{_literal});
|
||||
}
|
||||
catch (std::exception const&)
|
||||
{
|
||||
@@ -330,8 +400,7 @@ bytes TestFileParser::convertHexNumber(string const& _literal)
|
||||
}
|
||||
else
|
||||
{
|
||||
bytes result = fromHex(_literal);
|
||||
return result + bytes(32 - result.size(), 0);
|
||||
return fromHex(_literal);
|
||||
}
|
||||
}
|
||||
catch (std::exception const&)
|
||||
@@ -357,6 +426,8 @@ void TestFileParser::Scanner::scanNextToken()
|
||||
if (_literal == "true") return TokenDesc{Token::Boolean, _literal};
|
||||
if (_literal == "false") return TokenDesc{Token::Boolean, _literal};
|
||||
if (_literal == "ether") return TokenDesc{Token::Ether, _literal};
|
||||
if (_literal == "left") return TokenDesc{Token::Left, _literal};
|
||||
if (_literal == "right") return TokenDesc{Token::Right, _literal};
|
||||
if (_literal == "FAILURE") return TokenDesc{Token::Failure, _literal};
|
||||
return TokenDesc{Token::Identifier, _literal};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user