mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Convenience class for type members.
This commit is contained in:
parent
735dbe6986
commit
fa987e0a20
10
AST.cpp
10
AST.cpp
@ -462,14 +462,10 @@ void MemberAccess::checkTypeRequirements()
|
||||
{
|
||||
m_expression->checkTypeRequirements();
|
||||
m_expression->requireLValue();
|
||||
if (m_expression->getType()->getCategory() != Type::Category::STRUCT)
|
||||
BOOST_THROW_EXCEPTION(createTypeError("Member access to a non-struct (is " +
|
||||
m_expression->getType()->toString() + ")"));
|
||||
StructType const& type = dynamic_cast<StructType const&>(*m_expression->getType());
|
||||
unsigned memberIndex = type.memberNameToIndex(*m_memberName);
|
||||
if (memberIndex >= type.getMemberCount())
|
||||
Type const& type = *m_expression->getType();
|
||||
m_type = type.getMemberType(*m_memberName);
|
||||
if (!m_type)
|
||||
BOOST_THROW_EXCEPTION(createTypeError("Member \"" + *m_memberName + "\" not found in " + type.toString()));
|
||||
m_type = type.getMemberByIndex(memberIndex);
|
||||
m_isLvalue = true;
|
||||
}
|
||||
|
||||
|
@ -208,10 +208,7 @@ void ExpressionCompiler::endVisit(MemberAccess& _memberAccess)
|
||||
if (asserts(m_currentLValue.isInStorage()))
|
||||
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Member access to a non-storage value."));
|
||||
StructType const& type = dynamic_cast<StructType const&>(*_memberAccess.getExpression().getType());
|
||||
unsigned memberIndex = type.memberNameToIndex(_memberAccess.getMemberName());
|
||||
if (asserts(memberIndex <= type.getMemberCount()))
|
||||
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Member not found in struct during compilation."));
|
||||
m_context << type.getStorageOffsetOfMember(memberIndex) << eth::Instruction::ADD;
|
||||
m_context << type.getStorageOffsetOfMember(_memberAccess.getMemberName()) << eth::Instruction::ADD;
|
||||
m_currentLValue.retrieveValueIfLValueNotRequested(_memberAccess);
|
||||
}
|
||||
|
||||
|
49
Types.cpp
49
Types.cpp
@ -86,6 +86,8 @@ shared_ptr<Type> Type::forLiteral(Literal const& _literal)
|
||||
}
|
||||
}
|
||||
|
||||
const MemberList Type::EmptyMemberList = MemberList();
|
||||
|
||||
shared_ptr<IntegerType> IntegerType::smallestTypeForLiteral(string const& _literal)
|
||||
{
|
||||
bigint value(_literal);
|
||||
@ -226,15 +228,15 @@ bool StructType::operator==(Type const& _other) const
|
||||
u256 StructType::getStorageSize() const
|
||||
{
|
||||
u256 size = 0;
|
||||
for (ASTPointer<VariableDeclaration> const& variable: m_struct.getMembers())
|
||||
size += variable->getType()->getStorageSize();
|
||||
for (pair<string, shared_ptr<Type const>> const& member: getMembers())
|
||||
size += member.second->getStorageSize();
|
||||
return max<u256>(1, size);
|
||||
}
|
||||
|
||||
bool StructType::canLiveOutsideStorage() const
|
||||
{
|
||||
for (unsigned i = 0; i < getMemberCount(); ++i)
|
||||
if (!getMemberByIndex(i)->canLiveOutsideStorage())
|
||||
for (pair<string, shared_ptr<Type const>> const& member: getMembers())
|
||||
if (!member.second->canLiveOutsideStorage())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
@ -244,33 +246,30 @@ string StructType::toString() const
|
||||
return string("struct ") + m_struct.getName();
|
||||
}
|
||||
|
||||
unsigned StructType::getMemberCount() const
|
||||
MemberList const& StructType::getMembers() const
|
||||
{
|
||||
return m_struct.getMembers().size();
|
||||
// We need to lazy-initialize it because of recursive references.
|
||||
if (!m_members)
|
||||
{
|
||||
map<string, shared_ptr<Type const>> members;
|
||||
for (ASTPointer<VariableDeclaration> const& variable: m_struct.getMembers())
|
||||
members[variable->getName()] = variable->getType();
|
||||
m_members.reset(new MemberList(members));
|
||||
}
|
||||
return *m_members;
|
||||
}
|
||||
|
||||
unsigned StructType::memberNameToIndex(string const& _name) const
|
||||
{
|
||||
vector<ASTPointer<VariableDeclaration>> const& members = m_struct.getMembers();
|
||||
for (unsigned index = 0; index < members.size(); ++index)
|
||||
if (members[index]->getName() == _name)
|
||||
return index;
|
||||
return unsigned(-1);
|
||||
}
|
||||
|
||||
shared_ptr<Type const> const& StructType::getMemberByIndex(unsigned _index) const
|
||||
{
|
||||
return m_struct.getMembers()[_index].getType();
|
||||
}
|
||||
|
||||
u256 StructType::getStorageOffsetOfMember(unsigned _index) const
|
||||
u256 StructType::getStorageOffsetOfMember(string const& _name) const
|
||||
{
|
||||
//@todo cache member offset?
|
||||
u256 offset;
|
||||
// vector<ASTPointer<VariableDeclaration>> const& members = m_struct.getMembers();
|
||||
for (unsigned index = 0; index < _index; ++index)
|
||||
offset += getMemberByIndex(index)->getStorageSize();
|
||||
return offset;
|
||||
for (ASTPointer<VariableDeclaration> variable: m_struct.getMembers())
|
||||
{
|
||||
offset += variable->getType()->getStorageSize();
|
||||
if (variable->getName() == _name)
|
||||
return offset;
|
||||
}
|
||||
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Storage offset of non-existing member requested."));
|
||||
}
|
||||
|
||||
bool FunctionType::operator==(Type const& _other) const
|
||||
|
47
Types.h
47
Types.h
@ -24,6 +24,7 @@
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <libdevcore/Common.h>
|
||||
#include <libsolidity/Exceptions.h>
|
||||
@ -37,6 +38,33 @@ namespace solidity
|
||||
|
||||
// @todo realMxN, string<N>
|
||||
|
||||
class Type; // forward
|
||||
|
||||
/**
|
||||
* List of members of a type.
|
||||
*/
|
||||
class MemberList
|
||||
{
|
||||
public:
|
||||
using TypePointer = std::shared_ptr<Type const>;
|
||||
using MemberMap = std::map<std::string, TypePointer>;
|
||||
|
||||
MemberList() {}
|
||||
explicit MemberList(MemberMap const& _members): m_memberTypes(_members) {}
|
||||
TypePointer getMemberType(std::string const& _name) const
|
||||
{
|
||||
auto it = m_memberTypes.find(_name);
|
||||
return it != m_memberTypes.end() ? it->second : std::shared_ptr<Type const>();
|
||||
}
|
||||
|
||||
MemberMap::const_iterator begin() const { return m_memberTypes.begin(); }
|
||||
MemberMap::const_iterator end() const { return m_memberTypes.end(); }
|
||||
|
||||
private:
|
||||
MemberMap m_memberTypes;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Abstract base class that forms the root of the type hierarchy.
|
||||
*/
|
||||
@ -81,12 +109,21 @@ public:
|
||||
/// Returns false if the type cannot live outside the storage, i.e. if it includes some mapping.
|
||||
virtual bool canLiveOutsideStorage() const { return true; }
|
||||
|
||||
/// Returns the list of all members of this type. Default implementation: no members.
|
||||
virtual MemberList const& getMembers() const { return EmptyMemberList; }
|
||||
/// Convenience method, returns the type of the given named member or an empty pointer if no such member exists.
|
||||
std::shared_ptr<Type const> getMemberType(std::string const& _name) const { return getMembers().getMemberType(_name); }
|
||||
|
||||
virtual std::string toString() const = 0;
|
||||
virtual u256 literalValue(Literal const&) const
|
||||
{
|
||||
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Literal value requested "
|
||||
"for type without literals."));
|
||||
}
|
||||
|
||||
protected:
|
||||
/// Convenience object used when returning an empty member list.
|
||||
static const MemberList EmptyMemberList;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -187,14 +224,14 @@ public:
|
||||
virtual bool canLiveOutsideStorage() const;
|
||||
virtual std::string toString() const override;
|
||||
|
||||
unsigned getMemberCount() const;
|
||||
/// Returns the index of the member with name @a _name or unsigned(-1) if it does not exist.
|
||||
unsigned memberNameToIndex(std::string const& _name) const;
|
||||
std::shared_ptr<Type const> const& getMemberByIndex(unsigned _index) const;
|
||||
u256 getStorageOffsetOfMember(unsigned _index) const;
|
||||
virtual MemberList const& getMembers() const override;
|
||||
|
||||
u256 getStorageOffsetOfMember(std::string const& _name) const;
|
||||
|
||||
private:
|
||||
StructDefinition const& m_struct;
|
||||
/// List of member types, will be lazy-initialized because of recursive references.
|
||||
mutable std::unique_ptr<MemberList> m_members;
|
||||
};
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user