mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #83 from LianaHus/sol_split_the_source_tree
fixed-sized arrays as return type for functions
This commit is contained in:
commit
4a2114ba35
@ -86,16 +86,27 @@ void CompilerUtils::loadFromMemoryDynamic(
|
|||||||
bool _padToWordBoundaries,
|
bool _padToWordBoundaries,
|
||||||
bool _keepUpdatedMemoryOffset
|
bool _keepUpdatedMemoryOffset
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
solAssert(_type.category() != Type::Category::Array, "Arrays not yet implemented.");
|
|
||||||
if (_keepUpdatedMemoryOffset)
|
if (_keepUpdatedMemoryOffset)
|
||||||
m_context << eth::Instruction::DUP1;
|
m_context << eth::Instruction::DUP1;
|
||||||
unsigned numBytes = loadFromMemoryHelper(_type, _fromCalldata, _padToWordBoundaries);
|
|
||||||
if (_keepUpdatedMemoryOffset)
|
if (auto arrayType = dynamic_cast<ArrayType const*>(&_type))
|
||||||
{
|
{
|
||||||
// update memory counter
|
solAssert(!arrayType->isDynamicallySized(), "");
|
||||||
moveToStackTop(_type.sizeOnStack());
|
solAssert(!_fromCalldata, "");
|
||||||
m_context << u256(numBytes) << eth::Instruction::ADD;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1256,10 +1256,14 @@ void ExpressionCompiler::appendExternalFunctionCall(
|
|||||||
}
|
}
|
||||||
else if (firstReturnType)
|
else if (firstReturnType)
|
||||||
{
|
{
|
||||||
//@todo manually update free memory pointer if we accept returning memory-stored objects
|
|
||||||
utils().fetchFreeMemoryPointer();
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -853,6 +853,15 @@ TypePointer ArrayType::externalType() const
|
|||||||
return std::make_shared<ArrayType>(DataLocation::Memory, baseExt, m_length);
|
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
|
TypePointer ArrayType::copyForLocation(DataLocation _location, bool _isPointer) const
|
||||||
{
|
{
|
||||||
auto copy = make_shared<ArrayType>(_location);
|
auto copy = make_shared<ArrayType>(_location);
|
||||||
|
@ -501,6 +501,7 @@ public:
|
|||||||
bool isString() const { return m_arrayKind == ArrayKind::String; }
|
bool isString() const { return m_arrayKind == ArrayKind::String; }
|
||||||
TypePointer const& baseType() const { solAssert(!!m_baseType, ""); return m_baseType;}
|
TypePointer const& baseType() const { solAssert(!!m_baseType, ""); return m_baseType;}
|
||||||
u256 const& length() const { return m_length; }
|
u256 const& length() const { return m_length; }
|
||||||
|
u256 memorySize() const;
|
||||||
|
|
||||||
TypePointer copyForLocation(DataLocation _location, bool _isPointer) const override;
|
TypePointer copyForLocation(DataLocation _location, bool _isPointer) const override;
|
||||||
|
|
||||||
|
@ -5325,6 +5325,35 @@ BOOST_AUTO_TEST_CASE(strings_in_struct)
|
|||||||
BOOST_CHECK(callContractFunction("getLast()") == encodeDyn(s));
|
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()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user