diff options
author | Christian <c@ethdev.com> | 2015-02-23 08:31:05 +0800 |
---|---|---|
committer | Christian <c@ethdev.com> | 2015-02-24 01:28:30 +0800 |
commit | 5d2323c91486cfcab9322b01d52ba35525e06272 (patch) | |
tree | 556109fcfcff6c1089732545701dfc397efbf848 | |
parent | 754c804d191ad8f05d886566e599a82efbd38d8e (diff) | |
download | dexon-solidity-5d2323c91486cfcab9322b01d52ba35525e06272.tar dexon-solidity-5d2323c91486cfcab9322b01d52ba35525e06272.tar.gz dexon-solidity-5d2323c91486cfcab9322b01d52ba35525e06272.tar.bz2 dexon-solidity-5d2323c91486cfcab9322b01d52ba35525e06272.tar.lz dexon-solidity-5d2323c91486cfcab9322b01d52ba35525e06272.tar.xz dexon-solidity-5d2323c91486cfcab9322b01d52ba35525e06272.tar.zst dexon-solidity-5d2323c91486cfcab9322b01d52ba35525e06272.zip |
Index and length access for dynamic arrays.
-rw-r--r-- | AST.cpp | 12 | ||||
-rw-r--r-- | ExpressionCompiler.cpp | 18 |
2 files changed, 19 insertions, 11 deletions
@@ -603,7 +603,17 @@ void MemberAccess::checkTypeRequirements() if (!m_type) BOOST_THROW_EXCEPTION(createTypeError("Member \"" + *m_memberName + "\" not found or not " "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() diff --git a/ExpressionCompiler.cpp b/ExpressionCompiler.cpp index dcd411c3..a54915bc 100644 --- a/ExpressionCompiler.cpp +++ b/ExpressionCompiler.cpp @@ -546,7 +546,8 @@ void ExpressionCompiler::endVisit(MemberAccess const& _memberAccess) m_context << eth::Instruction::SWAP1 << eth::Instruction::POP; break; case ArrayType::Location::Storage: - m_context << eth::Instruction::SLOAD; + m_currentLValue = LValue(m_context, LValue::LValueType::Storage, _memberAccess.getType()); + m_currentLValue.retrieveValueIfLValueNotRequested(_memberAccess); break; default: solAssert(false, "Unsupported array location."); @@ -583,13 +584,10 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess) ArrayType const& arrayType = dynamic_cast<ArrayType const&>(baseType); solAssert(arrayType.getLocation() == ArrayType::Location::Storage, "TODO: Index acces only implemented for storage arrays."); - solAssert(!arrayType.isDynamicallySized(), - "TODO: Index acces only implemented for fixed-size arrays."); - solAssert(!arrayType.isByteArray(), - "TODO: Index acces not implemented for byte arrays."); + solAssert(!arrayType.isByteArray(), "TODO: Index acces not implemented for byte arrays."); solAssert(_indexAccess.getIndexExpression(), "Index expression expected."); - // TODO: for dynamically-sized arrays, update the length for each write - // TODO: do we want to check the index? + if (arrayType.isDynamicallySized()) + CompilerUtils(m_context).computeHashStatic(); _indexAccess.getIndexExpression()->accept(*this); m_context << arrayType.getBaseType()->getStorageSize() << eth::Instruction::MUL << eth::Instruction::ADD; @@ -1075,7 +1073,7 @@ void ExpressionCompiler::LValue::retrieveValue(Location const& _location, bool _ { 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 BOOST_THROW_EXCEPTION(CompilerError() << errinfo_sourceLocation(_location) << errinfo_comment("Stack too deep.")); @@ -1124,7 +1122,7 @@ void ExpressionCompiler::LValue::storeValue(Type const& _sourceType, Location co { 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) BOOST_THROW_EXCEPTION(CompilerError() << errinfo_sourceLocation(_location) << errinfo_comment("Stack too deep.")); @@ -1227,7 +1225,7 @@ void ExpressionCompiler::LValue::setToZero(Location const& _location) const { case LValueType::Stack: { - unsigned stackDiff = m_context->baseToCurrentStackOffset(unsigned(m_baseStackOffset)); + unsigned stackDiff = m_context->baseToCurrentStackOffset(m_baseStackOffset); if (stackDiff > 16) BOOST_THROW_EXCEPTION(CompilerError() << errinfo_sourceLocation(_location) << errinfo_comment("Stack too deep.")); |