Some cleanup.

This commit is contained in:
chriseth 2016-05-10 12:42:38 +02:00
parent 22318c0c1a
commit ef7049f9a6
2 changed files with 32 additions and 60 deletions

View File

@ -191,7 +191,7 @@ TypePointer Type::forLiteral(Literal const& _literal)
case Token::StringLiteral: case Token::StringLiteral:
return make_shared<StringLiteralType>(_literal); return make_shared<StringLiteralType>(_literal);
default: default:
return shared_ptr<Type>(); return TypePointer();
} }
} }
@ -471,12 +471,11 @@ tuple<bool, rational> RationalNumberType::isValidLiteral(Literal const& _literal
) )
throw; throw;
//Only decimal notation allowed here, leading zeros would switch to octal. //Only decimal notation allowed here, leading zeros would switch to octal.
auto leadingZeroes = find_if_not( auto fractionalBegin = find_if_not(
radixPoint + 1, radixPoint + 1,
_literal.value().end(), _literal.value().end(),
[](char const& a) { return a == '0'; } [](char const& a) { return a == '0'; }
); );
auto fractionalBegin = leadingZeroes;
denominator = bigint(string(fractionalBegin, _literal.value().end())); denominator = bigint(string(fractionalBegin, _literal.value().end()));
denominator /= boost::multiprecision::pow( denominator /= boost::multiprecision::pow(
@ -550,13 +549,12 @@ bool RationalNumberType::isImplicitlyConvertibleTo(Type const& _convertTo) const
} }
else if (_convertTo.category() == Category::FixedPoint) else if (_convertTo.category() == Category::FixedPoint)
{ {
//call fixed point type...call fractional bits...shift our number by the number of fractional bits...
//...see if it's a whole number. Make helper function for whether or not finitely representable.
if (auto fixed = fixedPointType()) if (auto fixed = fixedPointType())
{ {
// We disallow implicit conversion if we would have to truncate (fixedPointType()
// can return a type that requires truncation).
rational value = m_value * boost::multiprecision::pow(bigint(2), fixed->fractionalBits()); rational value = m_value * boost::multiprecision::pow(bigint(2), fixed->fractionalBits());
if (value.denominator() == 1 && fixed->isImplicitlyConvertibleTo(_convertTo)) return value.denominator() == 1 && fixed->isImplicitlyConvertibleTo(_convertTo);
return true;
} }
return false; return false;
} }
@ -573,13 +571,8 @@ bool RationalNumberType::isImplicitlyConvertibleTo(Type const& _convertTo) const
bool RationalNumberType::isExplicitlyConvertibleTo(Type const& _convertTo) const bool RationalNumberType::isExplicitlyConvertibleTo(Type const& _convertTo) const
{ {
if (m_value.denominator() == 1) TypePointer mobType = mobileType();
{ return mobType && mobType->isExplicitlyConvertibleTo(_convertTo);
TypePointer intType = integerType();
return intType && intType->isExplicitlyConvertibleTo(_convertTo);
}
TypePointer fixType = fixedPointType();
return fixType && fixType->isExplicitlyConvertibleTo(_convertTo);
} }
TypePointer RationalNumberType::unaryOperatorResult(Token::Value _operator) const TypePointer RationalNumberType::unaryOperatorResult(Token::Value _operator) const
@ -608,19 +601,12 @@ TypePointer RationalNumberType::unaryOperatorResult(Token::Value _operator) cons
TypePointer RationalNumberType::binaryOperatorResult(Token::Value _operator, TypePointer const& _other) const TypePointer RationalNumberType::binaryOperatorResult(Token::Value _operator, TypePointer const& _other) const
{ {
if (_other->category() == Category::Integer) if (_other->category() == Category::Integer || _other->category() == Category::FixedPoint)
{ {
shared_ptr<IntegerType const> intType = integerType(); auto mobile = mobileType();
if (!intType) if (!mobile)
return TypePointer(); return TypePointer();
return intType->binaryOperatorResult(_operator, _other); return mobile->binaryOperatorResult(_operator, _other);
}
else if (_other->category() == Category::FixedPoint)
{
shared_ptr<FixedPointType const> fixType = fixedPointType();
if (!fixType)
return TypePointer();
return fixType->binaryOperatorResult(_operator, _other);
} }
else if (_other->category() != category()) else if (_other->category() != category())
return TypePointer(); return TypePointer();
@ -628,22 +614,14 @@ TypePointer RationalNumberType::binaryOperatorResult(Token::Value _operator, Typ
RationalNumberType const& other = dynamic_cast<RationalNumberType const&>(*_other); RationalNumberType const& other = dynamic_cast<RationalNumberType const&>(*_other);
if (Token::isCompareOp(_operator)) if (Token::isCompareOp(_operator))
{ {
if (m_value.denominator() == 1) // Since we do not have a "BoolConstantType", we have to do the acutal comparison
{ // at runtime and convert to mobile typse first. Such a comparison is not a very common
shared_ptr<IntegerType const> thisIntegerType = integerType(); // use-case and will be optimized away.
shared_ptr<IntegerType const> otherIntegerType = other.integerType(); TypePointer thisMobile = mobileType();
if (!thisIntegerType || !otherIntegerType) TypePointer otherMobile = other.mobileType();
if (!thisMobile || !otherMobile)
return TypePointer(); return TypePointer();
return thisIntegerType->binaryOperatorResult(_operator, otherIntegerType); return thisMobile->binaryOperatorResult(_operator, otherMobile);
}
else
{
shared_ptr<FixedPointType const> thisFixedPointType = fixedPointType();
shared_ptr<FixedPointType const> otherFixedPointType = other.fixedPointType();
if (!thisFixedPointType || !otherFixedPointType)
return TypePointer();
return thisFixedPointType->binaryOperatorResult(_operator, otherFixedPointType);
}
} }
else else
{ {
@ -695,25 +673,19 @@ TypePointer RationalNumberType::binaryOperatorResult(Token::Value _operator, Typ
break; break;
case Token::Exp: case Token::Exp:
{ {
bigint newDenominator; using boost::multiprecision::pow;
bigint newNumerator;
if (other.m_value.denominator() != 1) if (other.m_value.denominator() != 1)
return TypePointer(); return TypePointer();
else if (abs(other.m_value) > numeric_limits<unsigned>::max()) else if (abs(other.m_value) > numeric_limits<uint32_t>::max())
return TypePointer(); return TypePointer(); // This will need too much memory to represent.
else if (other.m_value < 0) //apply inverse uint32_t exponent = abs(other.m_value).numerator().convert_to<uint32_t>();
{ bigint numerator = pow(m_value.numerator(), exponent);
rational absoluteValue = abs(other.m_value); bigint denominator = pow(m_value.denominator(), exponent);
newDenominator = boost::multiprecision::pow(m_value.numerator(), absoluteValue.numerator().convert_to<unsigned>()); if (other.m_value >= 0)
newNumerator = boost::multiprecision::pow(m_value.denominator(), absoluteValue.numerator().convert_to<unsigned>()); value = rational(numerator, denominator);
value = rational(newNumerator, newDenominator);
}
else else
{ // invert
newNumerator = boost::multiprecision::pow(m_value.numerator(), other.m_value.numerator().convert_to<unsigned>()); value = rational(denominator, numerator);
newDenominator = boost::multiprecision::pow(m_value.denominator(), other.m_value.numerator().convert_to<unsigned>());
value = rational(newNumerator, newDenominator);
}
break; break;
} }
default: default:

View File

@ -365,7 +365,7 @@ public:
/// @returns true if the literal is a valid integer. /// @returns true if the literal is a valid integer.
static std::tuple<bool, rational> isValidLiteral(Literal const& _literal); static std::tuple<bool, rational> isValidLiteral(Literal const& _literal);
explicit RationalNumberType(rational _value): explicit RationalNumberType(rational const& _value):
m_value(_value) m_value(_value)
{} {}
virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override; virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override;