aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian <c@ethdev.com>2015-02-23 08:31:05 +0800
committerChristian <c@ethdev.com>2015-02-24 01:28:30 +0800
commit5d2323c91486cfcab9322b01d52ba35525e06272 (patch)
tree556109fcfcff6c1089732545701dfc397efbf848
parent754c804d191ad8f05d886566e599a82efbd38d8e (diff)
downloaddexon-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.cpp12
-rw-r--r--ExpressionCompiler.cpp18
2 files changed, 19 insertions, 11 deletions
diff --git a/AST.cpp b/AST.cpp
index 17946115..c37e8c37 100644
--- a/AST.cpp
+++ b/AST.cpp
@@ -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."));