mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
More flexible array literals.
This commit is contained in:
parent
8735d3fb6c
commit
83e7f5e83e
@ -2565,8 +2565,26 @@ vector<tuple<string, Type const*>> UserDefinedValueType::makeStackItems() const
|
|||||||
|
|
||||||
BoolResult TupleType::isImplicitlyConvertibleTo(Type const& _other) const
|
BoolResult TupleType::isImplicitlyConvertibleTo(Type const& _other) const
|
||||||
{
|
{
|
||||||
if (auto tupleType = dynamic_cast<TupleType const*>(&_other))
|
if (auto arrayType = dynamic_cast<ArrayType const*>(&_other))
|
||||||
{
|
{
|
||||||
|
if (!m_isArrayLiteral)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!(
|
||||||
|
arrayType->isDynamicallySized() ||
|
||||||
|
arrayType->length() == m_components.size()
|
||||||
|
))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (Type const* t: m_components)
|
||||||
|
if (!t->isImplicitlyConvertibleTo(arrayType->baseType()))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (auto tupleType = dynamic_cast<TupleType const*>(&_other))
|
||||||
|
{
|
||||||
|
if (m_isArrayLiteral != tupleType->m_isArrayLiteral)
|
||||||
|
return false;
|
||||||
TypePointers const& targets = tupleType->components();
|
TypePointers const& targets = tupleType->components();
|
||||||
if (targets.empty())
|
if (targets.empty())
|
||||||
return components().empty();
|
return components().empty();
|
||||||
@ -2585,19 +2603,20 @@ BoolResult TupleType::isImplicitlyConvertibleTo(Type const& _other) const
|
|||||||
|
|
||||||
string TupleType::richIdentifier() const
|
string TupleType::richIdentifier() const
|
||||||
{
|
{
|
||||||
return "t_tuple" + identifierList(components());
|
return (m_isArrayLiteral ? "t_arrayLiteral" : "t_tuple") + identifierList(components());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TupleType::operator==(Type const& _other) const
|
bool TupleType::operator==(Type const& _other) const
|
||||||
{
|
{
|
||||||
if (auto tupleType = dynamic_cast<TupleType const*>(&_other))
|
if (auto tupleType = dynamic_cast<TupleType const*>(&_other))
|
||||||
return components() == tupleType->components();
|
return components() == tupleType->components() && m_isArrayLiteral == tupleType->m_isArrayLiteral;
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
string TupleType::toString(bool _short) const
|
string TupleType::toString(bool _short) const
|
||||||
{
|
{
|
||||||
|
// TODO
|
||||||
if (components().empty())
|
if (components().empty())
|
||||||
return "tuple()";
|
return "tuple()";
|
||||||
string str = "tuple(";
|
string str = "tuple(";
|
||||||
@ -2640,7 +2659,8 @@ Type const* TupleType::mobileType() const
|
|||||||
else
|
else
|
||||||
mobiles.push_back(nullptr);
|
mobiles.push_back(nullptr);
|
||||||
}
|
}
|
||||||
return TypeProvider::tuple(move(mobiles));
|
// TODO correct?
|
||||||
|
return TypeProvider::tuple(move(mobiles), m_isArrayLiteral);
|
||||||
}
|
}
|
||||||
|
|
||||||
FunctionType::FunctionType(FunctionDefinition const& _function, Kind _kind):
|
FunctionType::FunctionType(FunctionDefinition const& _function, Kind _kind):
|
||||||
|
@ -1136,7 +1136,10 @@ private:
|
|||||||
class TupleType: public CompositeType
|
class TupleType: public CompositeType
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit TupleType(std::vector<Type const*> _types = {}): m_components(std::move(_types)) {}
|
explicit TupleType(std::vector<Type const*> _types = {}, bool _arrayLiteral = false):
|
||||||
|
m_components(std::move(_types)),
|
||||||
|
m_isArrayLiteral(_arrayLiteral)
|
||||||
|
{}
|
||||||
|
|
||||||
Category category() const override { return Category::Tuple; }
|
Category category() const override { return Category::Tuple; }
|
||||||
|
|
||||||
@ -1150,6 +1153,7 @@ public:
|
|||||||
bool hasSimpleZeroValueInMemory() const override { return false; }
|
bool hasSimpleZeroValueInMemory() const override { return false; }
|
||||||
Type const* mobileType() const override;
|
Type const* mobileType() const override;
|
||||||
|
|
||||||
|
bool isArrayLiteral() const { return m_isArrayLiteral; }
|
||||||
std::vector<Type const*> const& components() const { return m_components; }
|
std::vector<Type const*> const& components() const { return m_components; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@ -1166,6 +1170,7 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<Type const*> const m_components;
|
std::vector<Type const*> const m_components;
|
||||||
|
bool const m_isArrayLiteral;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3256,6 +3256,11 @@ string YulUtilFunctions::conversionFunction(Type const& _from, Type const& _to)
|
|||||||
solAssert(_to.category() == Type::Category::Array, "");
|
solAssert(_to.category() == Type::Category::Array, "");
|
||||||
return arrayConversionFunction(fromArrayType, dynamic_cast<ArrayType const&>(_to));
|
return arrayConversionFunction(fromArrayType, dynamic_cast<ArrayType const&>(_to));
|
||||||
}
|
}
|
||||||
|
else if (auto tupleType = dynamic_cast<TupleType const*>(&_from))
|
||||||
|
{
|
||||||
|
if (tupleType->isArrayLiteral())
|
||||||
|
return arrayLiteralConversionFunction(*tupleType, dynamic_cast<ArrayType const&>(_to));
|
||||||
|
}
|
||||||
|
|
||||||
if (_from.sizeOnStack() != 1 || _to.sizeOnStack() != 1)
|
if (_from.sizeOnStack() != 1 || _to.sizeOnStack() != 1)
|
||||||
return conversionFunctionSpecial(_from, _to);
|
return conversionFunctionSpecial(_from, _to);
|
||||||
@ -3418,10 +3423,8 @@ string YulUtilFunctions::conversionFunction(Type const& _from, Type const& _to)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Type::Category::Tuple:
|
case Type::Category::Tuple:
|
||||||
{
|
solAssert(false, "");
|
||||||
solUnimplementedAssert(false, "Tuple conversion not implemented.");
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case Type::Category::TypeType:
|
case Type::Category::TypeType:
|
||||||
{
|
{
|
||||||
TypeType const& typeType = dynamic_cast<decltype(typeType)>(_from);
|
TypeType const& typeType = dynamic_cast<decltype(typeType)>(_from);
|
||||||
@ -3704,6 +3707,34 @@ string YulUtilFunctions::arrayConversionFunction(ArrayType const& _from, ArrayTy
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string YulUtilFunctions::arrayLiteralConversionFunction(TupleType const& _from, ArrayType const& _to)
|
||||||
|
{
|
||||||
|
solUnimplementedAssert(_to.dataStoredIn(DataLocation::Memory, "");
|
||||||
|
|
||||||
|
string functionName =
|
||||||
|
"convert_arrayliteral_" +
|
||||||
|
_from.identifier() +
|
||||||
|
"_to_" +
|
||||||
|
_to.identifier();
|
||||||
|
|
||||||
|
return m_functionCollector.createFunction(functionName, [&](vector<string>& _args, vector<string>& _ret) {
|
||||||
|
_args = _from.stackItems();
|
||||||
|
_ret = "converted";
|
||||||
|
Whiskers templ(R"(
|
||||||
|
// Copy the array to a free position in memory
|
||||||
|
converted := <allocate>(<length>)
|
||||||
|
<?dynamic>
|
||||||
|
mstore(converted, <length>)
|
||||||
|
</dynamic>
|
||||||
|
<#items>
|
||||||
|
mstore(<pos>, <var>)
|
||||||
|
</items>
|
||||||
|
)");
|
||||||
|
return templ.render();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
string YulUtilFunctions::cleanupFunction(Type const& _type)
|
string YulUtilFunctions::cleanupFunction(Type const& _type)
|
||||||
{
|
{
|
||||||
if (auto userDefinedValueType = dynamic_cast<UserDefinedValueType const*>(&_type))
|
if (auto userDefinedValueType = dynamic_cast<UserDefinedValueType const*>(&_type))
|
||||||
|
@ -530,6 +530,8 @@ private:
|
|||||||
/// Special case of conversion functions - handles all array conversions.
|
/// Special case of conversion functions - handles all array conversions.
|
||||||
std::string arrayConversionFunction(ArrayType const& _from, ArrayType const& _to);
|
std::string arrayConversionFunction(ArrayType const& _from, ArrayType const& _to);
|
||||||
|
|
||||||
|
std::string arrayLiteralConversionFunction(TupleType const& _from, ArrayType const& _to);
|
||||||
|
|
||||||
/// Special case of conversionFunction - handles everything that does not
|
/// Special case of conversionFunction - handles everything that does not
|
||||||
/// use exactly one variable to hold the value.
|
/// use exactly one variable to hold the value.
|
||||||
std::string conversionFunctionSpecial(Type const& _from, Type const& _to);
|
std::string conversionFunctionSpecial(Type const& _from, Type const& _to);
|
||||||
|
Loading…
Reference in New Issue
Block a user