Support true/false literals in inline assembly

This commit is contained in:
Alex Beregszaszi 2017-05-02 18:26:33 +01:00
parent cc9a99a63f
commit edd0afa3c3
5 changed files with 42 additions and 5 deletions

View File

@ -72,7 +72,7 @@ bool AsmAnalyzer::operator()(assembly::Instruction const& _instruction)
bool AsmAnalyzer::operator()(assembly::Literal const& _literal) bool AsmAnalyzer::operator()(assembly::Literal const& _literal)
{ {
++m_stackHeight; ++m_stackHeight;
if (!_literal.isNumber && _literal.value.size() > 32) if (_literal.kind == assembly::LiteralKind::String && _literal.value.size() > 32)
{ {
m_errors.push_back(make_shared<Error>( m_errors.push_back(make_shared<Error>(
Error::Type::TypeError, Error::Type::TypeError,

View File

@ -118,8 +118,15 @@ public:
void operator()(assembly::Literal const& _literal) void operator()(assembly::Literal const& _literal)
{ {
m_state.assembly.setSourceLocation(_literal.location); m_state.assembly.setSourceLocation(_literal.location);
if (_literal.isNumber) if (_literal.kind == assembly::LiteralKind::Number)
m_state.assembly.append(u256(_literal.value)); m_state.assembly.append(u256(_literal.value));
else if (_literal.kind == assembly::LiteralKind::Boolean)
{
if (_literal.value == "true")
m_state.assembly.append(u256(1));
else
m_state.assembly.append(u256(0));
}
else else
{ {
solAssert(_literal.value.size() <= 32, ""); solAssert(_literal.value.size() <= 32, "");

View File

@ -43,7 +43,8 @@ using TypedNameList = std::vector<TypedName>;
/// Direct EVM instruction (except PUSHi and JUMPDEST) /// Direct EVM instruction (except PUSHi and JUMPDEST)
struct Instruction { SourceLocation location; solidity::Instruction instruction; }; struct Instruction { SourceLocation location; solidity::Instruction instruction; };
/// Literal number or string (up to 32 bytes) /// Literal number or string (up to 32 bytes)
struct Literal { SourceLocation location; bool isNumber; std::string value; Type type; }; enum class LiteralKind { Number, Boolean, String };
struct Literal { SourceLocation location; LiteralKind kind; std::string value; Type type; };
/// External / internal identifier or label reference /// External / internal identifier or label reference
struct Identifier { SourceLocation location; std::string name; }; struct Identifier { SourceLocation location; std::string name; };
struct FunctionalInstruction; struct FunctionalInstruction;

View File

@ -206,10 +206,29 @@ assembly::Statement Parser::parseElementaryOperation(bool _onlySinglePusher)
} }
case Token::StringLiteral: case Token::StringLiteral:
case Token::Number: case Token::Number:
case Token::TrueLiteral:
case Token::FalseLiteral:
{ {
LiteralKind kind = LiteralKind::Number;
switch (m_scanner->currentToken())
{
case Token::StringLiteral:
kind = LiteralKind::String;
break;
case Token::Number:
kind = LiteralKind::Number;
break;
case Token::TrueLiteral:
case Token::FalseLiteral:
kind = LiteralKind::Boolean;
break;
default:
break;
}
Literal literal{ Literal literal{
location(), location(),
m_scanner->currentToken() == Token::Number, kind,
m_scanner->currentLiteral(), m_scanner->currentLiteral(),
"" ""
}; };
@ -220,6 +239,8 @@ assembly::Statement Parser::parseElementaryOperation(bool _onlySinglePusher)
literal.location.end = endPosition(); literal.location.end = endPosition();
literal.type = expectAsmIdentifier(); literal.type = expectAsmIdentifier();
} }
else if (kind == LiteralKind::Boolean)
fatalParserError("True and false are not valid literals.");
ret = std::move(literal); ret = std::move(literal);
break; break;
} }

View File

@ -46,8 +46,16 @@ string AsmPrinter::operator()(assembly::Instruction const& _instruction)
string AsmPrinter::operator()(assembly::Literal const& _literal) string AsmPrinter::operator()(assembly::Literal const& _literal)
{ {
if (_literal.isNumber) switch (_literal.kind)
{
case LiteralKind::Number:
return _literal.value + appendTypeName(_literal.type); return _literal.value + appendTypeName(_literal.type);
case LiteralKind::Boolean:
return ((_literal.value == "true") ? "true" : "false") + appendTypeName(_literal.type);
case LiteralKind::String:
break;
}
string out; string out;
for (char c: _literal.value) for (char c: _literal.value)
if (c == '\\') if (c == '\\')