mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
updated algorithm for bit finding...now to figure out literal value
tiny fixups changed location of the check got rid of extra space and fixed a couple of things added binary results bits change back literal value
This commit is contained in:
parent
5bddb2d6ff
commit
bfc238c8d1
@ -104,10 +104,8 @@ 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)
|
if (!lengthType || lengthType->denominator() != 1)
|
||||||
fatalTypeError(length->location(), "Invalid array length.");
|
fatalTypeError(length->location(), "Invalid array length, expected integer literal.");
|
||||||
else if (lengthType->denominator() != 1)
|
|
||||||
fatalTypeError(length->location(), "Invalid input for array length, expected integer.");
|
|
||||||
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));
|
||||||
}
|
}
|
||||||
|
@ -774,9 +774,10 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement)
|
|||||||
solAssert(!var.typeName(), "");
|
solAssert(!var.typeName(), "");
|
||||||
if (
|
if (
|
||||||
valueComponentType->category() == Type::Category::RationalNumber &&
|
valueComponentType->category() == Type::Category::RationalNumber &&
|
||||||
!dynamic_pointer_cast<RationalNumberType const>(valueComponentType)->integerType()
|
!dynamic_pointer_cast<RationalNumberType const>(valueComponentType)->integerType() &&
|
||||||
|
!dynamic_pointer_cast<RationalNumberType const>(valueComponentType)->fixedPointType()
|
||||||
)
|
)
|
||||||
fatalTypeError(_statement.initialValue()->location(), "Invalid integer constant " + valueComponentType->toString() + ".");
|
fatalTypeError(_statement.initialValue()->location(), "Invalid rational " + valueComponentType->toString() + ".");
|
||||||
var.annotation().type = valueComponentType->mobileType();
|
var.annotation().type = valueComponentType->mobileType();
|
||||||
var.accept(*this);
|
var.accept(*this);
|
||||||
}
|
}
|
||||||
@ -800,8 +801,11 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement)
|
|||||||
void TypeChecker::endVisit(ExpressionStatement const& _statement)
|
void TypeChecker::endVisit(ExpressionStatement const& _statement)
|
||||||
{
|
{
|
||||||
if (type(_statement.expression())->category() == Type::Category::RationalNumber)
|
if (type(_statement.expression())->category() == Type::Category::RationalNumber)
|
||||||
if (!dynamic_pointer_cast<RationalNumberType const>(type(_statement.expression()))->integerType())
|
if (
|
||||||
typeError(_statement.expression().location(), "Invalid integer constant.");
|
!dynamic_pointer_cast<RationalNumberType const>(type(_statement.expression()))->integerType() &&
|
||||||
|
!dynamic_pointer_cast<RationalNumberType const>(type(_statement.expression()))->fixedPointType()
|
||||||
|
)
|
||||||
|
typeError(_statement.expression().location(), "Invalid rational number.");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TypeChecker::visit(Conditional const& _conditional)
|
bool TypeChecker::visit(Conditional const& _conditional)
|
||||||
@ -1107,8 +1111,8 @@ bool TypeChecker::visit(FunctionCall const& _functionCall)
|
|||||||
if (functionType->takesArbitraryParameters())
|
if (functionType->takesArbitraryParameters())
|
||||||
{
|
{
|
||||||
if (auto t = dynamic_cast<RationalNumberType const*>(argType.get()))
|
if (auto t = dynamic_cast<RationalNumberType const*>(argType.get()))
|
||||||
if (!t->integerType())
|
if (!t->integerType() && !t->fixedPointType())
|
||||||
typeError(arguments[i]->location(), "Integer constant too large.");
|
typeError(arguments[i]->location(), "Rational number too large.");
|
||||||
}
|
}
|
||||||
else if (!type(*arguments[i])->isImplicitlyConvertibleTo(*parameterTypes[i]))
|
else if (!type(*arguments[i])->isImplicitlyConvertibleTo(*parameterTypes[i]))
|
||||||
typeError(
|
typeError(
|
||||||
@ -1343,8 +1347,7 @@ 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()))
|
||||||
{
|
{
|
||||||
if (numberType->denominator() != 1)
|
solAssert(!numberType->denominator() != 1 ,"Invalid type for array access.");
|
||||||
typeError(_access.location(), "Invalid type for array access.");
|
|
||||||
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.");
|
||||||
}
|
}
|
||||||
@ -1371,7 +1374,7 @@ bool TypeChecker::visit(IndexAccess const& _access)
|
|||||||
resultType = make_shared<TypeType>(make_shared<ArrayType>(DataLocation::Memory, typeType.actualType()));
|
resultType = make_shared<TypeType>(make_shared<ArrayType>(DataLocation::Memory, typeType.actualType()));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
index->accept(*this);
|
expectType(*index, IntegerType(256));
|
||||||
if (auto length = dynamic_cast<RationalNumberType const*>(type(*index).get()))
|
if (auto length = dynamic_cast<RationalNumberType const*>(type(*index).get()))
|
||||||
resultType = make_shared<TypeType>(make_shared<ArrayType>(
|
resultType = make_shared<TypeType>(make_shared<ArrayType>(
|
||||||
DataLocation::Memory,
|
DataLocation::Memory,
|
||||||
|
@ -181,10 +181,13 @@ TypePointer Type::forLiteral(Literal const& _literal)
|
|||||||
case Token::FalseLiteral:
|
case Token::FalseLiteral:
|
||||||
return make_shared<BoolType>();
|
return make_shared<BoolType>();
|
||||||
case Token::Number:
|
case Token::Number:
|
||||||
if (RationalNumberType::isValidLiteral(_literal))
|
{
|
||||||
return make_shared<RationalNumberType>(_literal);
|
tuple<bool, rational> validLiteral = RationalNumberType::isValidLiteral(_literal);
|
||||||
|
if (get<0>(validLiteral) == true)
|
||||||
|
return make_shared<RationalNumberType>(get<1>(validLiteral));
|
||||||
else
|
else
|
||||||
return TypePointer();
|
return TypePointer();
|
||||||
|
}
|
||||||
case Token::StringLiteral:
|
case Token::StringLiteral:
|
||||||
return make_shared<StringLiteralType>(_literal);
|
return make_shared<StringLiteralType>(_literal);
|
||||||
default:
|
default:
|
||||||
@ -272,7 +275,7 @@ bool IntegerType::isImplicitlyConvertibleTo(Type const& _convertTo) const
|
|||||||
else if (_convertTo.category() == Category::FixedPoint)
|
else if (_convertTo.category() == Category::FixedPoint)
|
||||||
{
|
{
|
||||||
FixedPointType const& convertTo = dynamic_cast<FixedPointType const&>(_convertTo);
|
FixedPointType const& convertTo = dynamic_cast<FixedPointType const&>(_convertTo);
|
||||||
if (convertTo.integerBits() < m_bits)
|
if (convertTo.integerBits() < m_bits || isAddress())
|
||||||
return false;
|
return false;
|
||||||
else if (isSigned())
|
else if (isSigned())
|
||||||
return convertTo.isSigned();
|
return convertTo.isSigned();
|
||||||
@ -440,7 +443,8 @@ string FixedPointType::toString(bool) const
|
|||||||
|
|
||||||
TypePointer FixedPointType::binaryOperatorResult(Token::Value _operator, TypePointer const& _other) const
|
TypePointer FixedPointType::binaryOperatorResult(Token::Value _operator, TypePointer const& _other) const
|
||||||
{
|
{
|
||||||
if (_other->category() != Category::RationalNumber
|
if (
|
||||||
|
_other->category() != Category::RationalNumber
|
||||||
&& _other->category() != category()
|
&& _other->category() != category()
|
||||||
&& _other->category() != Category::Integer
|
&& _other->category() != Category::Integer
|
||||||
)
|
)
|
||||||
@ -453,22 +457,29 @@ TypePointer FixedPointType::binaryOperatorResult(Token::Value _operator, TypePoi
|
|||||||
// All fixed types can be compared
|
// All fixed types can be compared
|
||||||
if (Token::isCompareOp(_operator))
|
if (Token::isCompareOp(_operator))
|
||||||
return commonType;
|
return commonType;
|
||||||
if (Token::isBooleanOp(_operator))
|
if (Token::isBitOp(_operator) || Token::isBooleanOp(_operator))
|
||||||
return TypePointer();
|
return TypePointer();
|
||||||
return commonType;
|
return commonType;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RationalNumberType::isValidLiteral(Literal const& _literal)
|
tuple<bool, rational> RationalNumberType::isValidLiteral(Literal const& _literal)
|
||||||
{
|
{
|
||||||
|
rational x;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
rational numerator;
|
rational numerator;
|
||||||
rational denominator(1);
|
rational denominator(1);
|
||||||
|
|
||||||
auto radixPoint = find(_literal.value().begin(), _literal.value().end(), '.');
|
auto radixPoint = find(_literal.value().begin(), _literal.value().end(), '.');
|
||||||
|
|
||||||
if (radixPoint != _literal.value().end())
|
if (radixPoint != _literal.value().end())
|
||||||
{
|
{
|
||||||
//problem here. If the first digit is a 0 in the string, it won't
|
if (
|
||||||
//turn it into a integer...Using find if not to count the leading 0s.
|
!all_of(radixPoint + 1, _literal.value().end(), ::isdigit) ||
|
||||||
|
!all_of(_literal.value().begin(), radixPoint, ::isdigit)
|
||||||
|
)
|
||||||
|
throw;
|
||||||
|
//Only decimal notation allowed here, leading zeros would switch to octal.
|
||||||
auto leadingZeroes = find_if_not(
|
auto leadingZeroes = find_if_not(
|
||||||
radixPoint + 1,
|
radixPoint + 1,
|
||||||
_literal.value().end(),
|
_literal.value().end(),
|
||||||
@ -476,81 +487,55 @@ bool RationalNumberType::isValidLiteral(Literal const& _literal)
|
|||||||
);
|
);
|
||||||
auto fractionalBegin = leadingZeroes != _literal.value().end() ?
|
auto fractionalBegin = leadingZeroes != _literal.value().end() ?
|
||||||
leadingZeroes : radixPoint + 1;
|
leadingZeroes : radixPoint + 1;
|
||||||
|
|
||||||
denominator = bigint(string(fractionalBegin, _literal.value().end()));
|
denominator = bigint(string(fractionalBegin, _literal.value().end()));
|
||||||
denominator /= boost::multiprecision::pow(
|
denominator /= boost::multiprecision::pow(
|
||||||
bigint(10),
|
bigint(10),
|
||||||
distance(radixPoint + 1, _literal.value().end())
|
distance(radixPoint + 1, _literal.value().end())
|
||||||
);
|
);
|
||||||
numerator = bigint(string(_literal.value().begin(), radixPoint));
|
numerator = bigint(string(_literal.value().begin(), radixPoint));
|
||||||
rational x = numerator + denominator;
|
x = numerator + denominator;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
rational x = bigint(_literal.value());
|
x = bigint(_literal.value());
|
||||||
|
switch (_literal.subDenomination())
|
||||||
|
{
|
||||||
|
case Literal::SubDenomination::None:
|
||||||
|
case Literal::SubDenomination::Wei:
|
||||||
|
case Literal::SubDenomination::Second:
|
||||||
|
break;
|
||||||
|
case Literal::SubDenomination::Szabo:
|
||||||
|
x *= bigint("1000000000000");
|
||||||
|
break;
|
||||||
|
case Literal::SubDenomination::Finney:
|
||||||
|
x *= bigint("1000000000000000");
|
||||||
|
break;
|
||||||
|
case Literal::SubDenomination::Ether:
|
||||||
|
x *= bigint("1000000000000000000");
|
||||||
|
break;
|
||||||
|
case Literal::SubDenomination::Minute:
|
||||||
|
x *= bigint("60");
|
||||||
|
break;
|
||||||
|
case Literal::SubDenomination::Hour:
|
||||||
|
x *= bigint("3600");
|
||||||
|
break;
|
||||||
|
case Literal::SubDenomination::Day:
|
||||||
|
x *= bigint("86400");
|
||||||
|
break;
|
||||||
|
case Literal::SubDenomination::Week:
|
||||||
|
x *= bigint("604800");
|
||||||
|
break;
|
||||||
|
case Literal::SubDenomination::Year:
|
||||||
|
x *= bigint("31536000");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (...)
|
catch (...)
|
||||||
{
|
{
|
||||||
return false;
|
return make_tuple(false, rational(0));
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
RationalNumberType::RationalNumberType(Literal const& _literal)
|
|
||||||
{
|
|
||||||
rational numerator;
|
|
||||||
rational denominator = bigint(1);
|
|
||||||
auto radixPoint = find(_literal.value().begin(), _literal.value().end(), '.');
|
|
||||||
if (radixPoint != _literal.value().end())
|
|
||||||
{
|
|
||||||
auto leadingZeroes = find_if_not(
|
|
||||||
radixPoint + 1,
|
|
||||||
_literal.value().end(),
|
|
||||||
[](char const& a) { return a == '0'; }
|
|
||||||
);
|
|
||||||
auto fractionalBegin = leadingZeroes != _literal.value().end() ?
|
|
||||||
leadingZeroes : radixPoint + 1;
|
|
||||||
//separatly grabbing the numerator, denominator for conversions
|
|
||||||
denominator = bigint(string(fractionalBegin, _literal.value().end()));
|
|
||||||
denominator /= boost::multiprecision::pow(
|
|
||||||
bigint(10),
|
|
||||||
distance(radixPoint + 1, _literal.value().end())
|
|
||||||
);
|
|
||||||
numerator = bigint(string(_literal.value().begin(), radixPoint));
|
|
||||||
m_value = numerator + denominator;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
m_value = bigint(_literal.value());
|
|
||||||
|
|
||||||
switch (_literal.subDenomination())
|
|
||||||
{
|
|
||||||
case Literal::SubDenomination::None:
|
|
||||||
case Literal::SubDenomination::Wei:
|
|
||||||
case Literal::SubDenomination::Second:
|
|
||||||
break;
|
|
||||||
case Literal::SubDenomination::Szabo:
|
|
||||||
m_value *= bigint("1000000000000");
|
|
||||||
break;
|
|
||||||
case Literal::SubDenomination::Finney:
|
|
||||||
m_value *= bigint("1000000000000000");
|
|
||||||
break;
|
|
||||||
case Literal::SubDenomination::Ether:
|
|
||||||
m_value *= bigint("1000000000000000000");
|
|
||||||
break;
|
|
||||||
case Literal::SubDenomination::Minute:
|
|
||||||
m_value *= bigint("60");
|
|
||||||
break;
|
|
||||||
case Literal::SubDenomination::Hour:
|
|
||||||
m_value *= bigint("3600");
|
|
||||||
break;
|
|
||||||
case Literal::SubDenomination::Day:
|
|
||||||
m_value *= bigint("86400");
|
|
||||||
break;
|
|
||||||
case Literal::SubDenomination::Week:
|
|
||||||
m_value *= bigint("604800");
|
|
||||||
break;
|
|
||||||
case Literal::SubDenomination::Year:
|
|
||||||
m_value *= bigint("31536000");
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
return make_tuple(true, x);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RationalNumberType::isImplicitlyConvertibleTo(Type const& _convertTo) const
|
bool RationalNumberType::isImplicitlyConvertibleTo(Type const& _convertTo) const
|
||||||
@ -560,19 +545,20 @@ 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)
|
||||||
|
return false;
|
||||||
int forSignBit = (targetType->isSigned() ? 1 : 0);
|
int forSignBit = (targetType->isSigned() ? 1 : 0);
|
||||||
if (m_value > 0)
|
if (m_value > 0)
|
||||||
{
|
{
|
||||||
if (m_value <= (u256(-1) >> (256 - targetType->numBits() + forSignBit)))
|
if (integerPart() <= (u256(-1) >> (256 - targetType->numBits() + forSignBit)))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (targetType->isSigned() && -m_value <= (u256(1) << (targetType->numBits() - forSignBit)))
|
else if (targetType->isSigned() && -integerPart() <= (u256(1) << (targetType->numBits() - forSignBit)))
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (_convertTo.category() == Category::FixedPoint)
|
else if (_convertTo.category() == Category::FixedPoint)
|
||||||
{
|
{
|
||||||
cout << "hit here?" << endl;
|
|
||||||
if (fixedPointType() && fixedPointType()->isImplicitlyConvertibleTo(_convertTo))
|
if (fixedPointType() && fixedPointType()->isImplicitlyConvertibleTo(_convertTo))
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
@ -583,7 +569,7 @@ bool RationalNumberType::isImplicitlyConvertibleTo(Type const& _convertTo) const
|
|||||||
if (m_value.denominator() == 1)
|
if (m_value.denominator() == 1)
|
||||||
return fixedBytes.numBytes() * 8 >= integerType()->numBits();
|
return fixedBytes.numBytes() * 8 >= integerType()->numBits();
|
||||||
else
|
else
|
||||||
return fixedBytes.numBytes() * 8 >= fixedPointType()->numBits();
|
return false;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -692,7 +678,7 @@ TypePointer RationalNumberType::binaryOperatorResult(Token::Value _operator, Typ
|
|||||||
break;
|
break;
|
||||||
case Token::Mul:
|
case Token::Mul:
|
||||||
value = m_value * other.m_value;
|
value = m_value * other.m_value;
|
||||||
break;
|
break;
|
||||||
case Token::Div:
|
case Token::Div:
|
||||||
if (other.m_value == 0)
|
if (other.m_value == 0)
|
||||||
return TypePointer();
|
return TypePointer();
|
||||||
@ -758,9 +744,7 @@ string RationalNumberType::toString(bool) const
|
|||||||
u256 RationalNumberType::literalValue(Literal const*) const
|
u256 RationalNumberType::literalValue(Literal const*) const
|
||||||
{
|
{
|
||||||
u256 value;
|
u256 value;
|
||||||
unsigned uselessBits = 0;
|
bigint shiftedValue = integerPart();
|
||||||
bigint shiftedValue;
|
|
||||||
tie(shiftedValue, uselessBits) = findFractionNumberAndBits();
|
|
||||||
// we ignore the literal and hope that the type was correctly determined
|
// we ignore the literal and hope that the type was correctly determined
|
||||||
solAssert(shiftedValue <= u256(-1), "Integer constant too large.");
|
solAssert(shiftedValue <= u256(-1), "Integer constant too large.");
|
||||||
solAssert(shiftedValue >= -(bigint(1) << 255), "Number constant too small.");
|
solAssert(shiftedValue >= -(bigint(1) << 255), "Number constant too small.");
|
||||||
@ -768,8 +752,7 @@ u256 RationalNumberType::literalValue(Literal const*) const
|
|||||||
if (m_value >= 0)
|
if (m_value >= 0)
|
||||||
value = u256(shiftedValue);
|
value = u256(shiftedValue);
|
||||||
else
|
else
|
||||||
value = s2u(s256(0 - shiftedValue));
|
value = s2u(s256(shiftedValue));
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -789,7 +772,7 @@ TypePointer RationalNumberType::mobileType() const
|
|||||||
//TODO: combine integerType() and fixedPointType() into one function
|
//TODO: combine integerType() and fixedPointType() into one function
|
||||||
shared_ptr<IntegerType const> RationalNumberType::integerType() const
|
shared_ptr<IntegerType const> RationalNumberType::integerType() const
|
||||||
{
|
{
|
||||||
bigint value = wholeNumbers();
|
bigint value = integerPart();
|
||||||
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;
|
||||||
@ -806,26 +789,34 @@ shared_ptr<FixedPointType const> RationalNumberType::fixedPointType() const
|
|||||||
{
|
{
|
||||||
bool negative = (m_value < 0);
|
bool negative = (m_value < 0);
|
||||||
unsigned fractionalBits = 0;
|
unsigned fractionalBits = 0;
|
||||||
unsigned integerBits = bytesRequired(wholeNumbers()) * 8;
|
unsigned integerBits = 0;
|
||||||
rational value = m_value;
|
rational value = m_value;
|
||||||
bigint l = bigint(1) << 256;
|
bigint transitionValue = bigint(1) << 256;
|
||||||
rational maxValue = rational(l);
|
rational maxValue = rational(transitionValue);
|
||||||
|
|
||||||
if (!negative)
|
if (!negative)
|
||||||
maxValue -= 1;
|
|
||||||
else
|
|
||||||
value = -value;
|
|
||||||
cout << "Max value: " << maxValue << endl;
|
|
||||||
while (value * 0x100 <= maxValue && value.denominator() != 1 && fractionalBits < 256 - integerBits)
|
|
||||||
{
|
{
|
||||||
|
maxValue -= 1;
|
||||||
|
integerBits = bytesRequired(integerPart()) * 8;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
value = abs(value);
|
||||||
|
if (integerPart() > 0)
|
||||||
|
transitionValue = ((0 - integerPart()) - 1) << 1;
|
||||||
|
else
|
||||||
|
transitionValue = 0;
|
||||||
|
integerBits = bytesRequired(transitionValue) * 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (value * 0x100 <= maxValue && value.denominator() != 1 && fractionalBits < 256 - integerBits)
|
||||||
|
{
|
||||||
value *= 0x100;
|
value *= 0x100;
|
||||||
fractionalBits += 8;
|
fractionalBits += 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value > maxValue)
|
if (value > maxValue)
|
||||||
{
|
|
||||||
cout << "value > max value " << endl;
|
|
||||||
return shared_ptr<FixedPointType const>();
|
return shared_ptr<FixedPointType const>();
|
||||||
}
|
|
||||||
bigint v = value.denominator() / value.numerator();
|
bigint v = value.denominator() / value.numerator();
|
||||||
if (negative)
|
if (negative)
|
||||||
v = -v;
|
v = -v;
|
||||||
@ -834,12 +825,7 @@ shared_ptr<FixedPointType const> RationalNumberType::fixedPointType() const
|
|||||||
//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;
|
||||||
if (value > u256(-1))
|
if (value > u256(-1))
|
||||||
{
|
|
||||||
cout << "Too large of a number" << endl;
|
|
||||||
return shared_ptr<FixedPointType const>();
|
return shared_ptr<FixedPointType const>();
|
||||||
}
|
|
||||||
|
|
||||||
cout << "integer bits: " << integerBits << ", fractionalBits: " << fractionalBits << endl;
|
|
||||||
//solAssert(integerBits >= fractionalBits, "Invalid bit requirement calculation.");
|
//solAssert(integerBits >= fractionalBits, "Invalid bit requirement calculation.");
|
||||||
//@todo special handling for integerBits == 0 && fractionalBits == 0?
|
//@todo special handling for integerBits == 0 && fractionalBits == 0?
|
||||||
return make_shared<FixedPointType>(
|
return make_shared<FixedPointType>(
|
||||||
@ -848,31 +834,6 @@ shared_ptr<FixedPointType const> RationalNumberType::fixedPointType() const
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
//todo: change name of function
|
|
||||||
tuple<bigint, unsigned> RationalNumberType::findFractionNumberAndBits(unsigned const restrictedBits) const
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
StringLiteralType::StringLiteralType(Literal const& _literal):
|
StringLiteralType::StringLiteralType(Literal const& _literal):
|
||||||
m_value(_literal.value())
|
m_value(_literal.value())
|
||||||
{
|
{
|
||||||
|
@ -363,9 +363,8 @@ public:
|
|||||||
virtual Category category() const override { return Category::RationalNumber; }
|
virtual Category category() const override { return Category::RationalNumber; }
|
||||||
|
|
||||||
/// @returns true if the literal is a valid integer.
|
/// @returns true if the literal is a valid integer.
|
||||||
static bool isValidLiteral(Literal const& _literal);
|
static std::tuple<bool, rational> isValidLiteral(Literal const& _literal);
|
||||||
|
|
||||||
explicit RationalNumberType(Literal const& _literal);
|
|
||||||
explicit RationalNumberType(rational _value):
|
explicit RationalNumberType(rational _value):
|
||||||
m_value(_value)
|
m_value(_value)
|
||||||
{}
|
{}
|
||||||
@ -389,9 +388,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;
|
||||||
|
|
||||||
std::tuple<bigint, unsigned> findFractionNumberAndBits(unsigned const restrictedBits = 0) const;
|
|
||||||
bigint denominator() const { return m_value.denominator(); }
|
bigint denominator() const { return m_value.denominator(); }
|
||||||
bigint wholeNumbers() const { return m_value.numerator() / m_value.denominator(); }
|
bigint integerPart() const { return m_value.numerator() / m_value.denominator(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
rational m_value;
|
rational m_value;
|
||||||
|
@ -158,7 +158,7 @@ tuple<Token::Value, unsigned int, unsigned int> Token::fromIdentifierOrKeyword(s
|
|||||||
int n = parseSize(positionX + 1, _literal.end());
|
int n = parseSize(positionX + 1, _literal.end());
|
||||||
if (
|
if (
|
||||||
0 <= m && m <= 256 &&
|
0 <= m && m <= 256 &&
|
||||||
0 <= n && n <= 256 &&
|
8 <= n && n <= 256 &&
|
||||||
m + n > 0 &&
|
m + n > 0 &&
|
||||||
m + n <= 256 &&
|
m + n <= 256 &&
|
||||||
m % 8 == 0 &&
|
m % 8 == 0 &&
|
||||||
|
@ -3454,11 +3454,10 @@ BOOST_AUTO_TEST_CASE(inline_array_fixed_rationals)
|
|||||||
BOOST_CHECK(success(text));
|
BOOST_CHECK(success(text));
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(zero_and_eight_variants_fixed)
|
BOOST_AUTO_TEST_CASE(zero_and_eight_variant_fixed)
|
||||||
{
|
{
|
||||||
char const* text = R"(
|
char const* text = R"(
|
||||||
contract A {
|
contract A {
|
||||||
ufixed8x0 someInt = 4;
|
|
||||||
ufixed0x8 half = 0.5;
|
ufixed0x8 half = 0.5;
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
@ -3471,7 +3470,7 @@ BOOST_AUTO_TEST_CASE(size_capabilities_of_fixed_point_types)
|
|||||||
contract test {
|
contract test {
|
||||||
function f() {
|
function f() {
|
||||||
ufixed0x256 a = 0.12345678;
|
ufixed0x256 a = 0.12345678;
|
||||||
ufixed24x0 b = 12345678.0;
|
ufixed24x8 b = 12345678.5;
|
||||||
ufixed0x256 c = 0.00000009;
|
ufixed0x256 c = 0.00000009;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3532,7 +3531,7 @@ BOOST_AUTO_TEST_CASE(rational_to_bytes_implicit_conversion)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
BOOST_CHECK(success(text));
|
BOOST_CHECK(!success(text));
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(fixed_to_bytes_implicit_conversion)
|
BOOST_AUTO_TEST_CASE(fixed_to_bytes_implicit_conversion)
|
||||||
|
Loading…
Reference in New Issue
Block a user