diff options
Diffstat (limited to 'libsolidity')
-rw-r--r-- | libsolidity/ast/Types.cpp | 124 | ||||
-rw-r--r-- | libsolidity/ast/Types.h | 5 | ||||
-rw-r--r-- | libsolidity/codegen/LValue.cpp | 1 |
3 files changed, 69 insertions, 61 deletions
diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 8c0d21b1..343a7ea7 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -362,7 +362,6 @@ MemberList::MemberMap IntegerType::nativeMembers(ContractDefinition const*) cons FixedPointType::FixedPointType(int _integerBits, int _fractionalBits, FixedPointType::Modifier _modifier): m_integerBits(_integerBits), m_fractionalBits(_fractionalBits), m_modifier(_modifier) { - cout << "FIXED POINT CONSTRUCTOR: " << _integerBits << "x" << _fractionalBits << endl; solAssert( m_integerBits + m_fractionalBits > 0 && m_integerBits + m_fractionalBits <= 256 && @@ -573,14 +572,6 @@ bool RationalNumberType::isImplicitlyConvertibleTo(Type const& _convertTo) const } else if (_convertTo.category() == Category::FixedPoint) { - cout << "IMPLICIT CONVERSION" << endl; - if (fixedPointType() && fixedPointType()->isImplicitlyConvertibleTo(_convertTo)) - return true; - - return false; - } - else if (_convertTo.category() == Category::FixedPoint) - { if (fixedPointType() && fixedPointType()->isImplicitlyConvertibleTo(_convertTo)) return true; return false; @@ -588,7 +579,10 @@ bool RationalNumberType::isImplicitlyConvertibleTo(Type const& _convertTo) const else if (_convertTo.category() == Category::FixedBytes) { FixedBytesType const& fixedBytes = dynamic_cast<FixedBytesType const&>(_convertTo); - return fixedBytes.numBytes() * 8 >= integerType()->numBits(); + if (m_value.denominator() == 1) + return fixedBytes.numBytes() * 8 >= integerType()->numBits(); + else + return fixedBytes.numBytes() * 8 >= fixedPointType()->numBits(); } return false; } @@ -600,7 +594,6 @@ bool RationalNumberType::isExplicitlyConvertibleTo(Type const& _convertTo) const TypePointer intType = integerType(); return intType && intType->isExplicitlyConvertibleTo(_convertTo); } - cout << "EXPLICIT CONVERSION" << endl; TypePointer fixType = fixedPointType(); return fixType && fixType->isExplicitlyConvertibleTo(_convertTo); } @@ -612,7 +605,7 @@ TypePointer RationalNumberType::unaryOperatorResult(Token::Value _operator) cons { case Token::BitNot: if(m_value.denominator() != 1) - BOOST_THROW_EXCEPTION(Error(Error::Type::TypeError) << errinfo_comment("Cannot perform bit operations on non integer fixed type.")); + return TypePointer(); value = ~m_value.numerator(); break; case Token::Add: @@ -640,7 +633,6 @@ TypePointer RationalNumberType::binaryOperatorResult(Token::Value _operator, Typ } else if (_other->category() == Category::FixedPoint) { - cout << "BINARY OPERATOR RESULTS" << endl; shared_ptr<FixedPointType const> fixType = fixedPointType(); if (!fixType) return TypePointer(); @@ -662,7 +654,6 @@ TypePointer RationalNumberType::binaryOperatorResult(Token::Value _operator, Typ } else { - cout << "BINARY OPERATOR RESULTS PART 2" << endl; shared_ptr<FixedPointType const> thisFixedPointType = fixedPointType(); shared_ptr<FixedPointType const> otherFixedPointType = other.fixedPointType(); if (!thisFixedPointType || !otherFixedPointType) @@ -673,23 +664,23 @@ TypePointer RationalNumberType::binaryOperatorResult(Token::Value _operator, Typ else { rational value; - bool fixedPointType = (m_value.denominator() != 1 || other.m_value.denominator() != 1); + bool fractional = (m_value.denominator() != 1 || other.m_value.denominator() != 1); switch (_operator) { //bit operations will only be enabled for integers and fixed types that resemble integers case Token::BitOr: - if (fixedPointType) - BOOST_THROW_EXCEPTION(Error(Error::Type::TypeError) << errinfo_comment("Cannot perform bit operations on non integer fixed type.")); + if (fractional) + return TypePointer(); value = m_value.numerator() | other.m_value.numerator(); break; case Token::BitXor: - if (fixedPointType) - BOOST_THROW_EXCEPTION(Error(Error::Type::TypeError) << errinfo_comment("Cannot perform bit operations on non integer fixed type.")); + if (fractional) + return TypePointer(); value = m_value.numerator() ^ other.m_value.numerator(); break; case Token::BitAnd: - if (fixedPointType) - BOOST_THROW_EXCEPTION(Error(Error::Type::TypeError) << errinfo_comment("Cannot perform bit operations on non integer fixed type.")); + if (fractional) + return TypePointer(); value = m_value.numerator() & other.m_value.numerator(); break; case Token::Add: @@ -700,7 +691,7 @@ TypePointer RationalNumberType::binaryOperatorResult(Token::Value _operator, Typ break; case Token::Mul: value = m_value * other.m_value; - break; + break; case Token::Div: if (other.m_value == 0) return TypePointer(); @@ -710,19 +701,22 @@ TypePointer RationalNumberType::binaryOperatorResult(Token::Value _operator, Typ case Token::Mod: if (other.m_value == 0) return TypePointer(); - else if (fixedPointType) + else if (fractional) { value = m_value; - rational divisor = m_value / other.m_value; - value -= divisor * m_value; - cout << "MODULO VALUE: " << value << endl; + if (value > other.m_value) + { + do + { + value -= other.m_value; + } while (value > other.m_value); + } } else value = m_value.numerator() % other.m_value.numerator(); break; case Token::Exp: { - cout << "Is this the source of the problem" << endl; bigint newDenominator; bigint newNumerator; if (other.m_value.denominator() != 1) @@ -769,14 +763,17 @@ string RationalNumberType::toString(bool) const u256 RationalNumberType::literalValue(Literal const*) const { u256 value; + unsigned uselessBits = 0; + bigint shiftedValue; + tie(shiftedValue, uselessBits) = findFractionNumberAndBits(); // we ignore the literal and hope that the type was correctly determined - - solAssert(m_value >= -(bigint(1) << 255), "Number constant too small."); + solAssert(shiftedValue <= u256(-1), "Integer constant too large."); + solAssert(shiftedValue >= -(bigint(1) << 255), "Number constant too small."); if (m_value >= 0) - value = u256(m_value.numerator()); + value = u256(shiftedValue); else - value = s2u(s256(m_value.numerator())); + value = s2u(s256(0 - shiftedValue)); return value; } @@ -794,6 +791,7 @@ TypePointer RationalNumberType::mobileType() const return fixType; } +//TODO: combine integerType() and fixedPointType() into one function shared_ptr<IntegerType const> RationalNumberType::integerType() const { bigint value = wholeNumbers(); @@ -813,52 +811,62 @@ shared_ptr<FixedPointType const> RationalNumberType::fixedPointType() const { //do calculations up here bigint integers = wholeNumbers(); - //bigint _remainder = abs(m_value.numerator() % m_value.denominator()); + bigint shiftedValue; + unsigned integerBits = 0; + unsigned fractionalBits = 0; bool fractionalSignBit = integers == 0; //sign the fractional side or the integer side bool negative = (m_value < 0); - //todo: change name - bigint fractionalBits = findFractionNumberAndBits(); - cout << "Total int: " << fractionalBits.str() << endl; + if (negative && !fractionalSignBit) // convert to positive number of same bit requirements { integers = ((0 - integers) - 1) << 1; - fractionalBits = ((0 - fractionalBits) - 1) << 1; + integerBits = max(bytesRequired(integers), 1u) * 8; + tie(shiftedValue, fractionalBits) = findFractionNumberAndBits(integerBits); } else if (negative && fractionalSignBit) - fractionalBits = ((0 - fractionalBits) - 1) << 1; - - if (fractionalBits > u256(-1)) - return shared_ptr<FixedPointType const>(); + tie(shiftedValue, fractionalBits) = findFractionNumberAndBits(); else { - cout << "m_value: " << m_value << endl; - cout << "Total int: " << fractionalBits.str() << endl; - unsigned fractionalBytesRequired = bytesRequired(fractionalBits) * 8; - unsigned integerBytesRequired = bytesRequired(integers) * 8; - cout << "Fractional Bytes Required: " << fractionalBytesRequired << endl; - cout << "Integer Bytes Required: " << integerBytesRequired << endl << endl; + if (!fractionalSignBit) + integerBits = max(bytesRequired(integers), 1u) * 8; + tie(shiftedValue, fractionalBits) = findFractionNumberAndBits(integerBits); + if (shiftedValue == 0 && fractionalSignBit) + { + integerBits = 8; + fractionalBits = 8; + } + } + + if (shiftedValue > u256(-1) || integers > u256(-1)) + return shared_ptr<FixedPointType const>(); + else return make_shared<FixedPointType>( - integerBytesRequired, fractionalBytesRequired, + integerBits, fractionalBits, negative ? FixedPointType::Modifier::Signed : FixedPointType::Modifier::Unsigned ); - } } //todo: change name of function -tuple<bigint, unsigned> RationalNumberType::findFractionNumberAndBits(bool getWholeNumber) const +tuple<bigint, unsigned> RationalNumberType::findFractionNumberAndBits(unsigned const restrictedBits) const { - rational value; - if (getWholeNumber) - value = m_value; - else - value = m_value - wholeNumbers(); - for (unsigned fractionalBits = 0; value < boost::multiprecision::pow(bigint(2), 256); fractionalBits += 8, value *= 10) + bool isNegative = m_value < 0; + rational value = abs(m_value); + unsigned fractionalBits = 0; + for (; fractionalBits <= 256 - restrictedBits; fractionalBits += 8, value *= 256) { if (value.denominator() == 1) return make_tuple(value.numerator(), fractionalBits); - } - cout << "too big :(" << endl; - return make_tuple(value.numerator()/value.denominator(), fractionalBits); + bigint predictionValue = 256 * (value.numerator() / value.denominator()); + if (predictionValue > u256(-1)) + return make_tuple(value.numerator()/value.denominator(), fractionalBits); + predictionValue = ((0 - predictionValue) - 1) << 1; + if (predictionValue > u256(-1) && isNegative) + // essentially asking if its negative and if so will giving it a sign bit value put it over the limit + // if we also multiply it one more time by 256 + return make_tuple(((0 - value.numerator() / value.denominator()) - 1) << 1, fractionalBits); + + } + return make_tuple(value.numerator()/value.denominator(), 256 - restrictedBits); } diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 84236762..03b6563c 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -385,10 +385,11 @@ public: /// @returns the smallest integer type that can hold the value or an empty pointer if not possible. std::shared_ptr<IntegerType const> integerType() const; - /// @returns the smallest fixed type that can hold the value or an empty pointer + /// @returns the smallest fixed type that can hold the value or incurs the least precision loss. + /// If the integer part does not fit, returns an empty pointer. std::shared_ptr<FixedPointType const> fixedPointType() const; - std::tuple<bigint, unsigned> findFractionNumberAndBits(bool getWholeNumber = false) const; + std::tuple<bigint, unsigned> findFractionNumberAndBits(unsigned const restrictedBits = 0) const; bigint denominator() const { return m_value.denominator(); } bigint wholeNumbers() const { return m_value.numerator() / m_value.denominator(); } diff --git a/libsolidity/codegen/LValue.cpp b/libsolidity/codegen/LValue.cpp index 7d9fa4c8..1d1956aa 100644 --- a/libsolidity/codegen/LValue.cpp +++ b/libsolidity/codegen/LValue.cpp @@ -243,7 +243,6 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc m_context << Instruction::MUL << Instruction::OR; //else if (m_dataType->category() == Type::Category::Fixed) //trying to figure out what this does...going to require some more assistance - m_context << Instruction::MUL << eth::Instruction::OR; // stack: value storage_ref updated_value m_context << Instruction::SWAP1 << Instruction::SSTORE; if (_move) |