Browse Source

Merge pull request #2689 from chriseth/stringsAsMappingKeys

strings as mapping keys.
cl-refactor
chriseth 10 years ago
parent
commit
9a95078b97
  1. 3
      libsolidity/AST.cpp
  2. 27
      libsolidity/ExpressionCompiler.cpp
  3. 2
      libsolidity/Types.cpp
  4. 33
      test/libsolidity/SolidityEndToEndTest.cpp

3
libsolidity/AST.cpp

@ -784,8 +784,7 @@ void Expression::expectType(Type const& _expectedType)
" is not implicitly convertible to expected type " +
_expectedType.toString() +
"."
)
);
));
}
void Expression::requireLValue()

27
libsolidity/ExpressionCompiler.cpp

@ -85,6 +85,10 @@ void ExpressionCompiler::appendStateVariableAccessor(VariableDeclaration const&
if (auto mappingType = dynamic_cast<MappingType const*>(returnType.get()))
{
solAssert(CompilerUtils::freeMemoryPointer >= 0x40, "");
solAssert(
!paramTypes[i]->isDynamicallySized(),
"Accessors for mapping with dynamically-sized keys not yet implemented."
);
// pop offset
m_context << eth::Instruction::POP;
// move storage offset to memory.
@ -803,15 +807,30 @@ bool ExpressionCompiler::visit(IndexAccess const& _indexAccess)
if (baseType.getCategory() == Type::Category::Mapping)
{
// stack: storage_base_ref
Type const& keyType = *dynamic_cast<MappingType const&>(baseType).getKeyType();
m_context << u256(0); // memory position
auto const& mapping = dynamic_cast<MappingType const&>(baseType);
Type const& keyType = *mapping.getKeyType();
solAssert(_indexAccess.getIndexExpression(), "Index expression expected.");
solAssert(keyType.getCalldataEncodedSize() <= 0x20, "Dynamic keys not yet implemented.");
if (keyType.isDynamicallySized())
{
_indexAccess.getIndexExpression()->accept(*this);
utils().fetchFreeMemoryPointer();
// stack: base index mem
// note: the following operations must not allocate memory!
utils().encodeToMemory(TypePointers{mapping.getKeyType()}, TypePointers(), false, true);
m_context << eth::Instruction::SWAP1;
utils().storeInMemoryDynamic(IntegerType(256));
utils().toSizeAfterFreeMemoryPointer();
}
else
{
m_context << u256(0); // memory position
appendExpressionCopyToMemory(keyType, *_indexAccess.getIndexExpression());
m_context << eth::Instruction::SWAP1;
solAssert(CompilerUtils::freeMemoryPointer >= 0x40, "");
utils().storeInMemoryDynamic(IntegerType(256));
m_context << u256(0) << eth::Instruction::SHA3;
m_context << u256(0);
}
m_context << eth::Instruction::SHA3;
m_context << u256(0);
setLValueToStorageItem(_indexAccess);
}

2
libsolidity/Types.cpp

@ -179,6 +179,8 @@ TypePointer Type::fromMapping(ElementaryTypeName& _keyType, TypeName& _valueType
BOOST_THROW_EXCEPTION(_valueType.createTypeError("Invalid type name."));
// Convert value type to storage reference.
valueType = ReferenceType::copyForLocationIfReference(DataLocation::Storage, valueType);
// Convert key type to memory.
keyType = ReferenceType::copyForLocationIfReference(DataLocation::Memory, keyType);
return make_shared<MappingType>(keyType, valueType);
}

33
test/libsolidity/SolidityEndToEndTest.cpp

@ -5099,6 +5099,39 @@ BOOST_AUTO_TEST_CASE(memory_structs_with_mappings)
BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0)));
}
BOOST_AUTO_TEST_CASE(string_as_mapping_key)
{
char const* sourceCode = R"(
contract Test {
mapping(string => uint) data;
function set(string _s, uint _v) { data[_s] = _v; }
function get(string _s) returns (uint) { return data[_s]; }
}
)";
compileAndRun(sourceCode, 0, "Test");
vector<string> strings{
"Hello, World!",
"Hello, World!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1111",
"",
"1"
};
for (unsigned i = 0; i < strings.size(); i++)
BOOST_CHECK(callContractFunction(
"set(string,uint256)",
u256(0x40),
u256(7 + i),
u256(strings[i].size()),
strings[i]
) == encodeArgs());
for (unsigned i = 0; i < strings.size(); i++)
BOOST_CHECK(callContractFunction(
"get(string)",
u256(0x20),
u256(strings[i].size()),
strings[i]
) == encodeArgs(u256(7 + i)));
}
BOOST_AUTO_TEST_SUITE_END()
}

Loading…
Cancel
Save