aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchriseth <c@ethdev.com>2015-01-27 20:53:13 +0800
committerchriseth <c@ethdev.com>2015-01-27 20:53:13 +0800
commit18fc2ed2d6a58b0064f6c1d2430ffe988f68b7ca (patch)
treed83c226c64315d5994190b61fc93c0a74fbd809d
parent8dbdaa79e37619fc79b7111b12d5385f140fd1a1 (diff)
parentcad3d87482464017870080c54e3392bc5503ab20 (diff)
downloaddexon-solidity-18fc2ed2d6a58b0064f6c1d2430ffe988f68b7ca.tar
dexon-solidity-18fc2ed2d6a58b0064f6c1d2430ffe988f68b7ca.tar.gz
dexon-solidity-18fc2ed2d6a58b0064f6c1d2430ffe988f68b7ca.tar.bz2
dexon-solidity-18fc2ed2d6a58b0064f6c1d2430ffe988f68b7ca.tar.lz
dexon-solidity-18fc2ed2d6a58b0064f6c1d2430ffe988f68b7ca.tar.xz
dexon-solidity-18fc2ed2d6a58b0064f6c1d2430ffe988f68b7ca.tar.zst
dexon-solidity-18fc2ed2d6a58b0064f6c1d2430ffe988f68b7ca.zip
Merge pull request #857 from LianaHus/StringToHash
conversion for string to/from hash
-rw-r--r--ExpressionCompiler.cpp75
-rw-r--r--Types.cpp16
-rw-r--r--Types.h3
3 files changed, 69 insertions, 25 deletions
diff --git a/ExpressionCompiler.cpp b/ExpressionCompiler.cpp
index 60c5c4de..bd8c8653 100644
--- a/ExpressionCompiler.cpp
+++ b/ExpressionCompiler.cpp
@@ -628,38 +628,65 @@ 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 ||
- stackTypeCategory == Type::Category::INTEGER_CONSTANT)
+
+ if (stackTypeCategory == Type::Category::STRING)
{
- solAssert(targetTypeCategory == Type::Category::INTEGER || targetTypeCategory == Type::Category::CONTRACT, "");
- IntegerType addressType(0, IntegerType::Modifier::ADDRESS);
- IntegerType const& targetType = targetTypeCategory == Type::Category::INTEGER
- ? dynamic_cast<IntegerType const&>(_targetType) : addressType;
- if (stackTypeCategory == Type::Category::INTEGER_CONSTANT)
+ if (targetTypeCategory == Type::Category::INTEGER)
{
- IntegerConstantType const& constType = dynamic_cast<IntegerConstantType const&>(_typeOnStack);
- // We know that the stack is clean, we only have to clean for a narrowing conversion
- // where cleanup is forced.
- if (targetType.getNumBits() < constType.getIntegerType()->getNumBits() && _cleanupNeeded)
- appendHighBitsCleanup(targetType);
+ // 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& typeOnStack = dynamic_cast<StaticStringType const&>(_typeOnStack);
+ solAssert(targetIntegerType.isHash(), "Only conversion between String and Hash is allowed.");
+ solAssert(targetIntegerType.getNumBits() == typeOnStack.getNumBytes() * 8, "The size should be the same.");
+ m_context << (u256(1) << (256 - typeOnStack.getNumBytes() * 8)) << eth::Instruction::SWAP1 << eth::Instruction::DIV;
}
else
{
- IntegerType const& typeOnStack = stackTypeCategory == Type::Category::INTEGER
- ? dynamic_cast<IntegerType const&>(_typeOnStack) : addressType;
- // Widening: clean up according to source type width
- // Non-widening and force: clean up according to target type bits
- if (targetType.getNumBits() > typeOnStack.getNumBits())
- appendHighBitsCleanup(typeOnStack);
- else if (_cleanupNeeded)
- appendHighBitsCleanup(targetType);
+ solAssert(targetTypeCategory == Type::Category::STRING, "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
}
}
- else if (stackTypeCategory == Type::Category::STRING)
+ else if (stackTypeCategory == Type::Category::INTEGER || stackTypeCategory == Type::Category::CONTRACT ||
+ stackTypeCategory == Type::Category::INTEGER_CONSTANT)
{
- solAssert(targetTypeCategory == Type::Category::STRING, "");
- // nothing to do, strings are high-order-bit-aligned
- //@todo clear lower-order bytes if we allow explicit conversion to shorter strings
+ 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& typeOnStack = dynamic_cast<IntegerType const&>(_typeOnStack);
+ solAssert(typeOnStack.isHash(), "Only conversion between String and Hash is allowed.");
+ solAssert(typeOnStack.getNumBits() == targetStringType.getNumBytes() * 8, "The size should be the same.");
+ m_context << (u256(1) << (256 - typeOnStack.getNumBits())) << eth::Instruction::MUL;
+ }
+ else
+ {
+ solAssert(targetTypeCategory == Type::Category::INTEGER || targetTypeCategory == Type::Category::CONTRACT, "");
+ IntegerType addressType(0, IntegerType::Modifier::ADDRESS);
+ IntegerType const& targetType = targetTypeCategory == Type::Category::INTEGER
+ ? dynamic_cast<IntegerType const&>(_targetType) : addressType;
+ if (stackTypeCategory == Type::Category::INTEGER_CONSTANT)
+ {
+ IntegerConstantType const& constType = dynamic_cast<IntegerConstantType const&>(_typeOnStack);
+ // We know that the stack is clean, we only have to clean for a narrowing conversion
+ // where cleanup is forced.
+ if (targetType.getNumBits() < constType.getIntegerType()->getNumBits() && _cleanupNeeded)
+ appendHighBitsCleanup(targetType);
+ }
+ else
+ {
+ IntegerType const& typeOnStack = stackTypeCategory == Type::Category::INTEGER
+ ? dynamic_cast<IntegerType const&>(_typeOnStack) : addressType;
+ // Widening: clean up according to source type width
+ // Non-widening and force: clean up according to target type bits
+ if (targetType.getNumBits() > typeOnStack.getNumBits())
+ appendHighBitsCleanup(typeOnStack);
+ else if (_cleanupNeeded)
+ appendHighBitsCleanup(targetType);
+ }
+ }
}
else if (_typeOnStack != _targetType)
// All other types should not be convertible to non-equal types.
diff --git a/Types.cpp b/Types.cpp
index c75cecfa..dad3a145 100644
--- a/Types.cpp
+++ b/Types.cpp
@@ -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())
diff --git a/Types.h b/Types.h
index 935c39eb..83436efa 100644
--- a/Types.h
+++ b/Types.h
@@ -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; }