diff options
author | chriseth <chris@ethereum.org> | 2017-05-23 18:18:18 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-05-23 18:18:18 +0800 |
commit | 14b22150a1e3ad66cdbed70bcfacb5487f66aef8 (patch) | |
tree | f71af087d97b991da73b7d9e80b471c9ed037968 /libsolidity | |
parent | 74d2e7311aed67e3bb6fcf1f0fa138bc3d304095 (diff) | |
parent | fb46268982f9c19f15e01f0ee50764c58bb351d4 (diff) | |
download | dexon-solidity-14b22150a1e3ad66cdbed70bcfacb5487f66aef8.tar.gz dexon-solidity-14b22150a1e3ad66cdbed70bcfacb5487f66aef8.tar.zst dexon-solidity-14b22150a1e3ad66cdbed70bcfacb5487f66aef8.zip |
Merge pull request #2244 from ethereum/inlineasm-let-multi
Support tuple assignment in inline assembly
Diffstat (limited to 'libsolidity')
-rw-r--r-- | libsolidity/inlineasm/AsmAnalysis.cpp | 15 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmCodeGen.cpp | 12 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmData.h | 2 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmParser.cpp | 9 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmPrinter.cpp | 11 | ||||
-rw-r--r-- | libsolidity/inlineasm/AsmScopeFiller.cpp | 5 |
6 files changed, 44 insertions, 10 deletions
diff --git a/libsolidity/inlineasm/AsmAnalysis.cpp b/libsolidity/inlineasm/AsmAnalysis.cpp index e03eea2e..9e0ade2a 100644 --- a/libsolidity/inlineasm/AsmAnalysis.cpp +++ b/libsolidity/inlineasm/AsmAnalysis.cpp @@ -181,10 +181,21 @@ bool AsmAnalyzer::operator()(FunctionalAssignment const& _assignment) bool AsmAnalyzer::operator()(assembly::VariableDeclaration const& _varDecl) { + int const expectedItems = _varDecl.variables.size(); int const stackHeight = m_stackHeight; bool success = boost::apply_visitor(*this, *_varDecl.value); - solAssert(m_stackHeight - stackHeight == 1, "Invalid value size."); - boost::get<Scope::Variable>(m_currentScope->identifiers.at(_varDecl.variable.name)).active = true; + if ((m_stackHeight - stackHeight) != expectedItems) + { + m_errors.push_back(make_shared<Error>( + Error::Type::DeclarationError, + "Variable count mismatch.", + _varDecl.location + )); + return false; + } + + for (auto const& variable: _varDecl.variables) + boost::get<Scope::Variable>(m_currentScope->identifiers.at(variable.name)).active = true; m_info.stackHeightInfo[&_varDecl] = m_stackHeight; return success; } diff --git a/libsolidity/inlineasm/AsmCodeGen.cpp b/libsolidity/inlineasm/AsmCodeGen.cpp index b8af9dc6..02d5ced0 100644 --- a/libsolidity/inlineasm/AsmCodeGen.cpp +++ b/libsolidity/inlineasm/AsmCodeGen.cpp @@ -251,11 +251,15 @@ public: void operator()(assembly::VariableDeclaration const& _varDecl) { int height = m_assembly.stackHeight(); + int expectedItems = _varDecl.variables.size(); boost::apply_visitor(*this, *_varDecl.value); - expectDeposit(1, height); - auto& var = boost::get<Scope::Variable>(m_scope.identifiers.at(_varDecl.variable.name)); - var.stackHeight = height; - var.active = true; + expectDeposit(expectedItems, height); + for (auto const& variable: _varDecl.variables) + { + auto& var = boost::get<Scope::Variable>(m_scope.identifiers.at(variable.name)); + var.stackHeight = height++; + var.active = true; + } } void operator()(assembly::Block const& _block) { diff --git a/libsolidity/inlineasm/AsmData.h b/libsolidity/inlineasm/AsmData.h index 8efe1f07..65dfbadf 100644 --- a/libsolidity/inlineasm/AsmData.h +++ b/libsolidity/inlineasm/AsmData.h @@ -65,7 +65,7 @@ struct FunctionalAssignment { SourceLocation location; Identifier variableName; struct FunctionalInstruction { SourceLocation location; Instruction instruction; std::vector<Statement> arguments; }; struct FunctionCall { SourceLocation location; Identifier functionName; std::vector<Statement> arguments; }; /// Block-scope variable declaration ("let x:u256 := mload(20:u256)"), non-hoisted -struct VariableDeclaration { SourceLocation location; TypedName variable; std::shared_ptr<Statement> value; }; +struct VariableDeclaration { SourceLocation location; TypedNameList variables; std::shared_ptr<Statement> value; }; /// Block that creates a scope (frees declared stack variables) struct Block { SourceLocation location; std::vector<Statement> statements; }; /// Function definition ("function f(a, b) -> (d, e) { ... }") diff --git a/libsolidity/inlineasm/AsmParser.cpp b/libsolidity/inlineasm/AsmParser.cpp index a96984f5..73f70e3f 100644 --- a/libsolidity/inlineasm/AsmParser.cpp +++ b/libsolidity/inlineasm/AsmParser.cpp @@ -258,7 +258,14 @@ assembly::VariableDeclaration Parser::parseVariableDeclaration() { VariableDeclaration varDecl = createWithLocation<VariableDeclaration>(); expectToken(Token::Let); - varDecl.variable = parseTypedName(); + while (true) + { + varDecl.variables.push_back(parseTypedName()); + if (m_scanner->currentToken() == Token::Comma) + expectToken(Token::Comma); + else + break; + } expectToken(Token::Colon); expectToken(Token::Assign); varDecl.value.reset(new Statement(parseExpression())); diff --git a/libsolidity/inlineasm/AsmPrinter.cpp b/libsolidity/inlineasm/AsmPrinter.cpp index 636e61b8..219a57ad 100644 --- a/libsolidity/inlineasm/AsmPrinter.cpp +++ b/libsolidity/inlineasm/AsmPrinter.cpp @@ -121,7 +121,16 @@ string AsmPrinter::operator()(assembly::FunctionalAssignment const& _functionalA string AsmPrinter::operator()(assembly::VariableDeclaration const& _variableDeclaration) { - return "let " + _variableDeclaration.variable.name + appendTypeName(_variableDeclaration.variable.type) + " := " + boost::apply_visitor(*this, *_variableDeclaration.value); + string out = "let "; + out += boost::algorithm::join( + _variableDeclaration.variables | boost::adaptors::transformed( + [this](TypedName variable) { return variable.name + appendTypeName(variable.type); } + ), + ", " + ); + out += " := "; + out += boost::apply_visitor(*this, *_variableDeclaration.value); + return out; } string AsmPrinter::operator()(assembly::FunctionDefinition const& _functionDefinition) diff --git a/libsolidity/inlineasm/AsmScopeFiller.cpp b/libsolidity/inlineasm/AsmScopeFiller.cpp index eb10dbb3..05b1b211 100644 --- a/libsolidity/inlineasm/AsmScopeFiller.cpp +++ b/libsolidity/inlineasm/AsmScopeFiller.cpp @@ -59,7 +59,10 @@ bool ScopeFiller::operator()(Label const& _item) bool ScopeFiller::operator()(assembly::VariableDeclaration const& _varDecl) { - return registerVariable(_varDecl.variable, _varDecl.location, *m_currentScope); + for (auto const& variable: _varDecl.variables) + if (!registerVariable(variable, _varDecl.location, *m_currentScope)) + return false; + return true; } bool ScopeFiller::operator()(assembly::FunctionDefinition const& _funDef) |