mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Index and length access for dynamic arrays.
This commit is contained in:
parent
754c804d19
commit
5d2323c914
12
AST.cpp
12
AST.cpp
@ -603,7 +603,17 @@ void MemberAccess::checkTypeRequirements()
|
|||||||
if (!m_type)
|
if (!m_type)
|
||||||
BOOST_THROW_EXCEPTION(createTypeError("Member \"" + *m_memberName + "\" not found or not "
|
BOOST_THROW_EXCEPTION(createTypeError("Member \"" + *m_memberName + "\" not found or not "
|
||||||
"visible in " + type.toString()));
|
"visible in " + type.toString()));
|
||||||
m_isLValue = (type.getCategory() == Type::Category::Struct);
|
// This should probably move somewhere else.
|
||||||
|
if (type.getCategory() == Type::Category::Struct)
|
||||||
|
m_isLValue = true;
|
||||||
|
else if (type.getCategory() == Type::Category::Array)
|
||||||
|
{
|
||||||
|
auto const& arrayType(dynamic_cast<ArrayType const&>(type));
|
||||||
|
m_isLValue = (*m_memberName == "length" &&
|
||||||
|
arrayType.getLocation() != ArrayType::Location::CallData && arrayType.isDynamicallySized());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_isLValue = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IndexAccess::checkTypeRequirements()
|
void IndexAccess::checkTypeRequirements()
|
||||||
|
@ -546,7 +546,8 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess)
|
|||||||
m_context << eth::Instruction::SWAP1 << eth::Instruction::POP;
|
m_context << eth::Instruction::SWAP1 << eth::Instruction::POP;
|
||||||
break;
|
break;
|
||||||
case ArrayType::Location::Storage:
|
case ArrayType::Location::Storage:
|
||||||
m_context << eth::Instruction::SLOAD;
|
m_currentLValue = LValue(m_context, LValue::LValueType::Storage, _memberAccess.getType());
|
||||||
|
m_currentLValue.retrieveValueIfLValueNotRequested(_memberAccess);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
solAssert(false, "Unsupported array location.");
|
solAssert(false, "Unsupported array location.");
|
||||||
@ -583,13 +584,10 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
|
|||||||
ArrayType const& arrayType = dynamic_cast<ArrayType const&>(baseType);
|
ArrayType const& arrayType = dynamic_cast<ArrayType const&>(baseType);
|
||||||
solAssert(arrayType.getLocation() == ArrayType::Location::Storage,
|
solAssert(arrayType.getLocation() == ArrayType::Location::Storage,
|
||||||
"TODO: Index acces only implemented for storage arrays.");
|
"TODO: Index acces only implemented for storage arrays.");
|
||||||
solAssert(!arrayType.isDynamicallySized(),
|
solAssert(!arrayType.isByteArray(), "TODO: Index acces not implemented for byte arrays.");
|
||||||
"TODO: Index acces only implemented for fixed-size arrays.");
|
|
||||||
solAssert(!arrayType.isByteArray(),
|
|
||||||
"TODO: Index acces not implemented for byte arrays.");
|
|
||||||
solAssert(_indexAccess.getIndexExpression(), "Index expression expected.");
|
solAssert(_indexAccess.getIndexExpression(), "Index expression expected.");
|
||||||
// TODO: for dynamically-sized arrays, update the length for each write
|
if (arrayType.isDynamicallySized())
|
||||||
// TODO: do we want to check the index?
|
CompilerUtils(m_context).computeHashStatic();
|
||||||
_indexAccess.getIndexExpression()->accept(*this);
|
_indexAccess.getIndexExpression()->accept(*this);
|
||||||
m_context << arrayType.getBaseType()->getStorageSize() << eth::Instruction::MUL
|
m_context << arrayType.getBaseType()->getStorageSize() << eth::Instruction::MUL
|
||||||
<< eth::Instruction::ADD;
|
<< eth::Instruction::ADD;
|
||||||
@ -1075,7 +1073,7 @@ void ExpressionCompiler::LValue::retrieveValue(Location const& _location, bool _
|
|||||||
{
|
{
|
||||||
case LValueType::Stack:
|
case LValueType::Stack:
|
||||||
{
|
{
|
||||||
unsigned stackPos = m_context->baseToCurrentStackOffset(unsigned(m_baseStackOffset));
|
unsigned stackPos = m_context->baseToCurrentStackOffset(m_baseStackOffset);
|
||||||
if (stackPos >= 15) //@todo correct this by fetching earlier or moving to memory
|
if (stackPos >= 15) //@todo correct this by fetching earlier or moving to memory
|
||||||
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_sourceLocation(_location)
|
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_sourceLocation(_location)
|
||||||
<< errinfo_comment("Stack too deep."));
|
<< errinfo_comment("Stack too deep."));
|
||||||
@ -1124,7 +1122,7 @@ void ExpressionCompiler::LValue::storeValue(Type const& _sourceType, Location co
|
|||||||
{
|
{
|
||||||
case LValueType::Stack:
|
case LValueType::Stack:
|
||||||
{
|
{
|
||||||
unsigned stackDiff = m_context->baseToCurrentStackOffset(unsigned(m_baseStackOffset)) - m_size + 1;
|
unsigned stackDiff = m_context->baseToCurrentStackOffset(m_baseStackOffset) - m_size + 1;
|
||||||
if (stackDiff > 16)
|
if (stackDiff > 16)
|
||||||
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_sourceLocation(_location)
|
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_sourceLocation(_location)
|
||||||
<< errinfo_comment("Stack too deep."));
|
<< errinfo_comment("Stack too deep."));
|
||||||
@ -1227,7 +1225,7 @@ void ExpressionCompiler::LValue::setToZero(Location const& _location) const
|
|||||||
{
|
{
|
||||||
case LValueType::Stack:
|
case LValueType::Stack:
|
||||||
{
|
{
|
||||||
unsigned stackDiff = m_context->baseToCurrentStackOffset(unsigned(m_baseStackOffset));
|
unsigned stackDiff = m_context->baseToCurrentStackOffset(m_baseStackOffset);
|
||||||
if (stackDiff > 16)
|
if (stackDiff > 16)
|
||||||
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_sourceLocation(_location)
|
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_sourceLocation(_location)
|
||||||
<< errinfo_comment("Stack too deep."));
|
<< errinfo_comment("Stack too deep."));
|
||||||
|
Loading…
Reference in New Issue
Block a user