Merge pull request #8987 from ethereum/sol-yul-bound-functions

[Sol->Yul] Bound functions
This commit is contained in:
chriseth
2020-05-25 16:53:33 +02:00
committed by GitHub
17 changed files with 364 additions and 15 deletions
@@ -627,14 +627,20 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
auto memberAccess = dynamic_cast<MemberAccess const*>(&_functionCall.expression());
if (memberAccess)
{
if (auto expressionType = dynamic_cast<TypeType const*>(memberAccess->expression().annotation().type))
{
solAssert(!functionType->bound(), "");
if (auto contractType = dynamic_cast<ContractType const*>(expressionType->actualType()))
solUnimplementedAssert(
!contractType->contractDefinition().isLibrary() || functionType->kind() == FunctionType::Kind::Internal,
"Only internal function calls implemented for libraries"
);
}
}
else
solAssert(!functionType->bound(), "");
solUnimplementedAssert(!functionType->bound(), "");
switch (functionType->kind())
{
case FunctionType::Kind::Declaration:
@@ -658,14 +664,18 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
else
solAssert(!functionType->hasDeclaration(), "");
if (memberAccess)
solUnimplementedAssert(!functionType->bound(), "");
else
solAssert(!functionType->bound(), "");
solAssert(!functionType->takesArbitraryParameters(), "");
vector<string> args;
if (functionType->bound())
{
solAssert(memberAccess && functionDef, "");
solAssert(functionDef->parameters().size() == arguments.size() + 1, "");
args += convert(memberAccess->expression(), *functionDef->parameters()[0]->type()).stackSlots();
}
else
solAssert(!functionDef || functionDef->parameters().size() == arguments.size(), "");
for (size_t i = 0; i < arguments.size(); ++i)
args += convert(*arguments[i], *parameterTypes[i]).stackSlots();
@@ -1221,13 +1231,27 @@ void IRGeneratorForStatements::endVisit(FunctionCallOptions const& _options)
void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
{
ASTString const& member = _memberAccess.memberName();
if (auto funType = dynamic_cast<FunctionType const*>(_memberAccess.annotation().type))
if (funType->bound())
{
solUnimplementedAssert(false, "");
}
auto memberFunctionType = dynamic_cast<FunctionType const*>(_memberAccess.annotation().type);
Type::Category objectCategory = _memberAccess.expression().annotation().type->category();
switch (_memberAccess.expression().annotation().type->category())
if (memberFunctionType && memberFunctionType->bound())
{
solAssert((set<Type::Category>{
Type::Category::Contract,
Type::Category::Bool,
Type::Category::Integer,
Type::Category::Address,
Type::Category::Function,
Type::Category::Struct,
Type::Category::Enum,
Type::Category::Mapping,
Type::Category::Array,
Type::Category::FixedBytes,
}).count(objectCategory) > 0, "");
return;
}
switch (objectCategory)
{
case Type::Category::Contract:
{
@@ -1460,9 +1484,9 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
{
if (auto const* variable = dynamic_cast<VariableDeclaration const*>(_memberAccess.annotation().referencedDeclaration))
handleVariableReference(*variable, _memberAccess);
else if (auto const* funType = dynamic_cast<FunctionType const*>(_memberAccess.annotation().type))
else if (memberFunctionType)
{
switch (funType->kind())
switch (memberFunctionType->kind())
{
case FunctionType::Kind::Declaration:
break;
@@ -1481,7 +1505,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
break;
case FunctionType::Kind::DelegateCall:
define(IRVariable(_memberAccess).part("address"), _memberAccess.expression());
define(IRVariable(_memberAccess).part("functionIdentifier")) << formatNumber(funType->externalIdentifier()) << "\n";
define(IRVariable(_memberAccess).part("functionIdentifier")) << formatNumber(memberFunctionType->externalIdentifier()) << "\n";
break;
case FunctionType::Kind::External:
case FunctionType::Kind::Creation: