mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Implement switch.
This commit is contained in:
parent
c3705f268c
commit
01d1d08fea
@ -57,7 +57,11 @@ struct BuiltinCall { std::string functionName; std::vector<Expression> arguments
|
|||||||
struct LocalAssignment { std::string variableName; std::unique_ptr<Expression> value; };
|
struct LocalAssignment { std::string variableName; std::unique_ptr<Expression> value; };
|
||||||
struct GlobalAssignment { std::string variableName; std::unique_ptr<Expression> value; };
|
struct GlobalAssignment { std::string variableName; std::unique_ptr<Expression> value; };
|
||||||
struct Block { std::string labelName; std::vector<Expression> statements; };
|
struct Block { std::string labelName; std::vector<Expression> statements; };
|
||||||
struct If { std::unique_ptr<Expression> condition; std::vector<Expression> statements; };
|
struct If {
|
||||||
|
std::unique_ptr<Expression> condition;
|
||||||
|
std::vector<Expression> statements;
|
||||||
|
std::unique_ptr<std::vector<Expression>> elseStatements;
|
||||||
|
};
|
||||||
struct Loop { std::string labelName; std::vector<Expression> statements; };
|
struct Loop { std::string labelName; std::vector<Expression> statements; };
|
||||||
struct Break { Label label; };
|
struct Break { Label label; };
|
||||||
struct Continue { Label label; };
|
struct Continue { Label label; };
|
||||||
|
@ -44,7 +44,10 @@ string EWasmCodeTransform::run(Dialect const& _dialect, yul::Block const& _ast)
|
|||||||
|
|
||||||
for (auto const& statement: _ast.statements)
|
for (auto const& statement: _ast.statements)
|
||||||
{
|
{
|
||||||
yulAssert(statement.type() == typeid(yul::FunctionDefinition), "");
|
yulAssert(
|
||||||
|
statement.type() == typeid(yul::FunctionDefinition),
|
||||||
|
"Expected only function definitions at the highest level."
|
||||||
|
);
|
||||||
functions.emplace_back(transform.translateFunction(boost::get<yul::FunctionDefinition>(statement)));
|
functions.emplace_back(transform.translateFunction(boost::get<yul::FunctionDefinition>(statement)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,19 +60,19 @@ wasm::Expression EWasmCodeTransform::generateMultiAssignment(
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
yulAssert(!_variableNames.empty(), "");
|
yulAssert(!_variableNames.empty(), "");
|
||||||
wasm::LocalAssignment assignment{std::move(_variableNames.front()), std::move(_firstValue)};
|
wasm::LocalAssignment assignment{move(_variableNames.front()), std::move(_firstValue)};
|
||||||
|
|
||||||
if (_variableNames.size() == 1)
|
if (_variableNames.size() == 1)
|
||||||
return move(assignment);
|
return move(assignment);
|
||||||
|
|
||||||
wasm::Block block;
|
wasm::Block block;
|
||||||
block.statements.emplace_back(std::move(assignment));
|
block.statements.emplace_back(move(assignment));
|
||||||
for (size_t i = 1; i < _variableNames.size(); ++i)
|
for (size_t i = 1; i < _variableNames.size(); ++i)
|
||||||
block.statements.emplace_back(wasm::LocalAssignment{
|
block.statements.emplace_back(wasm::LocalAssignment{
|
||||||
std::move(_variableNames.at(i)),
|
move(_variableNames.at(i)),
|
||||||
make_unique<wasm::Expression>(wasm::GlobalVariable{m_globalVariables.at(i - 1).variableName})
|
make_unique<wasm::Expression>(wasm::GlobalVariable{m_globalVariables.at(i - 1).variableName})
|
||||||
});
|
});
|
||||||
return std::move(block);
|
return move(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
wasm::Expression EWasmCodeTransform::operator()(VariableDeclaration const& _varDecl)
|
wasm::Expression EWasmCodeTransform::operator()(VariableDeclaration const& _varDecl)
|
||||||
@ -82,7 +85,7 @@ wasm::Expression EWasmCodeTransform::operator()(VariableDeclaration const& _varD
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (_varDecl.value)
|
if (_varDecl.value)
|
||||||
return generateMultiAssignment(std::move(variableNames), visit(*_varDecl.value));
|
return generateMultiAssignment(move(variableNames), visit(*_varDecl.value));
|
||||||
else
|
else
|
||||||
return wasm::BuiltinCall{"nop", {}};
|
return wasm::BuiltinCall{"nop", {}};
|
||||||
}
|
}
|
||||||
@ -92,7 +95,7 @@ wasm::Expression EWasmCodeTransform::operator()(Assignment const& _assignment)
|
|||||||
vector<string> variableNames;
|
vector<string> variableNames;
|
||||||
for (auto const& var: _assignment.variableNames)
|
for (auto const& var: _assignment.variableNames)
|
||||||
variableNames.emplace_back(var.name.str());
|
variableNames.emplace_back(var.name.str());
|
||||||
return generateMultiAssignment(std::move(variableNames), visit(*_assignment.value));
|
return generateMultiAssignment(move(variableNames), visit(*_assignment.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
wasm::Expression EWasmCodeTransform::operator()(StackAssignment const&)
|
wasm::Expression EWasmCodeTransform::operator()(StackAssignment const&)
|
||||||
@ -150,13 +153,46 @@ wasm::Expression EWasmCodeTransform::operator()(yul::Instruction const&)
|
|||||||
|
|
||||||
wasm::Expression EWasmCodeTransform::operator()(If const& _if)
|
wasm::Expression EWasmCodeTransform::operator()(If const& _if)
|
||||||
{
|
{
|
||||||
return wasm::If{visit(*_if.condition), visit(_if.body.statements)};
|
return wasm::If{visit(*_if.condition), visit(_if.body.statements), {}};
|
||||||
}
|
}
|
||||||
|
|
||||||
wasm::Expression EWasmCodeTransform::operator()(Switch const&)
|
wasm::Expression EWasmCodeTransform::operator()(Switch const& _switch)
|
||||||
{
|
{
|
||||||
solUnimplementedAssert(false, "");
|
wasm::Block block;
|
||||||
return {};
|
string condition = m_nameDispenser.newName("condition"_yulstring).str();
|
||||||
|
m_localVariables.emplace_back(wasm::VariableDeclaration{condition});
|
||||||
|
block.statements.emplace_back(wasm::LocalAssignment{condition, visit(*_switch.expression)});
|
||||||
|
|
||||||
|
vector<wasm::Expression>* currentBlock = &block.statements;
|
||||||
|
for (size_t i = 0; i < _switch.cases.size(); ++i)
|
||||||
|
{
|
||||||
|
Case const& c = _switch.cases.at(i);
|
||||||
|
if (c.value)
|
||||||
|
{
|
||||||
|
wasm::BuiltinCall comparison{"i64.eq", {}};
|
||||||
|
comparison.arguments.emplace_back(wasm::LocalVariable{condition});
|
||||||
|
comparison.arguments.emplace_back(visitReturnByValue(*c.value));
|
||||||
|
wasm::If ifStmnt{
|
||||||
|
make_unique<wasm::Expression>(move(comparison)),
|
||||||
|
visit(c.body.statements),
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
vector<wasm::Expression>* nextBlock = nullptr;
|
||||||
|
if (i != _switch.cases.size() - 1)
|
||||||
|
{
|
||||||
|
ifStmnt.elseStatements = make_unique<vector<wasm::Expression>>();
|
||||||
|
nextBlock = ifStmnt.elseStatements.get();
|
||||||
|
}
|
||||||
|
currentBlock->emplace_back(move(ifStmnt));
|
||||||
|
currentBlock = nextBlock;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
yulAssert(i == _switch.cases.size() - 1, "Default case must be last.");
|
||||||
|
*currentBlock += visit(c.body.statements);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return move(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
wasm::Expression EWasmCodeTransform::operator()(FunctionDefinition const&)
|
wasm::Expression EWasmCodeTransform::operator()(FunctionDefinition const&)
|
||||||
|
@ -84,7 +84,10 @@ string EWasmToText::operator()(wasm::GlobalAssignment const& _assignment)
|
|||||||
|
|
||||||
string EWasmToText::operator()(wasm::If const& _if)
|
string EWasmToText::operator()(wasm::If const& _if)
|
||||||
{
|
{
|
||||||
return "(if " + visit(*_if.condition) + " (then\n" + indented(joinTransformed(_if.statements)) + "\n))\n";
|
string text = "(if " + visit(*_if.condition) + " (then\n" + indented(joinTransformed(_if.statements)) + ")";
|
||||||
|
if (_if.elseStatements)
|
||||||
|
text += "(else\n" + indented(joinTransformed(*_if.elseStatements)) + ")";
|
||||||
|
return std::move(text) + ")\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
string EWasmToText::operator()(wasm::Loop const& _loop)
|
string EWasmToText::operator()(wasm::Loop const& _loop)
|
||||||
|
Loading…
Reference in New Issue
Block a user