diff options
author | liana <liana@ethdev.com> | 2015-01-24 00:36:12 +0800 |
---|---|---|
committer | liana <liana@ethdev.com> | 2015-01-24 00:45:37 +0800 |
commit | 5de93e6acb81b9a39c1e8f1772dde81d5131e7e3 (patch) | |
tree | aec395a0f6011b1216c0ccc2f2a91e2e5d4bbc33 | |
parent | 376c6182ad813384af43bdf198c4afd596699750 (diff) | |
download | dexon-solidity-5de93e6acb81b9a39c1e8f1772dde81d5131e7e3.tar dexon-solidity-5de93e6acb81b9a39c1e8f1772dde81d5131e7e3.tar.gz dexon-solidity-5de93e6acb81b9a39c1e8f1772dde81d5131e7e3.tar.bz2 dexon-solidity-5de93e6acb81b9a39c1e8f1772dde81d5131e7e3.tar.lz dexon-solidity-5de93e6acb81b9a39c1e8f1772dde81d5131e7e3.tar.xz dexon-solidity-5de93e6acb81b9a39c1e8f1772dde81d5131e7e3.tar.zst dexon-solidity-5de93e6acb81b9a39c1e8f1772dde81d5131e7e3.zip |
- added conversion for string/hash of equal sizes
- added tests
-rw-r--r-- | ExpressionCompiler.cpp | 30 | ||||
-rw-r--r-- | Types.cpp | 16 | ||||
-rw-r--r-- | Types.h | 3 |
3 files changed, 46 insertions, 3 deletions
diff --git a/ExpressionCompiler.cpp b/ExpressionCompiler.cpp index 60c5c4de..66ca2ec1 100644 --- a/ExpressionCompiler.cpp +++ b/ExpressionCompiler.cpp @@ -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 } @@ -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()) @@ -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; } |