Simplify interface of RationalNumber.

This commit is contained in:
chriseth 2016-05-10 14:30:24 +02:00
parent cf226f0607
commit 656405240e
5 changed files with 25 additions and 24 deletions

View File

@ -104,7 +104,7 @@ void ReferencesResolver::endVisit(ArrayTypeName const& _typeName)
if (!length->annotation().type) if (!length->annotation().type)
ConstantEvaluator e(*length); ConstantEvaluator e(*length);
auto const* lengthType = dynamic_cast<RationalNumberType const*>(length->annotation().type.get()); auto const* lengthType = dynamic_cast<RationalNumberType const*>(length->annotation().type.get());
if (!lengthType || lengthType->denominator() != 1) if (!lengthType || lengthType->isFractional())
fatalTypeError(length->location(), "Invalid array length, expected integer literal."); fatalTypeError(length->location(), "Invalid array length, expected integer literal.");
else else
_typeName.annotation().type = make_shared<ArrayType>(DataLocation::Storage, baseType, lengthType->literalValue(nullptr)); _typeName.annotation().type = make_shared<ArrayType>(DataLocation::Storage, baseType, lengthType->literalValue(nullptr));

View File

@ -792,7 +792,7 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement)
{ {
if ( if (
valueComponentType->category() == Type::Category::RationalNumber && valueComponentType->category() == Type::Category::RationalNumber &&
dynamic_cast<RationalNumberType const&>(*valueComponentType).denominator() != 1 && dynamic_cast<RationalNumberType const&>(*valueComponentType).isFractional() &&
valueComponentType->mobileType() valueComponentType->mobileType()
) )
typeError( typeError(
@ -1366,9 +1366,9 @@ bool TypeChecker::visit(IndexAccess const& _access)
expectType(*index, IntegerType(256)); expectType(*index, IntegerType(256));
if (auto numberType = dynamic_cast<RationalNumberType const*>(type(*index).get())) if (auto numberType = dynamic_cast<RationalNumberType const*>(type(*index).get()))
{ {
solAssert(!numberType->denominator() != 1 ,"Invalid type for array access."); if (!numberType->isFractional()) // error is reported above
if (!actualType.isDynamicallySized() && actualType.length() <= numberType->literalValue(nullptr)) if (!actualType.isDynamicallySized() && actualType.length() <= numberType->literalValue(nullptr))
typeError(_access.location(), "Out of bounds array access."); typeError(_access.location(), "Out of bounds array access.");
} }
} }
resultType = actualType.baseType(); resultType = actualType.baseType();
@ -1522,7 +1522,7 @@ void TypeChecker::expectType(Expression const& _expression, Type const& _expecte
{ {
if ( if (
type(_expression)->category() == Type::Category::RationalNumber && type(_expression)->category() == Type::Category::RationalNumber &&
dynamic_pointer_cast<RationalNumberType const>(type(_expression))->denominator() != 1 && dynamic_pointer_cast<RationalNumberType const>(type(_expression))->isFractional() &&
type(_expression)->mobileType() type(_expression)->mobileType()
) )
typeError( typeError(

View File

@ -534,15 +534,15 @@ bool RationalNumberType::isImplicitlyConvertibleTo(Type const& _convertTo) const
auto targetType = dynamic_cast<IntegerType const*>(&_convertTo); auto targetType = dynamic_cast<IntegerType const*>(&_convertTo);
if (m_value == 0) if (m_value == 0)
return true; return true;
if (m_value.denominator() != 1) if (isFractional())
return false; return false;
int forSignBit = (targetType->isSigned() ? 1 : 0); int forSignBit = (targetType->isSigned() ? 1 : 0);
if (m_value > 0) if (m_value > 0)
{ {
if (integerPart() <= (u256(-1) >> (256 - targetType->numBits() + forSignBit))) if (m_value.numerator() <= (u256(-1) >> (256 - targetType->numBits() + forSignBit)))
return true; return true;
} }
else if (targetType->isSigned() && -integerPart() <= (u256(1) << (targetType->numBits() - forSignBit))) else if (targetType->isSigned() && -m_value.numerator() <= (u256(1) << (targetType->numBits() - forSignBit)))
return true; return true;
return false; return false;
} }
@ -560,7 +560,7 @@ bool RationalNumberType::isImplicitlyConvertibleTo(Type const& _convertTo) const
else if (_convertTo.category() == Category::FixedBytes) else if (_convertTo.category() == Category::FixedBytes)
{ {
FixedBytesType const& fixedBytes = dynamic_cast<FixedBytesType const&>(_convertTo); FixedBytesType const& fixedBytes = dynamic_cast<FixedBytesType const&>(_convertTo);
if (m_value.denominator() == 1) if (!isFractional())
return fixedBytes.numBytes() * 8 >= integerType()->numBits(); return fixedBytes.numBytes() * 8 >= integerType()->numBits();
else else
return false; return false;
@ -580,7 +580,7 @@ TypePointer RationalNumberType::unaryOperatorResult(Token::Value _operator) cons
switch (_operator) switch (_operator)
{ {
case Token::BitNot: case Token::BitNot:
if(m_value.denominator() != 1) if (isFractional())
return TypePointer(); return TypePointer();
value = ~m_value.numerator(); value = ~m_value.numerator();
break; break;
@ -625,7 +625,7 @@ TypePointer RationalNumberType::binaryOperatorResult(Token::Value _operator, Typ
else else
{ {
rational value; rational value;
bool fractional = (m_value.denominator() != 1 || other.m_value.denominator() != 1); bool fractional = isFractional() || other.isFractional();
switch (_operator) switch (_operator)
{ {
//bit operations will only be enabled for integers and fixed types that resemble integers //bit operations will only be enabled for integers and fixed types that resemble integers
@ -673,7 +673,7 @@ TypePointer RationalNumberType::binaryOperatorResult(Token::Value _operator, Typ
case Token::Exp: case Token::Exp:
{ {
using boost::multiprecision::pow; using boost::multiprecision::pow;
if (other.m_value.denominator() != 1) if (other.isFractional())
return TypePointer(); return TypePointer();
else if (abs(other.m_value) > numeric_limits<uint32_t>::max()) else if (abs(other.m_value) > numeric_limits<uint32_t>::max())
return TypePointer(); // This will need too much memory to represent. return TypePointer(); // This will need too much memory to represent.
@ -704,7 +704,7 @@ bool RationalNumberType::operator==(Type const& _other) const
string RationalNumberType::toString(bool) const string RationalNumberType::toString(bool) const
{ {
if (m_value.denominator() == 1) if (!isFractional())
return "int_const " + m_value.numerator().str(); return "int_const " + m_value.numerator().str();
return "rational_const " + m_value.numerator().str() + '/' + m_value.denominator().str(); return "rational_const " + m_value.numerator().str() + '/' + m_value.denominator().str();
} }
@ -717,7 +717,7 @@ u256 RationalNumberType::literalValue(Literal const*) const
u256 value; u256 value;
bigint shiftedValue; bigint shiftedValue;
if (m_value.denominator() == 1) if (!isFractional())
shiftedValue = m_value.numerator(); shiftedValue = m_value.numerator();
else else
{ {
@ -741,7 +741,7 @@ u256 RationalNumberType::literalValue(Literal const*) const
TypePointer RationalNumberType::mobileType() const TypePointer RationalNumberType::mobileType() const
{ {
if (m_value.denominator() == 1) if (!isFractional())
return integerType(); return integerType();
else else
return fixedPointType(); return fixedPointType();
@ -749,8 +749,8 @@ TypePointer RationalNumberType::mobileType() const
shared_ptr<IntegerType const> RationalNumberType::integerType() const shared_ptr<IntegerType const> RationalNumberType::integerType() const
{ {
solAssert(m_value.denominator() == 1, "integerType() called for fractional number."); solAssert(!isFractional(), "integerType() called for fractional number.");
bigint value = integerPart(); bigint value = m_value.numerator();
bool negative = (value < 0); bool negative = (value < 0);
if (negative) // convert to positive number of same bit requirements if (negative) // convert to positive number of same bit requirements
value = ((0 - value) - 1) << 1; value = ((0 - value) - 1) << 1;

View File

@ -204,8 +204,9 @@ public:
virtual bool isValueType() const { return false; } virtual bool isValueType() const { return false; }
virtual unsigned sizeOnStack() const { return 1; } virtual unsigned sizeOnStack() const { return 1; }
/// @returns the mobile (in contrast to static) type corresponding to the given type. /// @returns the mobile (in contrast to static) type corresponding to the given type.
/// This returns the corresponding integer type for ConstantTypes and the pointer type /// This returns the corresponding IntegerType or FixedPointType for RationalNumberType
/// for storage reference types. Might return a null pointer if there is no fitting type. /// and the pointer type for storage reference types.
/// Might return a null pointer if there is no fitting type.
virtual TypePointer mobileType() const { return shared_from_this(); } virtual TypePointer mobileType() const { return shared_from_this(); }
/// @returns true if this is a non-value type and the data of this type is stored at the /// @returns true if this is a non-value type and the data of this type is stored at the
/// given location. /// given location.
@ -388,8 +389,8 @@ public:
/// If the integer part does not fit, returns an empty pointer. /// If the integer part does not fit, returns an empty pointer.
std::shared_ptr<FixedPointType const> fixedPointType() const; std::shared_ptr<FixedPointType const> fixedPointType() const;
bigint denominator() const { return m_value.denominator(); } /// @returns true iff the value is not an integer.
bigint integerPart() const { return m_value.numerator() / m_value.denominator(); } bool isFractional() const { return m_value.denominator() != 1; }
private: private:
rational m_value; rational m_value;

View File

@ -431,7 +431,7 @@ bool Why3Translator::visit(BinaryOperation const& _binaryOperation)
if (commonType.category() == Type::Category::RationalNumber) if (commonType.category() == Type::Category::RationalNumber)
{ {
auto const& constantNumber = dynamic_cast<RationalNumberType const&>(commonType); auto const& constantNumber = dynamic_cast<RationalNumberType const&>(commonType);
if (constantNumber.denominator() != bigint(1)) if (constantNumber.isFractional())
error(_binaryOperation, "Fractional numbers not supported."); error(_binaryOperation, "Fractional numbers not supported.");
add("(of_int " + toString(commonType.literalValue(nullptr)) + ")"); add("(of_int " + toString(commonType.literalValue(nullptr)) + ")");
return false; return false;
@ -595,7 +595,7 @@ bool Why3Translator::visit(Literal const& _literal)
case Type::Category::RationalNumber: case Type::Category::RationalNumber:
{ {
auto const& constantNumber = dynamic_cast<RationalNumberType const&>(*type); auto const& constantNumber = dynamic_cast<RationalNumberType const&>(*type);
if (constantNumber.denominator() != 1) if (constantNumber.isFractional())
error(_literal, "Fractional numbers not supported."); error(_literal, "Fractional numbers not supported.");
add("(of_int " + toString(type->literalValue(&_literal)) + ")"); add("(of_int " + toString(type->literalValue(&_literal)) + ")");
break; break;