[Sol2Yul] Implements function-to-function cast.

This commit is contained in:
Christian Parpart 2020-03-03 12:20:04 +01:00
parent c8cbb98002
commit e210026e74
2 changed files with 52 additions and 0 deletions

View File

@ -1333,6 +1333,35 @@ string YulUtilFunctions::allocateMemoryArrayFunction(ArrayType const& _type)
string YulUtilFunctions::conversionFunction(Type const& _from, Type const& _to)
{
if (_from.category() == Type::Category::Function)
{
solAssert(_to.category() == Type::Category::Function, "");
FunctionType const& fromType = dynamic_cast<FunctionType const&>(_from);
FunctionType const& targetType = dynamic_cast<FunctionType const&>(_to);
solAssert(
fromType.isImplicitlyConvertibleTo(targetType) &&
fromType.sizeOnStack() == targetType.sizeOnStack() &&
(fromType.kind() == FunctionType::Kind::Internal || fromType.kind() == FunctionType::Kind::External) &&
fromType.kind() == targetType.kind(),
"Invalid function type conversion requested."
);
string const functionName =
"convert_" +
_from.identifier() +
"_to_" +
_to.identifier();
return m_functionCollector->createFunction(functionName, [&]() {
return Whiskers(R"(
function <functionName>(addr, functionId) -> outAddr, outFunctionId {
outAddr := addr
outFunctionId := functionId
}
)")
("functionName", functionName)
.render();
});
}
if (_from.sizeOnStack() != 1 || _to.sizeOnStack() != 1)
return conversionFunctionSpecial(_from, _to);

View File

@ -0,0 +1,23 @@
contract C {
function f(uint x) public pure returns (uint) {
return 2 * x;
}
function g() public view returns (function (uint) external returns (uint)) {
return this.f;
}
function h(uint x) public returns (uint) {
return this.g()(x) + 1;
}
function t() external view returns (
function(uint) external returns (uint) a,
function(uint) external view returns (uint) b) {
a = this.f;
b = this.f;
}
}
// ====
// compileViaYul: also
// ----
// f(uint256): 2 -> 4
// h(uint256): 2 -> 5
// t() -> 0xFDD67305928FCAC8D213D1E47BFA6165CD0B87BB3DE648B0000000000000000, 0xFDD67305928FCAC8D213D1E47BFA6165CD0B87BB3DE648B0000000000000000