From edd0afa3c35475990bacd8ffe64d15b3be40a036 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 2 May 2017 18:26:33 +0100 Subject: Support true/false literals in inline assembly --- libsolidity/inlineasm/AsmAnalysis.cpp | 2 +- libsolidity/inlineasm/AsmCodeGen.cpp | 9 ++++++++- libsolidity/inlineasm/AsmData.h | 3 ++- libsolidity/inlineasm/AsmParser.cpp | 23 ++++++++++++++++++++++- libsolidity/inlineasm/AsmPrinter.cpp | 10 +++++++++- 5 files changed, 42 insertions(+), 5 deletions(-) diff --git a/libsolidity/inlineasm/AsmAnalysis.cpp b/libsolidity/inlineasm/AsmAnalysis.cpp index 590f9ad6..e03eea2e 100644 --- a/libsolidity/inlineasm/AsmAnalysis.cpp +++ b/libsolidity/inlineasm/AsmAnalysis.cpp @@ -72,7 +72,7 @@ bool AsmAnalyzer::operator()(assembly::Instruction const& _instruction) bool AsmAnalyzer::operator()(assembly::Literal const& _literal) { ++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::Type::TypeError, diff --git a/libsolidity/inlineasm/AsmCodeGen.cpp b/libsolidity/inlineasm/AsmCodeGen.cpp index 137a70f5..44e12b3e 100644 --- a/libsolidity/inlineasm/AsmCodeGen.cpp +++ b/libsolidity/inlineasm/AsmCodeGen.cpp @@ -118,8 +118,15 @@ public: void operator()(assembly::Literal const& _literal) { m_state.assembly.setSourceLocation(_literal.location); - if (_literal.isNumber) + if (_literal.kind == assembly::LiteralKind::Number) 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 { solAssert(_literal.value.size() <= 32, ""); diff --git a/libsolidity/inlineasm/AsmData.h b/libsolidity/inlineasm/AsmData.h index 363873ab..8efe1f07 100644 --- a/libsolidity/inlineasm/AsmData.h +++ b/libsolidity/inlineasm/AsmData.h @@ -43,7 +43,8 @@ using TypedNameList = std::vector; /// Direct EVM instruction (except PUSHi and JUMPDEST) struct Instruction { SourceLocation location; solidity::Instruction instruction; }; /// 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 struct Identifier { SourceLocation location; std::string name; }; struct FunctionalInstruction; diff --git a/libsolidity/inlineasm/AsmParser.cpp b/libsolidity/inlineasm/AsmParser.cpp index 7ecad5ea..079b9352 100644 --- a/libsolidity/inlineasm/AsmParser.cpp +++ b/libsolidity/inlineasm/AsmParser.cpp @@ -206,10 +206,29 @@ assembly::Statement Parser::parseElementaryOperation(bool _onlySinglePusher) } case Token::StringLiteral: 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{ location(), - m_scanner->currentToken() == Token::Number, + kind, m_scanner->currentLiteral(), "" }; @@ -220,6 +239,8 @@ assembly::Statement Parser::parseElementaryOperation(bool _onlySinglePusher) literal.location.end = endPosition(); literal.type = expectAsmIdentifier(); } + else if (kind == LiteralKind::Boolean) + fatalParserError("True and false are not valid literals."); ret = std::move(literal); break; } diff --git a/libsolidity/inlineasm/AsmPrinter.cpp b/libsolidity/inlineasm/AsmPrinter.cpp index f3b66aee..636e61b8 100644 --- a/libsolidity/inlineasm/AsmPrinter.cpp +++ b/libsolidity/inlineasm/AsmPrinter.cpp @@ -46,8 +46,16 @@ string AsmPrinter::operator()(assembly::Instruction const& _instruction) string AsmPrinter::operator()(assembly::Literal const& _literal) { - if (_literal.isNumber) + switch (_literal.kind) + { + case LiteralKind::Number: return _literal.value + appendTypeName(_literal.type); + case LiteralKind::Boolean: + return ((_literal.value == "true") ? "true" : "false") + appendTypeName(_literal.type); + case LiteralKind::String: + break; + } + string out; for (char c: _literal.value) if (c == '\\') -- cgit v1.2.3