- added conversion for string/hash of equal sizes

- added tests
This commit is contained in:
liana 2015-01-23 17:36:12 +01:00
parent 376c6182ad
commit 5de93e6acb
3 changed files with 46 additions and 3 deletions

View File

@ -628,7 +628,33 @@ void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type con
return;
Type::Category stackTypeCategory = _typeOnStack.getCategory();
Type::Category targetTypeCategory = _targetType.getCategory();
if (stackTypeCategory == Type::Category::INTEGER || stackTypeCategory == Type::Category::CONTRACT ||
if (stackTypeCategory == Type::Category::STRING && targetTypeCategory == Type::Category::INTEGER)
{
// conversion from string to hash. no need to clean the high bit
// only to shift right because of opposite alignment
IntegerType const& targetIntegerType = dynamic_cast<IntegerType const&>(_targetType);
StaticStringType const& sourceStringType = dynamic_cast<StaticStringType const&>(_typeOnStack);
if (targetIntegerType.isHash())
{
solAssert(targetIntegerType.getNumBits() == sourceStringType.getNumBytes() * 8, "The size should be the same.");
m_context << u256(std::pow(2, 256 - sourceStringType.getNumBytes() * 8)) <<
eth::Instruction::SWAP1 << eth::Instruction::DIV;
}
}
else if (targetTypeCategory == Type::Category::STRING && stackTypeCategory == Type::Category::INTEGER)
{
// conversion from hash to string. no need to clean the high bit
// only to shift left because of opposite alignment
StaticStringType const& targetStringType = dynamic_cast<StaticStringType const&>(_targetType);
IntegerType const& sourceIntegerType = dynamic_cast<IntegerType const&>(_typeOnStack);
if (sourceIntegerType.isHash())
{
solAssert(sourceIntegerType.getNumBits() == targetStringType.getNumBytes() * 8, "The size should be the same.");
m_context << u256(std::pow(2, 256 - sourceIntegerType.getNumBits())) << eth::Instruction::MUL;
}
}
else if (stackTypeCategory == Type::Category::INTEGER || stackTypeCategory == Type::Category::CONTRACT ||
stackTypeCategory == Type::Category::INTEGER_CONSTANT)
{
solAssert(targetTypeCategory == Type::Category::INTEGER || targetTypeCategory == Type::Category::CONTRACT, "");
@ -657,7 +683,7 @@ void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type con
}
else if (stackTypeCategory == Type::Category::STRING)
{
solAssert(targetTypeCategory == Type::Category::STRING, "");
solAssert(targetTypeCategory == Type::Category::STRING || targetTypeCategory == Type::Category::INTEGER, "Invalid type conversion requested.");
// nothing to do, strings are high-order-bit-aligned
//@todo clear lower-order bytes if we allow explicit conversion to shorter strings
}

View File

@ -140,6 +140,11 @@ bool IntegerType::isImplicitlyConvertibleTo(Type const& _convertTo) const
bool IntegerType::isExplicitlyConvertibleTo(Type const& _convertTo) const
{
if (_convertTo.getCategory() == Category::STRING)
{
StaticStringType const& convertTo = dynamic_cast<StaticStringType const&>(_convertTo);
return isHash() && (m_bits == convertTo.getNumBytes() * 8);
}
return _convertTo.getCategory() == getCategory() || _convertTo.getCategory() == Category::CONTRACT;
}
@ -367,6 +372,17 @@ bool StaticStringType::isImplicitlyConvertibleTo(Type const& _convertTo) const
return convertTo.m_bytes >= m_bytes;
}
bool StaticStringType::isExplicitlyConvertibleTo(Type const& _convertTo) const
{
if (_convertTo.getCategory() == Category::INTEGER)
{
IntegerType const& convertTo = dynamic_cast<IntegerType const&>(_convertTo);
if (convertTo.isHash() && (m_bytes * 8 == convertTo.getNumBits()))
return true;
}
return isImplicitlyConvertibleTo(_convertTo);
}
bool StaticStringType::operator==(Type const& _other) const
{
if (_other.getCategory() != getCategory())

View File

@ -233,9 +233,10 @@ public:
/// if no type fits.
static std::shared_ptr<StaticStringType> smallestTypeForLiteral(std::string const& _literal);
StaticStringType(int _bytes);
explicit StaticStringType(int _bytes);
virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override;
virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override;
virtual bool operator==(Type const& _other) const override;
virtual unsigned getCalldataEncodedSize() const override { return m_bytes; }