Browse Source

Convenience class for type members.

cl-refactor
Christian 10 years ago
parent
commit
6ee07c2cb8
  1. 10
      libsolidity/AST.cpp
  2. 5
      libsolidity/ExpressionCompiler.cpp
  3. 47
      libsolidity/Types.cpp
  4. 47
      libsolidity/Types.h

10
libsolidity/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;
} }

5
libsolidity/ExpressionCompiler.cpp

@ -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
libsolidity/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,33 +246,30 @@ 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();
}
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(); // 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;
} }
u256 StructType::getStorageOffsetOfMember(unsigned _index) const u256 StructType::getStorageOffsetOfMember(string const& _name) 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
libsolidity/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…
Cancel
Save