mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Support multiple variables in a variable declaration in inline assembly
This commit is contained in:
parent
74d2e7311a
commit
15b4d4def2
@ -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)
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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) { ... }")
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user