mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Re-introduce string type.
This commit is contained in:
parent
f7e3568c62
commit
6949ce97e4
2
AST.cpp
2
AST.cpp
@ -890,6 +890,8 @@ void IndexAccess::checkTypeRequirements(TypePointers const*)
|
|||||||
ArrayType const& type = dynamic_cast<ArrayType const&>(*m_base->getType());
|
ArrayType const& type = dynamic_cast<ArrayType const&>(*m_base->getType());
|
||||||
if (!m_index)
|
if (!m_index)
|
||||||
BOOST_THROW_EXCEPTION(createTypeError("Index expression cannot be omitted."));
|
BOOST_THROW_EXCEPTION(createTypeError("Index expression cannot be omitted."));
|
||||||
|
if (type.isString())
|
||||||
|
BOOST_THROW_EXCEPTION(createTypeError("Index access for string is not possible."));
|
||||||
m_index->expectType(IntegerType(256));
|
m_index->expectType(IntegerType(256));
|
||||||
if (type.isByteArray())
|
if (type.isByteArray())
|
||||||
m_type = make_shared<FixedBytesType>(1);
|
m_type = make_shared<FixedBytesType>(1);
|
||||||
|
@ -824,7 +824,10 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
|
|||||||
if (arrayType.getLocation() == ArrayType::Location::Storage)
|
if (arrayType.getLocation() == ArrayType::Location::Storage)
|
||||||
{
|
{
|
||||||
if (arrayType.isByteArray())
|
if (arrayType.isByteArray())
|
||||||
|
{
|
||||||
|
solAssert(!arrayType.isString(), "Index access to string is not allowed.");
|
||||||
setLValue<StorageByteArrayElement>(_indexAccess);
|
setLValue<StorageByteArrayElement>(_indexAccess);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
setLValueToStorageItem(_indexAccess);
|
setLValueToStorageItem(_indexAccess);
|
||||||
}
|
}
|
||||||
|
2
Token.h
2
Token.h
@ -286,6 +286,7 @@ namespace solidity
|
|||||||
K(Bytes32, "bytes32", 0) \
|
K(Bytes32, "bytes32", 0) \
|
||||||
K(Bytes, "bytes", 0) \
|
K(Bytes, "bytes", 0) \
|
||||||
K(Byte, "byte", 0) \
|
K(Byte, "byte", 0) \
|
||||||
|
K(String, "string", 0) \
|
||||||
K(Address, "address", 0) \
|
K(Address, "address", 0) \
|
||||||
K(Bool, "bool", 0) \
|
K(Bool, "bool", 0) \
|
||||||
K(Real, "real", 0) \
|
K(Real, "real", 0) \
|
||||||
@ -312,7 +313,6 @@ namespace solidity
|
|||||||
K(Match, "match", 0) \
|
K(Match, "match", 0) \
|
||||||
K(Of, "of", 0) \
|
K(Of, "of", 0) \
|
||||||
K(Relocatable, "relocatable", 0) \
|
K(Relocatable, "relocatable", 0) \
|
||||||
T(String, "string", 0) \
|
|
||||||
K(Switch, "switch", 0) \
|
K(Switch, "switch", 0) \
|
||||||
K(Throw, "throw", 0) \
|
K(Throw, "throw", 0) \
|
||||||
K(Try, "try", 0) \
|
K(Try, "try", 0) \
|
||||||
|
20
Types.cpp
20
Types.cpp
@ -145,6 +145,8 @@ TypePointer Type::fromElementaryTypeName(Token::Value _typeToken)
|
|||||||
return make_shared<BoolType>();
|
return make_shared<BoolType>();
|
||||||
else if (_typeToken == Token::Bytes)
|
else if (_typeToken == Token::Bytes)
|
||||||
return make_shared<ArrayType>(ArrayType::Location::Storage);
|
return make_shared<ArrayType>(ArrayType::Location::Storage);
|
||||||
|
else if (_typeToken == Token::String)
|
||||||
|
return make_shared<ArrayType>(ArrayType::Location::Storage, true);
|
||||||
else
|
else
|
||||||
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unable to convert elementary typename " +
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unable to convert elementary typename " +
|
||||||
std::string(Token::toString(_typeToken)) + " to type."));
|
std::string(Token::toString(_typeToken)) + " to type."));
|
||||||
@ -663,7 +665,7 @@ bool ArrayType::isImplicitlyConvertibleTo(const Type& _convertTo) const
|
|||||||
// let us not allow assignment to memory arrays for now
|
// let us not allow assignment to memory arrays for now
|
||||||
if (convertTo.getLocation() != Location::Storage)
|
if (convertTo.getLocation() != Location::Storage)
|
||||||
return false;
|
return false;
|
||||||
if (convertTo.isByteArray() != isByteArray())
|
if (convertTo.isByteArray() != isByteArray() || convertTo.isString() != isString())
|
||||||
return false;
|
return false;
|
||||||
if (!getBaseType()->isImplicitlyConvertibleTo(*convertTo.getBaseType()))
|
if (!getBaseType()->isImplicitlyConvertibleTo(*convertTo.getBaseType()))
|
||||||
return false;
|
return false;
|
||||||
@ -684,8 +686,12 @@ bool ArrayType::operator==(Type const& _other) const
|
|||||||
if (_other.getCategory() != getCategory())
|
if (_other.getCategory() != getCategory())
|
||||||
return false;
|
return false;
|
||||||
ArrayType const& other = dynamic_cast<ArrayType const&>(_other);
|
ArrayType const& other = dynamic_cast<ArrayType const&>(_other);
|
||||||
if (other.m_location != m_location || other.isByteArray() != isByteArray() ||
|
if (
|
||||||
other.isDynamicallySized() != isDynamicallySized())
|
other.m_location != m_location ||
|
||||||
|
other.isByteArray() != isByteArray() ||
|
||||||
|
other.isString() != isString() ||
|
||||||
|
other.isDynamicallySized() != isDynamicallySized()
|
||||||
|
)
|
||||||
return false;
|
return false;
|
||||||
return isDynamicallySized() || getLength() == other.getLength();
|
return isDynamicallySized() || getLength() == other.getLength();
|
||||||
}
|
}
|
||||||
@ -736,7 +742,9 @@ unsigned ArrayType::getSizeOnStack() const
|
|||||||
|
|
||||||
string ArrayType::toString() const
|
string ArrayType::toString() const
|
||||||
{
|
{
|
||||||
if (isByteArray())
|
if (isString())
|
||||||
|
return "string";
|
||||||
|
else if (isByteArray())
|
||||||
return "bytes";
|
return "bytes";
|
||||||
string ret = getBaseType()->toString() + "[";
|
string ret = getBaseType()->toString() + "[";
|
||||||
if (!isDynamicallySized())
|
if (!isDynamicallySized())
|
||||||
@ -746,7 +754,7 @@ string ArrayType::toString() const
|
|||||||
|
|
||||||
TypePointer ArrayType::externalType() const
|
TypePointer ArrayType::externalType() const
|
||||||
{
|
{
|
||||||
if (m_isByteArray)
|
if (m_arrayKind != ArrayKind::Ordinary)
|
||||||
return shared_from_this();
|
return shared_from_this();
|
||||||
if (!m_baseType->externalType())
|
if (!m_baseType->externalType())
|
||||||
return TypePointer();
|
return TypePointer();
|
||||||
@ -762,7 +770,7 @@ TypePointer ArrayType::externalType() const
|
|||||||
shared_ptr<ArrayType> ArrayType::copyForLocation(ArrayType::Location _location) const
|
shared_ptr<ArrayType> ArrayType::copyForLocation(ArrayType::Location _location) const
|
||||||
{
|
{
|
||||||
auto copy = make_shared<ArrayType>(_location);
|
auto copy = make_shared<ArrayType>(_location);
|
||||||
copy->m_isByteArray = m_isByteArray;
|
copy->m_arrayKind = m_arrayKind;
|
||||||
if (m_baseType->getCategory() == Type::Category::Array)
|
if (m_baseType->getCategory() == Type::Category::Array)
|
||||||
copy->m_baseType = dynamic_cast<ArrayType const&>(*m_baseType).copyForLocation(_location);
|
copy->m_baseType = dynamic_cast<ArrayType const&>(*m_baseType).copyForLocation(_location);
|
||||||
else
|
else
|
||||||
|
22
Types.h
22
Types.h
@ -367,10 +367,10 @@ public:
|
|||||||
|
|
||||||
virtual Category getCategory() const override { return Category::Array; }
|
virtual Category getCategory() const override { return Category::Array; }
|
||||||
|
|
||||||
/// Constructor for a byte array ("bytes")
|
/// Constructor for a byte array ("bytes") and string.
|
||||||
explicit ArrayType(Location _location):
|
explicit ArrayType(Location _location, bool _isString = false):
|
||||||
m_location(_location),
|
m_location(_location),
|
||||||
m_isByteArray(true),
|
m_arrayKind(_isString ? ArrayKind::String : ArrayKind::Bytes),
|
||||||
m_baseType(std::make_shared<FixedBytesType>(1))
|
m_baseType(std::make_shared<FixedBytesType>(1))
|
||||||
{}
|
{}
|
||||||
/// Constructor for a dynamically sized array type ("type[]")
|
/// Constructor for a dynamically sized array type ("type[]")
|
||||||
@ -394,11 +394,17 @@ public:
|
|||||||
virtual u256 getStorageSize() const override;
|
virtual u256 getStorageSize() const override;
|
||||||
virtual unsigned getSizeOnStack() const override;
|
virtual unsigned getSizeOnStack() const override;
|
||||||
virtual std::string toString() const override;
|
virtual std::string toString() const override;
|
||||||
virtual MemberList const& getMembers() const override { return s_arrayTypeMemberList; }
|
virtual MemberList const& getMembers() const override
|
||||||
|
{
|
||||||
|
return isString() ? EmptyMemberList : s_arrayTypeMemberList;
|
||||||
|
}
|
||||||
virtual TypePointer externalType() const override;
|
virtual TypePointer externalType() const override;
|
||||||
|
|
||||||
Location getLocation() const { return m_location; }
|
Location getLocation() const { return m_location; }
|
||||||
bool isByteArray() const { return m_isByteArray; }
|
/// @returns true if this is a byte array or a string
|
||||||
|
bool isByteArray() const { return m_arrayKind != ArrayKind::Ordinary; }
|
||||||
|
/// @returns true if this is a string
|
||||||
|
bool isString() const { return m_arrayKind == ArrayKind::String; }
|
||||||
TypePointer const& getBaseType() const { solAssert(!!m_baseType, ""); return m_baseType;}
|
TypePointer const& getBaseType() const { solAssert(!!m_baseType, ""); return m_baseType;}
|
||||||
u256 const& getLength() const { return m_length; }
|
u256 const& getLength() const { return m_length; }
|
||||||
|
|
||||||
@ -407,8 +413,12 @@ public:
|
|||||||
std::shared_ptr<ArrayType> copyForLocation(Location _location) const;
|
std::shared_ptr<ArrayType> copyForLocation(Location _location) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/// String is interpreted as a subtype of Bytes.
|
||||||
|
enum class ArrayKind { Ordinary, Bytes, String };
|
||||||
|
|
||||||
Location m_location;
|
Location m_location;
|
||||||
bool m_isByteArray = false; ///< Byte arrays ("bytes") have different semantics from ordinary arrays.
|
///< Byte arrays ("bytes") and strings have different semantics from ordinary arrays.
|
||||||
|
ArrayKind m_arrayKind = ArrayKind::Ordinary;
|
||||||
TypePointer m_baseType;
|
TypePointer m_baseType;
|
||||||
bool m_hasDynamicLength = true;
|
bool m_hasDynamicLength = true;
|
||||||
u256 m_length;
|
u256 m_length;
|
||||||
|
Loading…
Reference in New Issue
Block a user