aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Beregszaszi <alex@rtfs.hu>2017-05-06 01:35:40 +0800
committerAlex Beregszaszi <alex@rtfs.hu>2017-05-23 01:45:34 +0800
commit15b4d4def23bcf0feb93c67dccc137baa59d5102 (patch)
treeb684d5e478bde7d69021fd2f2235fa569d457f40
parent74d2e7311aed67e3bb6fcf1f0fa138bc3d304095 (diff)
downloaddexon-solidity-15b4d4def23bcf0feb93c67dccc137baa59d5102.tar.gz
dexon-solidity-15b4d4def23bcf0feb93c67dccc137baa59d5102.tar.zst
dexon-solidity-15b4d4def23bcf0feb93c67dccc137baa59d5102.zip
Support multiple variables in a variable declaration in inline assembly
-rw-r--r--libsolidity/inlineasm/AsmAnalysis.cpp28
-rw-r--r--libsolidity/inlineasm/AsmCodeGen.cpp15
-rw-r--r--libsolidity/inlineasm/AsmData.h2
-rw-r--r--libsolidity/inlineasm/AsmParser.cpp20
-rw-r--r--libsolidity/inlineasm/AsmPrinter.cpp16
-rw-r--r--libsolidity/inlineasm/AsmScopeFiller.cpp5
6 files changed, 71 insertions, 15 deletions
diff --git a/libsolidity/inlineasm/AsmAnalysis.cpp b/libsolidity/inlineasm/AsmAnalysis.cpp
index e03eea2e..8d3d1fd2 100644
--- a/libsolidity/inlineasm/AsmAnalysis.cpp
+++ b/libsolidity/inlineasm/AsmAnalysis.cpp
@@ -181,12 +181,32 @@ bool AsmAnalyzer::operator()(FunctionalAssignment const& _assignment)
bool AsmAnalyzer::operator()(assembly::VariableDeclaration const& _varDecl)
{
+ // The number of variable names and values must match. One exception
+ // is a single value, where a tuple assignment is assumed from a function.
+ if (_varDecl.variables.size() != _varDecl.values.size())
+ {
+ if (_varDecl.values.size() != 1)
+ {
+ m_errors.push_back(make_shared<Error>(
+ Error::Type::DeclarationError,
+ "Variable declaration name and value count mismatch.",
+ _varDecl.location
+ ));
+ return false;
+ }
+ }
+
+ 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;
+ for (auto const& value: _varDecl.values)
+ if (!boost::apply_visitor(*this, value))
+ return false;
+ solAssert(m_stackHeight - stackHeight == expectedItems, "Invalid value size.");
+
+ 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;
+ return true;
}
bool AsmAnalyzer::operator()(assembly::FunctionDefinition const& _funDef)
diff --git a/libsolidity/inlineasm/AsmCodeGen.cpp b/libsolidity/inlineasm/AsmCodeGen.cpp
index b8af9dc6..1063d552 100644
--- a/libsolidity/inlineasm/AsmCodeGen.cpp
+++ b/libsolidity/inlineasm/AsmCodeGen.cpp
@@ -251,11 +251,16 @@ public:
void operator()(assembly::VariableDeclaration const& _varDecl)
{
int height = m_assembly.stackHeight();
- 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;
+ int expectedItems = _varDecl.variables.size();
+ for (auto const& value: _varDecl.values)
+ boost::apply_visitor(*this, value);
+ 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..bf21ba00 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::vector<Statement> values; };
/// 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..53954a49 100644
--- a/libsolidity/inlineasm/AsmParser.cpp
+++ b/libsolidity/inlineasm/AsmParser.cpp
@@ -258,11 +258,25 @@ 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()));
- varDecl.location.end = locationOf(*varDecl.value).end;
+ while (true)
+ {
+ varDecl.values.emplace_back(new Statement(parseExpression()));
+ if (m_scanner->currentToken() == Token::Comma)
+ expectToken(Token::Comma);
+ else
+ break;
+ }
+ varDecl.location.end = locationOf(varDecl.values.back()).end;
return varDecl;
}
diff --git a/libsolidity/inlineasm/AsmPrinter.cpp b/libsolidity/inlineasm/AsmPrinter.cpp
index 636e61b8..845aefb9 100644
--- a/libsolidity/inlineasm/AsmPrinter.cpp
+++ b/libsolidity/inlineasm/AsmPrinter.cpp
@@ -121,7 +121,21 @@ 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::algorithm::join(
+ _variableDeclaration.values | boost::adaptors::transformed(
+ [this](Statement statement) { return boost::apply_visitor(*this, statement); }
+ ),
+ ", "
+ );
+ 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)