Browse Source

Accessors for multiple mappings implemented

cl-refactor
Lefteris Karapetsas 10 years ago
parent
commit
6c5120978e
  1. 43
      libsolidity/ExpressionCompiler.cpp
  2. 22
      libsolidity/Types.cpp
  3. 3
      test/SolidityEndToEndTest.cpp
  4. 15
      test/SolidityNameAndTypeResolution.cpp

43
libsolidity/ExpressionCompiler.cpp

@ -22,6 +22,7 @@
#include <utility> #include <utility>
#include <numeric> #include <numeric>
#include <boost/range/adaptor/reversed.hpp>
#include <libdevcore/Common.h> #include <libdevcore/Common.h>
#include <libdevcrypto/SHA3.h> #include <libdevcrypto/SHA3.h>
#include <libsolidity/AST.h> #include <libsolidity/AST.h>
@ -847,36 +848,34 @@ unsigned ExpressionCompiler::appendExpressionCopyToMemory(Type const& _expectedT
void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& _varDecl) void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const& _varDecl)
{ {
TypePointer resultType = _varDecl.getType(); FunctionType thisType(_varDecl);
auto mappingType = dynamic_cast<const MappingType*>(resultType.get()); solAssert(thisType.getReturnParameterTypes().size() == 1, "");
TypePointer const& resultType = thisType.getReturnParameterTypes().front();
unsigned sizeOnStack; unsigned sizeOnStack;
if (mappingType != nullptr) unsigned length = 0;
{ TypePointers const& params = thisType.getParameterTypes();
// this copies from ExpressionCompiler::visit(IndexAccess .. ) for mapping access // move arguments to memory
TypePointer const& keyType = mappingType->getKeyType(); for (TypePointer const& param: boost::adaptors::reverse(params))
unsigned length = appendTypeConversionAndMoveToMemory(*keyType, *keyType, Location()); length += appendTypeConversionAndMoveToMemory(*param, *param, Location(), length);
solAssert(length == 32, "Mapping key has to take 32 bytes in memory (for now).");
// @todo move this once we actually use memory // retrieve the position of the mapping
m_context << m_context.getStorageLocationOfVariable(_varDecl); m_context << m_context.getStorageLocationOfVariable(_varDecl);
length += CompilerUtils(m_context).storeInMemory(length);
m_context << u256(length) << u256(0) << eth::Instruction::SHA3;
m_currentLValue = LValue(m_context, LValue::STORAGE, *mappingType->getValueType());
m_currentLValue.retrieveValue(mappingType->getValueType(), Location(), true);
m_currentLValue.reset();
resultType = mappingType->getValueType(); for (TypePointer const& param: params)
}
else
{ {
m_currentLValue.fromStateVariable(_varDecl, _varDecl.getType()); // move offset to memory
solAssert(m_currentLValue.isInStorage(), ""); CompilerUtils(m_context).storeInMemory(length);
m_currentLValue.retrieveValue(_varDecl.getType(), Location(), true); unsigned argLen = CompilerUtils::getPaddedSize(param->getCalldataEncodedSize());
length -= argLen;
m_context << u256(argLen + 32) << u256(length) << eth::Instruction::SHA3;
} }
sizeOnStack = _varDecl.getType()->getSizeOnStack();
m_currentLValue = LValue(m_context, LValue::STORAGE, *resultType);
m_currentLValue.retrieveValue(resultType, Location(), true);
sizeOnStack = resultType->getSizeOnStack();
solAssert(sizeOnStack <= 15, "Stack too deep."); solAssert(sizeOnStack <= 15, "Stack too deep.");
m_context << eth::dupInstruction(sizeOnStack + 1) << eth::Instruction::JUMP; m_context << eth::dupInstruction(sizeOnStack + 1) << eth::Instruction::JUMP;
} }
ExpressionCompiler::LValue::LValue(CompilerContext& _compilerContext, LValueType _type, Type const& _dataType, ExpressionCompiler::LValue::LValue(CompilerContext& _compilerContext, LValueType _type, Type const& _dataType,

22
libsolidity/Types.cpp

@ -626,20 +626,20 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl):
TypePointers retParams; TypePointers retParams;
vector<string> retParamNames; vector<string> retParamNames;
TypePointer varDeclType = _varDecl.getType(); TypePointer varDeclType = _varDecl.getType();
auto mappingType = dynamic_cast<const MappingType*>(varDeclType.get()); auto mappingType = dynamic_cast<MappingType const*>(varDeclType.get());
if (mappingType!= nullptr) auto returnType = varDeclType;
{
params.push_back(mappingType->getKeyType());
paramNames.push_back(mappingType->getKeyType()->toString());
retParams.push_back(mappingType->getValueType()); while (mappingType!= nullptr)
retParamNames.push_back(mappingType->getValueType()->toString());
}
else // elelemntary type
{ {
retParams.push_back(varDeclType); params.push_back(mappingType->getKeyType());
retParamNames.push_back(_varDecl.getName()); paramNames.push_back("");
returnType = mappingType->getValueType();
mappingType = dynamic_cast<MappingType const*>(mappingType->getValueType().get());
} }
retParams.push_back(returnType);
retParamNames.push_back("");
swap(params, m_parameterTypes); swap(params, m_parameterTypes);
swap(paramNames, m_parameterNames); swap(paramNames, m_parameterNames);
swap(retParams, m_returnParameterTypes); swap(retParams, m_returnParameterTypes);

3
test/SolidityEndToEndTest.cpp

@ -925,16 +925,19 @@ BOOST_AUTO_TEST_CASE(complex_accessors)
" mapping(uint256 => string4) to_string_map;\n" " mapping(uint256 => string4) to_string_map;\n"
" mapping(uint256 => bool) to_bool_map;\n" " mapping(uint256 => bool) to_bool_map;\n"
" mapping(uint256 => uint256) to_uint_map;\n" " mapping(uint256 => uint256) to_uint_map;\n"
" mapping(uint256 => mapping(uint256 => uint256)) to_multiple_map;\n"
" function test() {\n" " function test() {\n"
" to_string_map[42] = \"24\";\n" " to_string_map[42] = \"24\";\n"
" to_bool_map[42] = false;\n" " to_bool_map[42] = false;\n"
" to_uint_map[42] = 12;\n" " to_uint_map[42] = 12;\n"
" to_multiple_map[42][23] = 31;\n"
" }\n" " }\n"
"}\n"; "}\n";
compileAndRun(sourceCode); compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("to_string_map(uint256)", 42) == encodeArgs("24")); BOOST_CHECK(callContractFunction("to_string_map(uint256)", 42) == encodeArgs("24"));
BOOST_CHECK(callContractFunction("to_bool_map(uint256)", 42) == encodeArgs(false)); BOOST_CHECK(callContractFunction("to_bool_map(uint256)", 42) == encodeArgs(false));
BOOST_CHECK(callContractFunction("to_uint_map(uint256)", 42) == encodeArgs(12)); BOOST_CHECK(callContractFunction("to_uint_map(uint256)", 42) == encodeArgs(12));
BOOST_CHECK(callContractFunction("to_multiple_map(uint256,uint256)", 42, 23) == encodeArgs(31));
} }
BOOST_AUTO_TEST_CASE(balance) BOOST_AUTO_TEST_CASE(balance)

15
test/SolidityNameAndTypeResolution.cpp

@ -638,6 +638,7 @@ BOOST_AUTO_TEST_CASE(state_variable_accessors)
" }\n" " }\n"
"uint256 foo;\n" "uint256 foo;\n"
"mapping(uint=>string4) map;\n" "mapping(uint=>string4) map;\n"
"mapping(uint=>mapping(uint=>string4)) multiple_map;\n"
"}\n"; "}\n";
ASTPointer<SourceUnit> source; ASTPointer<SourceUnit> source;
@ -649,10 +650,20 @@ BOOST_AUTO_TEST_CASE(state_variable_accessors)
auto returnParams = function->getReturnParameterTypeNames(); auto returnParams = function->getReturnParameterTypeNames();
BOOST_CHECK_EQUAL(returnParams.at(0), "uint256"); BOOST_CHECK_EQUAL(returnParams.at(0), "uint256");
BOOST_CHECK(function->isConstant()); BOOST_CHECK(function->isConstant());
function = retrieveFunctionBySignature(contract, "map(uint256)"); function = retrieveFunctionBySignature(contract, "map(uint256)");
BOOST_REQUIRE(function && function->hasDeclaration()); BOOST_REQUIRE(function && function->hasDeclaration());
auto Params = function->getParameterTypeNames(); auto params = function->getParameterTypeNames();
BOOST_CHECK_EQUAL(returnParams.at(0), "uint256"); BOOST_CHECK_EQUAL(params.at(0), "uint256");
returnParams = function->getReturnParameterTypeNames();
BOOST_CHECK_EQUAL(returnParams.at(0), "string4");
BOOST_CHECK(function->isConstant());
function = retrieveFunctionBySignature(contract, "multiple_map(uint256,uint256)");
BOOST_REQUIRE(function && function->hasDeclaration());
params = function->getParameterTypeNames();
BOOST_CHECK_EQUAL(params.at(0), "uint256");
BOOST_CHECK_EQUAL(params.at(1), "uint256");
returnParams = function->getReturnParameterTypeNames(); returnParams = function->getReturnParameterTypeNames();
BOOST_CHECK_EQUAL(returnParams.at(0), "string4"); BOOST_CHECK_EQUAL(returnParams.at(0), "string4");
BOOST_CHECK(function->isConstant()); BOOST_CHECK(function->isConstant());

Loading…
Cancel
Save