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->checkTypeRequirements();
|
||||||
m_expression->requireLValue();
|
m_expression->requireLValue();
|
||||||
if (m_expression->getType()->getCategory() != Type::Category::STRUCT)
|
Type const& type = *m_expression->getType();
|
||||||
BOOST_THROW_EXCEPTION(createTypeError("Member access to a non-struct (is " +
|
m_type = type.getMemberType(*m_memberName);
|
||||||
m_expression->getType()->toString() + ")"));
|
if (!m_type)
|
||||||
StructType const& type = dynamic_cast<StructType const&>(*m_expression->getType());
|
|
||||||
unsigned memberIndex = type.memberNameToIndex(*m_memberName);
|
|
||||||
if (memberIndex >= type.getMemberCount())
|
|
||||||
BOOST_THROW_EXCEPTION(createTypeError("Member \"" + *m_memberName + "\" not found in " + type.toString()));
|
BOOST_THROW_EXCEPTION(createTypeError("Member \"" + *m_memberName + "\" not found in " + type.toString()));
|
||||||
m_type = type.getMemberByIndex(memberIndex);
|
|
||||||
m_isLvalue = true;
|
m_isLvalue = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,10 +208,7 @@ void ExpressionCompiler::endVisit(MemberAccess& _memberAccess)
|
|||||||
if (asserts(m_currentLValue.isInStorage()))
|
if (asserts(m_currentLValue.isInStorage()))
|
||||||
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Member access to a non-storage value."));
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Member access to a non-storage value."));
|
||||||
StructType const& type = dynamic_cast<StructType const&>(*_memberAccess.getExpression().getType());
|
StructType const& type = dynamic_cast<StructType const&>(*_memberAccess.getExpression().getType());
|
||||||
unsigned memberIndex = type.memberNameToIndex(_memberAccess.getMemberName());
|
m_context << type.getStorageOffsetOfMember(_memberAccess.getMemberName()) << eth::Instruction::ADD;
|
||||||
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_currentLValue.retrieveValueIfLValueNotRequested(_memberAccess);
|
m_currentLValue.retrieveValueIfLValueNotRequested(_memberAccess);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
47
Types.cpp
47
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)
|
shared_ptr<IntegerType> IntegerType::smallestTypeForLiteral(string const& _literal)
|
||||||
{
|
{
|
||||||
bigint value(_literal);
|
bigint value(_literal);
|
||||||
@ -226,15 +228,15 @@ bool StructType::operator==(Type const& _other) const
|
|||||||
u256 StructType::getStorageSize() const
|
u256 StructType::getStorageSize() const
|
||||||
{
|
{
|
||||||
u256 size = 0;
|
u256 size = 0;
|
||||||
for (ASTPointer<VariableDeclaration> const& variable: m_struct.getMembers())
|
for (pair<string, shared_ptr<Type const>> const& member: getMembers())
|
||||||
size += variable->getType()->getStorageSize();
|
size += member.second->getStorageSize();
|
||||||
return max<u256>(1, size);
|
return max<u256>(1, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StructType::canLiveOutsideStorage() const
|
bool StructType::canLiveOutsideStorage() const
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < getMemberCount(); ++i)
|
for (pair<string, shared_ptr<Type const>> const& member: getMembers())
|
||||||
if (!getMemberByIndex(i)->canLiveOutsideStorage())
|
if (!member.second->canLiveOutsideStorage())
|
||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -244,34 +246,31 @@ string StructType::toString() const
|
|||||||
return string("struct ") + m_struct.getName();
|
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
|
u256 StructType::getStorageOffsetOfMember(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
|
|
||||||
{
|
{
|
||||||
//@todo cache member offset?
|
//@todo cache member offset?
|
||||||
u256 offset;
|
u256 offset;
|
||||||
// vector<ASTPointer<VariableDeclaration>> const& members = m_struct.getMembers();
|
for (ASTPointer<VariableDeclaration> variable: m_struct.getMembers())
|
||||||
for (unsigned index = 0; index < _index; ++index)
|
{
|
||||||
offset += getMemberByIndex(index)->getStorageSize();
|
offset += variable->getType()->getStorageSize();
|
||||||
|
if (variable->getName() == _name)
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Storage offset of non-existing member requested."));
|
||||||
|
}
|
||||||
|
|
||||||
bool FunctionType::operator==(Type const& _other) const
|
bool FunctionType::operator==(Type const& _other) const
|
||||||
{
|
{
|
||||||
|
47
Types.h
47
Types.h
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <map>
|
||||||
#include <boost/noncopyable.hpp>
|
#include <boost/noncopyable.hpp>
|
||||||
#include <libdevcore/Common.h>
|
#include <libdevcore/Common.h>
|
||||||
#include <libsolidity/Exceptions.h>
|
#include <libsolidity/Exceptions.h>
|
||||||
@ -37,6 +38,33 @@ namespace solidity
|
|||||||
|
|
||||||
// @todo realMxN, string<N>
|
// @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.
|
* 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.
|
/// Returns false if the type cannot live outside the storage, i.e. if it includes some mapping.
|
||||||
virtual bool canLiveOutsideStorage() const { return true; }
|
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 std::string toString() const = 0;
|
||||||
virtual u256 literalValue(Literal const&) const
|
virtual u256 literalValue(Literal const&) const
|
||||||
{
|
{
|
||||||
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Literal value requested "
|
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Literal value requested "
|
||||||
"for type without literals."));
|
"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 bool canLiveOutsideStorage() const;
|
||||||
virtual std::string toString() const override;
|
virtual std::string toString() const override;
|
||||||
|
|
||||||
unsigned getMemberCount() const;
|
virtual MemberList const& getMembers() const override;
|
||||||
/// 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;
|
u256 getStorageOffsetOfMember(std::string const& _name) const;
|
||||||
std::shared_ptr<Type const> const& getMemberByIndex(unsigned _index) const;
|
|
||||||
u256 getStorageOffsetOfMember(unsigned _index) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
StructDefinition const& m_struct;
|
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