diff options
author | chriseth <c@ethdev.com> | 2015-09-24 07:12:51 +0800 |
---|---|---|
committer | chriseth <c@ethdev.com> | 2015-09-24 07:12:51 +0800 |
commit | 4a2114ba35eae0a9dae5be2526d107dd19d33baf (patch) | |
tree | 93c0d7c98daf8345bb2d2572fc0ce1cbdda856bb | |
parent | 09f1f1e5955fc358697b49542c6c8eb42496ef10 (diff) | |
parent | c096c3c3490176c8fa61345a38b14078a399962f (diff) | |
download | dexon-solidity-4a2114ba35eae0a9dae5be2526d107dd19d33baf.tar.gz dexon-solidity-4a2114ba35eae0a9dae5be2526d107dd19d33baf.tar.zst dexon-solidity-4a2114ba35eae0a9dae5be2526d107dd19d33baf.zip |
Merge pull request #83 from LianaHus/sol_split_the_source_tree
fixed-sized arrays as return type for functions
-rw-r--r-- | libsolidity/CompilerUtils.cpp | 25 | ||||
-rw-r--r-- | libsolidity/ExpressionCompiler.cpp | 10 | ||||
-rw-r--r-- | libsolidity/Types.cpp | 9 | ||||
-rw-r--r-- | libsolidity/Types.h | 1 | ||||
-rw-r--r-- | test/libsolidity/SolidityEndToEndTest.cpp | 29 |
5 files changed, 64 insertions, 10 deletions
diff --git a/libsolidity/CompilerUtils.cpp b/libsolidity/CompilerUtils.cpp index b9b554e8..a77e6536 100644 --- a/libsolidity/CompilerUtils.cpp +++ b/libsolidity/CompilerUtils.cpp @@ -86,16 +86,27 @@ void CompilerUtils::loadFromMemoryDynamic( bool _padToWordBoundaries, bool _keepUpdatedMemoryOffset ) -{ - solAssert(_type.category() != Type::Category::Array, "Arrays not yet implemented."); +{ if (_keepUpdatedMemoryOffset) m_context << eth::Instruction::DUP1; - unsigned numBytes = loadFromMemoryHelper(_type, _fromCalldata, _padToWordBoundaries); - if (_keepUpdatedMemoryOffset) + + if (auto arrayType = dynamic_cast<ArrayType const*>(&_type)) { - // update memory counter - moveToStackTop(_type.sizeOnStack()); - m_context << u256(numBytes) << eth::Instruction::ADD; + solAssert(!arrayType->isDynamicallySized(), ""); + solAssert(!_fromCalldata, ""); + solAssert(_padToWordBoundaries, ""); + if (_keepUpdatedMemoryOffset) + m_context << arrayType->memorySize() << eth::Instruction::ADD; + } + else + { + unsigned numBytes = loadFromMemoryHelper(_type, _fromCalldata, _padToWordBoundaries); + if (_keepUpdatedMemoryOffset) + { + // update memory counter + moveToStackTop(_type.sizeOnStack()); + m_context << u256(numBytes) << eth::Instruction::ADD; + } } } diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index 65706602..49bf2559 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -1256,10 +1256,14 @@ void ExpressionCompiler::appendExternalFunctionCall( } else if (firstReturnType) { - //@todo manually update free memory pointer if we accept returning memory-stored objects utils().fetchFreeMemoryPointer(); - utils().loadFromMemoryDynamic(*firstReturnType, false, true, false); - + if (dynamic_cast<ReferenceType const*>(firstReturnType)) + { + utils().loadFromMemoryDynamic(*firstReturnType, false, true, true); + utils().storeFreeMemoryPointer(); + } + else + utils().loadFromMemoryDynamic(*firstReturnType, false, true, false); } } diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp index 68e8e91d..18f2817e 100644 --- a/libsolidity/Types.cpp +++ b/libsolidity/Types.cpp @@ -853,6 +853,15 @@ TypePointer ArrayType::externalType() const return std::make_shared<ArrayType>(DataLocation::Memory, baseExt, m_length); } +u256 ArrayType::memorySize() const +{ + solAssert(!isDynamicallySized(), ""); + solAssert(m_location == DataLocation::Memory, ""); + u256 size = m_length * m_baseType->memoryHeadSize(); + solAssert(size <= numeric_limits<unsigned>::max(), "Array size does not fit unsigned."); + return size; +} + TypePointer ArrayType::copyForLocation(DataLocation _location, bool _isPointer) const { auto copy = make_shared<ArrayType>(_location); diff --git a/libsolidity/Types.h b/libsolidity/Types.h index 11218b7a..73111e48 100644 --- a/libsolidity/Types.h +++ b/libsolidity/Types.h @@ -501,6 +501,7 @@ public: bool isString() const { return m_arrayKind == ArrayKind::String; } TypePointer const& baseType() const { solAssert(!!m_baseType, ""); return m_baseType;} u256 const& length() const { return m_length; } + u256 memorySize() const; TypePointer copyForLocation(DataLocation _location, bool _isPointer) const override; diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 8026f216..3124f9cf 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -5325,6 +5325,35 @@ BOOST_AUTO_TEST_CASE(strings_in_struct) BOOST_CHECK(callContractFunction("getLast()") == encodeDyn(s)); } +BOOST_AUTO_TEST_CASE(fixed_arrays_as_return_type) +{ + char const* sourceCode = R"( + contract A { + function f(uint16 input) constant returns (uint16[5] arr) + { + arr[0] = input; + arr[1] = ++input; + arr[2] = ++input; + arr[3] = ++input; + arr[4] = ++input; + } + } + contract B { + function f() returns (uint16[5] res, uint16[5] res2) + { + var a = new A(); + res = a.f(2); + res2 = a.f(1000); + } + } + )"; + compileAndRun(sourceCode, 0, "B"); + BOOST_CHECK(callContractFunction("f()") == encodeArgs( + u256(2), u256(3), u256(4), u256(5), u256(6), // first return argument + u256(1000), u256(1001), u256(1002), u256(1003), u256(1004)) // second return argument + ); +} + BOOST_AUTO_TEST_SUITE_END() } |