Simplify endVisit() for internal calls

- Define IRHelpers::referencedFunctionDeclaration() to avoid repeating the same dynamic_casts over and over again.
This commit is contained in:
Kamil Śliwak 2020-05-13 18:50:57 +02:00
parent 32bec6b374
commit 0943333276
3 changed files with 33 additions and 33 deletions

View File

@ -99,3 +99,13 @@ string IRNames::zeroValue(Type const& _type, string const& _variableName)
{ {
return "zero_value_for_type_" + _type.identifier() + _variableName; return "zero_value_for_type_" + _type.identifier() + _variableName;
} }
FunctionDefinition const* IRHelpers::referencedFunctionDeclaration(Expression const& _expression)
{
if (auto memberAccess = dynamic_cast<MemberAccess const*>(&_expression))
return dynamic_cast<FunctionDefinition const*>(memberAccess->annotation().referencedDeclaration);
else if (auto identifier = dynamic_cast<Identifier const*>(&_expression))
return dynamic_cast<FunctionDefinition const*>(identifier->annotation().referencedDeclaration);
else
return nullptr;
}

View File

@ -62,6 +62,11 @@ struct IRNames
static std::string zeroValue(Type const& _type, std::string const& _variableName); static std::string zeroValue(Type const& _type, std::string const& _variableName);
}; };
struct IRHelpers
{
static FunctionDefinition const* referencedFunctionDeclaration(Expression const& _expression);
};
} }
// Overloading std::less() makes it possible to use YulArity as a map key. We could define operator< // Overloading std::less() makes it possible to use YulArity as a map key. We could define operator<

View File

@ -625,7 +625,8 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
arguments.push_back(callArguments[std::distance(callArgumentNames.begin(), it)]); arguments.push_back(callArguments[std::distance(callArgumentNames.begin(), it)]);
} }
if (auto memberAccess = dynamic_cast<MemberAccess const*>(&_functionCall.expression())) auto memberAccess = dynamic_cast<MemberAccess const*>(&_functionCall.expression());
if (memberAccess)
if (auto expressionType = dynamic_cast<TypeType const*>(memberAccess->expression().annotation().type)) if (auto expressionType = dynamic_cast<TypeType const*>(memberAccess->expression().annotation().type))
if (auto contractType = dynamic_cast<ContractType const*>(expressionType->actualType())) if (auto contractType = dynamic_cast<ContractType const*>(expressionType->actualType()))
solUnimplementedAssert( solUnimplementedAssert(
@ -641,42 +642,26 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
break; break;
case FunctionType::Kind::Internal: case FunctionType::Kind::Internal:
{ {
optional<FunctionDefinition const*> functionDef; auto identifier = dynamic_cast<Identifier const*>(&_functionCall.expression());
if (auto memberAccess = dynamic_cast<MemberAccess const*>(&_functionCall.expression())) FunctionDefinition const* functionDef = IRHelpers::referencedFunctionDeclaration(_functionCall.expression());
{
solUnimplementedAssert(!functionType->bound(), "Internal calls to bound functions are not yet implemented for libraries and not allowed for contracts");
functionDef = dynamic_cast<FunctionDefinition const*>(memberAccess->annotation().referencedDeclaration); if (functionDef)
if (functionDef.value() != nullptr)
solAssert(functionType->declaration() == *memberAccess->annotation().referencedDeclaration, "");
else
{
solAssert(dynamic_cast<VariableDeclaration const*>(memberAccess->annotation().referencedDeclaration), "");
solAssert(!functionType->hasDeclaration(), "");
}
}
else if (auto identifier = dynamic_cast<Identifier const*>(&_functionCall.expression()))
{ {
solAssert(!functionType->bound(), ""); solAssert(memberAccess || identifier, "");
solAssert(functionType->declaration() == *functionDef, "");
if (auto unresolvedFunctionDef = dynamic_cast<FunctionDefinition const*>(identifier->annotation().referencedDeclaration)) if (identifier)
{ functionDef = &functionDef->resolveVirtual(m_context.mostDerivedContract());
functionDef = &unresolvedFunctionDef->resolveVirtual(m_context.mostDerivedContract());
solAssert(functionType->declaration() == *identifier->annotation().referencedDeclaration, ""); solAssert(functionDef->isImplemented(), "");
}
else
{
functionDef = nullptr;
solAssert(dynamic_cast<VariableDeclaration const*>(identifier->annotation().referencedDeclaration), "");
solAssert(!functionType->hasDeclaration(), "");
}
} }
else else
// Not a simple expression like x or A.x solAssert(!functionType->hasDeclaration(), "");
functionDef = nullptr;
solAssert(functionDef.has_value(), ""); if (memberAccess)
solAssert(functionDef.value() == nullptr || functionDef.value()->isImplemented(), ""); solUnimplementedAssert(!functionType->bound(), "");
else
solAssert(!functionType->bound(), "");
vector<string> args; vector<string> args;
for (size_t i = 0; i < arguments.size(); ++i) for (size_t i = 0; i < arguments.size(); ++i)
@ -685,9 +670,9 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
else else
args += convert(*arguments[i], *parameterTypes[i]).stackSlots(); args += convert(*arguments[i], *parameterTypes[i]).stackSlots();
if (functionDef.value() != nullptr) if (functionDef)
define(_functionCall) << define(_functionCall) <<
m_context.enqueueFunctionForCodeGeneration(*functionDef.value()) << m_context.enqueueFunctionForCodeGeneration(*functionDef) <<
"(" << "(" <<
joinHumanReadable(args) << joinHumanReadable(args) <<
")\n"; ")\n";