mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
reorganized tests and fixed mobile types and implicit conversions of rationals and fixed point types
one final tweak check for null types
This commit is contained in:
parent
bfc238c8d1
commit
a6fc3c8f30
@ -774,8 +774,7 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement)
|
||||
solAssert(!var.typeName(), "");
|
||||
if (
|
||||
valueComponentType->category() == Type::Category::RationalNumber &&
|
||||
!dynamic_pointer_cast<RationalNumberType const>(valueComponentType)->integerType() &&
|
||||
!dynamic_pointer_cast<RationalNumberType const>(valueComponentType)->fixedPointType()
|
||||
!dynamic_pointer_cast<RationalNumberType const>(valueComponentType)->mobileType()
|
||||
)
|
||||
fatalTypeError(_statement.initialValue()->location(), "Invalid rational " + valueComponentType->toString() + ".");
|
||||
var.annotation().type = valueComponentType->mobileType();
|
||||
@ -785,14 +784,32 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement)
|
||||
{
|
||||
var.accept(*this);
|
||||
if (!valueComponentType->isImplicitlyConvertibleTo(*var.annotation().type))
|
||||
typeError(
|
||||
_statement.location(),
|
||||
"Type " +
|
||||
valueComponentType->toString() +
|
||||
" is not implicitly convertible to expected type " +
|
||||
var.annotation().type->toString() +
|
||||
"."
|
||||
);
|
||||
{
|
||||
if (
|
||||
valueComponentType->category() == Type::Category::RationalNumber &&
|
||||
dynamic_pointer_cast<RationalNumberType const>(valueComponentType)->denominator() != 1 &&
|
||||
!!valueComponentType->mobileType()
|
||||
)
|
||||
typeError(
|
||||
_statement.location(),
|
||||
"Type " +
|
||||
valueComponentType->toString() +
|
||||
" is not implicitly convertible to expected type " +
|
||||
var.annotation().type->toString() +
|
||||
". Try converting to type " +
|
||||
valueComponentType->mobileType()->toString() +
|
||||
" or use an explicit conversion."
|
||||
);
|
||||
else
|
||||
typeError(
|
||||
_statement.location(),
|
||||
"Type " +
|
||||
valueComponentType->toString() +
|
||||
" is not implicitly convertible to expected type " +
|
||||
var.annotation().type->toString() +
|
||||
"."
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@ -1499,16 +1516,33 @@ Declaration const& TypeChecker::dereference(UserDefinedTypeName const& _typeName
|
||||
void TypeChecker::expectType(Expression const& _expression, Type const& _expectedType)
|
||||
{
|
||||
_expression.accept(*this);
|
||||
|
||||
if (!type(_expression)->isImplicitlyConvertibleTo(_expectedType))
|
||||
typeError(
|
||||
_expression.location(),
|
||||
"Type " +
|
||||
type(_expression)->toString() +
|
||||
" is not implicitly convertible to expected type " +
|
||||
_expectedType.toString() +
|
||||
"."
|
||||
);
|
||||
{
|
||||
if (
|
||||
type(_expression)->category() == Type::Category::RationalNumber &&
|
||||
dynamic_pointer_cast<RationalNumberType const>(type(_expression))->denominator() != 1 &&
|
||||
!!type(_expression)->mobileType()
|
||||
)
|
||||
typeError(
|
||||
_expression.location(),
|
||||
"Type " +
|
||||
type(_expression)->toString() +
|
||||
" is not implicitly convertible to expected type " +
|
||||
_expectedType.toString() +
|
||||
". Try converting to type " +
|
||||
type(_expression)->mobileType()->toString() +
|
||||
" or using an explicit conversion."
|
||||
);
|
||||
else
|
||||
typeError(
|
||||
_expression.location(),
|
||||
"Type " +
|
||||
type(_expression)->toString() +
|
||||
" is not implicitly convertible to expected type " +
|
||||
_expectedType.toString() +
|
||||
"."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void TypeChecker::requireLValue(Expression const& _expression)
|
||||
|
@ -387,18 +387,8 @@ bool FixedPointType::isImplicitlyConvertibleTo(Type const& _convertTo) const
|
||||
else
|
||||
return !convertTo.isSigned() || (convertTo.m_integerBits > m_integerBits);
|
||||
}
|
||||
else if (_convertTo.category() == Category::Integer)
|
||||
{
|
||||
IntegerType const& convertTo = dynamic_cast<IntegerType const&>(_convertTo);
|
||||
if (convertTo.numBits() < m_integerBits)
|
||||
return false;
|
||||
else if (isSigned())
|
||||
return convertTo.isSigned();
|
||||
else
|
||||
return !convertTo.isSigned() || convertTo.numBits() > m_integerBits;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FixedPointType::isExplicitlyConvertibleTo(Type const& _convertTo) const
|
||||
@ -459,6 +449,8 @@ TypePointer FixedPointType::binaryOperatorResult(Token::Value _operator, TypePoi
|
||||
return commonType;
|
||||
if (Token::isBitOp(_operator) || Token::isBooleanOp(_operator))
|
||||
return TypePointer();
|
||||
if (Token::Exp == _operator)
|
||||
return TypePointer();
|
||||
return commonType;
|
||||
}
|
||||
|
||||
@ -471,7 +463,6 @@ tuple<bool, rational> RationalNumberType::isValidLiteral(Literal const& _literal
|
||||
rational denominator(1);
|
||||
|
||||
auto radixPoint = find(_literal.value().begin(), _literal.value().end(), '.');
|
||||
|
||||
if (radixPoint != _literal.value().end())
|
||||
{
|
||||
if (
|
||||
@ -485,8 +476,7 @@ tuple<bool, rational> RationalNumberType::isValidLiteral(Literal const& _literal
|
||||
_literal.value().end(),
|
||||
[](char const& a) { return a == '0'; }
|
||||
);
|
||||
auto fractionalBegin = leadingZeroes != _literal.value().end() ?
|
||||
leadingZeroes : radixPoint + 1;
|
||||
auto fractionalBegin = leadingZeroes;
|
||||
|
||||
denominator = bigint(string(fractionalBegin, _literal.value().end()));
|
||||
denominator /= boost::multiprecision::pow(
|
||||
@ -498,43 +488,44 @@ tuple<bool, rational> RationalNumberType::isValidLiteral(Literal const& _literal
|
||||
}
|
||||
else
|
||||
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 (...)
|
||||
{
|
||||
return make_tuple(false, rational(0));
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
return make_tuple(true, x);
|
||||
}
|
||||
|
||||
@ -559,8 +550,14 @@ bool RationalNumberType::isImplicitlyConvertibleTo(Type const& _convertTo) const
|
||||
}
|
||||
else if (_convertTo.category() == Category::FixedPoint)
|
||||
{
|
||||
if (fixedPointType() && fixedPointType()->isImplicitlyConvertibleTo(_convertTo))
|
||||
return true;
|
||||
//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())
|
||||
{
|
||||
rational value = m_value * boost::multiprecision::pow(bigint(2), fixed->fractionalBits());
|
||||
if (value.denominator() == 1 && fixed->isImplicitlyConvertibleTo(_convertTo))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else if (_convertTo.category() == Category::FixedBytes)
|
||||
@ -744,7 +741,17 @@ string RationalNumberType::toString(bool) const
|
||||
u256 RationalNumberType::literalValue(Literal const*) const
|
||||
{
|
||||
u256 value;
|
||||
bigint shiftedValue = integerPart();
|
||||
bigint shiftedValue;
|
||||
|
||||
if (m_value.denominator() != 1)
|
||||
{
|
||||
rational temporaryValue = m_value;
|
||||
auto fixed = fixedPointType();
|
||||
temporaryValue *= boost::multiprecision::pow(bigint(2), fixed->fractionalBits());
|
||||
shiftedValue = temporaryValue.numerator() / temporaryValue.denominator();
|
||||
}
|
||||
else
|
||||
shiftedValue = integerPart();
|
||||
// we ignore the literal and hope that the type was correctly determined
|
||||
solAssert(shiftedValue <= u256(-1), "Integer constant too large.");
|
||||
solAssert(shiftedValue >= -(bigint(1) << 255), "Number constant too small.");
|
||||
@ -772,6 +779,7 @@ TypePointer RationalNumberType::mobileType() const
|
||||
//TODO: combine integerType() and fixedPointType() into one function
|
||||
shared_ptr<IntegerType const> RationalNumberType::integerType() const
|
||||
{
|
||||
solAssert(m_value.denominator() == 1, "Non integer type found.");
|
||||
bigint value = integerPart();
|
||||
bool negative = (value < 0);
|
||||
if (negative) // convert to positive number of same bit requirements
|
||||
@ -788,28 +796,15 @@ shared_ptr<IntegerType const> RationalNumberType::integerType() const
|
||||
shared_ptr<FixedPointType const> RationalNumberType::fixedPointType() const
|
||||
{
|
||||
bool negative = (m_value < 0);
|
||||
bigint fillRationalBits = bigint(1) << 256; //use this because rationals don't have bit ops
|
||||
unsigned fractionalBits = 0;
|
||||
unsigned integerBits = 0;
|
||||
rational value = m_value;
|
||||
bigint transitionValue = bigint(1) << 256;
|
||||
rational maxValue = rational(transitionValue);
|
||||
rational value = abs(m_value); //convert to absolute value of same type for byte requirements
|
||||
rational maxValue = negative ?
|
||||
rational(fillRationalBits) / 2:
|
||||
rational(fillRationalBits) - 1;
|
||||
|
||||
if (!negative)
|
||||
{
|
||||
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)
|
||||
while (value * 0x100 <= maxValue && value.denominator() != 1 && fractionalBits < 256)
|
||||
{
|
||||
value *= 0x100;
|
||||
fractionalBits += 8;
|
||||
@ -817,17 +812,27 @@ shared_ptr<FixedPointType const> RationalNumberType::fixedPointType() const
|
||||
|
||||
if (value > maxValue)
|
||||
return shared_ptr<FixedPointType const>();
|
||||
bigint v = value.denominator() / value.numerator();
|
||||
if (negative)
|
||||
v = -v;
|
||||
// u256(v) is the actual value that will be put on the stack
|
||||
// From here on, very similar to integerType()
|
||||
//if (negative) // convert to positive number of same bit requirements
|
||||
// value = ((0 - value) - 1) << 1;
|
||||
if (value > u256(-1))
|
||||
bigint v = value.numerator() / value.denominator();
|
||||
if (negative) //convert back to negative number and then shift into a positive number of equal size
|
||||
v = (v - 1) << 1;
|
||||
|
||||
if (v > u256(-1))
|
||||
return shared_ptr<FixedPointType const>();
|
||||
//solAssert(integerBits >= fractionalBits, "Invalid bit requirement calculation.");
|
||||
//@todo special handling for integerBits == 0 && fractionalBits == 0?
|
||||
if (0 == integerPart())
|
||||
integerBits = 0;
|
||||
else
|
||||
integerBits = (bytesRequired(v) * 8) - fractionalBits;
|
||||
|
||||
if (integerBits > 256 || fractionalBits > 256 || fractionalBits + integerBits > 256)
|
||||
return shared_ptr<FixedPointType const>();
|
||||
if (integerBits + fractionalBits == 0)
|
||||
{
|
||||
integerBits = 0;
|
||||
fractionalBits = 8;
|
||||
}
|
||||
|
||||
return make_shared<FixedPointType>(
|
||||
integerBits, fractionalBits,
|
||||
negative ? FixedPointType::Modifier::Signed : FixedPointType::Modifier::Unsigned
|
||||
|
@ -3278,23 +3278,6 @@ BOOST_AUTO_TEST_CASE(invalid_fixed_type_long)
|
||||
BOOST_CHECK(!success(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(valid_fixed_types_casting)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract test {
|
||||
function f(){
|
||||
ufixed8x8 a = ufixed8x8(8765.1234);
|
||||
ufixed16x16 b = a**2;
|
||||
ufixed24x24 c = b**3;
|
||||
ufixed32x32 d = b**2;
|
||||
ufixed40x40 e = a**5;
|
||||
}
|
||||
}
|
||||
)";
|
||||
|
||||
BOOST_CHECK(success(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(fixed_type_int_conversion)
|
||||
{
|
||||
char const* text = R"(
|
||||
@ -3310,7 +3293,7 @@ BOOST_AUTO_TEST_CASE(fixed_type_int_conversion)
|
||||
BOOST_CHECK(success(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(fixed_type_rational_conversion)
|
||||
BOOST_AUTO_TEST_CASE(fixed_type_rational_int_conversion)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract test {
|
||||
@ -3323,7 +3306,7 @@ BOOST_AUTO_TEST_CASE(fixed_type_rational_conversion)
|
||||
BOOST_CHECK(success(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(fixed_type_literal)
|
||||
BOOST_AUTO_TEST_CASE(fixed_type_rational_fraction_conversion)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract test {
|
||||
@ -3336,17 +3319,214 @@ BOOST_AUTO_TEST_CASE(fixed_type_literal)
|
||||
BOOST_CHECK(success(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(fixed_type_literal_expression)
|
||||
BOOST_AUTO_TEST_CASE(invalid_int_implicit_conversion_from_fixed)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract test {
|
||||
function f() {
|
||||
ufixed8x248 a = 3.14 * 3;
|
||||
ufixed8x248 b = 4 - 2.555555;
|
||||
ufixed0x256 c = 1.0 / 3.0;
|
||||
ufixed16x240 d = 599 + .5367;
|
||||
ufixed8x248 e = 35.245 % 12.9;
|
||||
ufixed8x248 f = 1.2 % 2;
|
||||
fixed a = 4.5;
|
||||
int b = a;
|
||||
}
|
||||
}
|
||||
)";
|
||||
BOOST_CHECK(!success(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(rational_unary_operation)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract test {
|
||||
function f() {
|
||||
ufixed8x16 a = +3.25;
|
||||
fixed8x16 b = -3.25;
|
||||
}
|
||||
}
|
||||
)";
|
||||
BOOST_CHECK(success(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(leading_zero_rationals_convert)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract A {
|
||||
function f() {
|
||||
ufixed0x8 a = 0.5;
|
||||
ufixed0x56 b = 0.0000000000000006661338147750939242541790008544921875;
|
||||
fixed0x8 c = -0.5;
|
||||
fixed0x56 d = -0.0000000000000006661338147750939242541790008544921875;
|
||||
}
|
||||
}
|
||||
)";
|
||||
BOOST_CHECK(success(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(size_capabilities_of_fixed_point_types)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract test {
|
||||
function f() {
|
||||
ufixed248x8 a = 123456781234567979695948382928485849359686494864095409282048094275023098123.5;
|
||||
ufixed0x256 b = 0.920890746623327805482905058466021565416131529487595827354393978494366605267637829135688384325135165352082715782143655824815685807141335814463015972119819459298455224338812271036061391763384038070334798471324635050876128428143374549108557403087615966796875;
|
||||
ufixed0x256 c = 0.0000000000015198847363997979984922685411315294875958273543939784943666052676464653042434787697605517039455161817147718251801220885263595179331845639229818863564267318422845592626219390573301877339317935702714669975697814319204326238832436501979827880859375;
|
||||
fixed248x8 d = -123456781234567979695948382928485849359686494864095409282048094275023098123.5;
|
||||
fixed0x256 e = -0.93322335481643744342575580035176794825198893968114429702091846411734101080123092162893656820177312738451291806995868682861328125;
|
||||
fixed0x256 g = -0.00011788606643744342575580035176794825198893968114429702091846411734101080123092162893656820177312738451291806995868682861328125;
|
||||
}
|
||||
}
|
||||
)";
|
||||
BOOST_CHECK(success(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(fixed_type_invalid_implicit_conversion_size)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract test {
|
||||
function f() {
|
||||
ufixed a = 11/4;
|
||||
ufixed248x8 b = a;
|
||||
}
|
||||
}
|
||||
)";
|
||||
BOOST_CHECK(!success(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(fixed_type_invalid_implicit_conversion_lost_data)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract test {
|
||||
function f() {
|
||||
ufixed0x256 a = 1/3;
|
||||
}
|
||||
}
|
||||
)";
|
||||
BOOST_CHECK(!success(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(fixed_type_valid_explicit_conversions)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract test {
|
||||
function f() {
|
||||
ufixed0x256 a = ufixed0x256(1/3);
|
||||
ufixed0x248 b = ufixed0x248(1/3);
|
||||
ufixed0x8 c = ufixed0x8(1/3);
|
||||
}
|
||||
}
|
||||
)";
|
||||
BOOST_CHECK(success(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(invalid_array_declaration_with_rational)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract test {
|
||||
function f() {
|
||||
uint[3.5] a;
|
||||
}
|
||||
}
|
||||
)";
|
||||
BOOST_CHECK(!success(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(invalid_array_declaration_with_fixed_type)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract test {
|
||||
function f() {
|
||||
uint[fixed(3.5)] a;
|
||||
}
|
||||
}
|
||||
)";
|
||||
BOOST_CHECK(!success(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(rational_to_bytes_implicit_conversion)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract test {
|
||||
function f() {
|
||||
bytes32 c = 3.2;
|
||||
}
|
||||
}
|
||||
)";
|
||||
BOOST_CHECK(!success(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(fixed_to_bytes_implicit_conversion)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract test {
|
||||
function f() {
|
||||
fixed a = 3.2;
|
||||
bytes32 c = a;
|
||||
}
|
||||
}
|
||||
)";
|
||||
BOOST_CHECK(!success(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(mapping_with_fixed_literal)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract test {
|
||||
mapping(ufixed8x248 => string) fixedString;
|
||||
function f() {
|
||||
fixedString[0.5] = "Half";
|
||||
}
|
||||
}
|
||||
)";
|
||||
BOOST_CHECK(success(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(fixed_points_inside_structs)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract test {
|
||||
struct myStruct {
|
||||
ufixed a;
|
||||
int b;
|
||||
}
|
||||
myStruct a = myStruct(3.125, 3);
|
||||
}
|
||||
)";
|
||||
BOOST_CHECK(success(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(inline_array_fixed_types)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract test {
|
||||
function f() {
|
||||
fixed[3] memory a = [fixed(3.5), fixed(-4.25), fixed(967.125)];
|
||||
}
|
||||
}
|
||||
)";
|
||||
BOOST_CHECK(success(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(inline_array_rationals)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract test {
|
||||
function f() {
|
||||
ufixed8x8[4] memory a = [3.5, 4.125, 2.5, 4.0];
|
||||
}
|
||||
}
|
||||
)";
|
||||
BOOST_CHECK(success(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(rational_to_fixed_literal_expression)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract test {
|
||||
function f() {
|
||||
ufixed8x8 a = 3.5 * 3;
|
||||
ufixed8x8 b = 4 - 2.5;
|
||||
ufixed8x8 c = 11 / 4;
|
||||
ufixed16x240 d = 599 + 0.21875;
|
||||
ufixed8x248 e = ufixed8x248(35.245 % 12.9);
|
||||
ufixed8x248 f = ufixed8x248(1.2 % 2);
|
||||
fixed g = 2 ** -2;
|
||||
}
|
||||
}
|
||||
@ -3360,147 +3540,9 @@ BOOST_AUTO_TEST_CASE(rational_as_exponent_value)
|
||||
contract test {
|
||||
function f() {
|
||||
fixed g = 2 ** -2.2;
|
||||
fixed b = 3 ** 2.56;
|
||||
}
|
||||
}
|
||||
)";
|
||||
BOOST_CHECK(!success(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(fixed_type_invalid_size_conversion)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract test {
|
||||
function f() {
|
||||
fixed a = 1/3;
|
||||
ufixed248x8 b = a + 2.5;
|
||||
}
|
||||
}
|
||||
)";
|
||||
BOOST_CHECK(!success(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(fixed_type_valid_size_conversion)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract test {
|
||||
function f() {
|
||||
fixed a = 1/3;
|
||||
ufixed248x8 b = ufixed248x8(a) + 2.5;
|
||||
}
|
||||
}
|
||||
)";
|
||||
BOOST_CHECK(!success(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(uint_array_declaration_with_fixed_type)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract test {
|
||||
function f() {
|
||||
uint[fixed(3.56)] a;
|
||||
}
|
||||
}
|
||||
)";
|
||||
BOOST_CHECK(!success(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(array_declaration_with_fixed_literal)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract test {
|
||||
function f() {
|
||||
uint[3.56] a;
|
||||
}
|
||||
}
|
||||
)";
|
||||
BOOST_CHECK(!success(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(mapping_with_fixed_literal)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract test {
|
||||
mapping(ufixed8x248 => string) fixedString;
|
||||
function f() {
|
||||
fixedString[3.14] = "Pi";
|
||||
}
|
||||
}
|
||||
)";
|
||||
BOOST_CHECK(success(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(inline_array_fixed_type)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract test {
|
||||
function f() {
|
||||
fixed[3] memory a = [fixed(3.5), fixed(4.1234), fixed(967.32)];
|
||||
}
|
||||
}
|
||||
)";
|
||||
BOOST_CHECK(success(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(inline_array_fixed_rationals)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract test {
|
||||
function f() {
|
||||
ufixed8x248[4] memory a = [3.5, 4.1234, 2.5, 4.0];
|
||||
}
|
||||
}
|
||||
)";
|
||||
BOOST_CHECK(success(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(zero_and_eight_variant_fixed)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract A {
|
||||
ufixed0x8 half = 0.5;
|
||||
}
|
||||
)";
|
||||
BOOST_CHECK(success(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(size_capabilities_of_fixed_point_types)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract test {
|
||||
function f() {
|
||||
ufixed0x256 a = 0.12345678;
|
||||
ufixed24x8 b = 12345678.5;
|
||||
ufixed0x256 c = 0.00000009;
|
||||
}
|
||||
}
|
||||
)";
|
||||
BOOST_CHECK(success(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(var_capable_of_holding_constant_rationals)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract test {
|
||||
function f() {
|
||||
var a = 0.12345678;
|
||||
var b = 12345678.0;
|
||||
var c = 0.00000009;
|
||||
}
|
||||
}
|
||||
)";
|
||||
BOOST_CHECK(success(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(invalid_rational_exponent_usage)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract test {
|
||||
function f() {
|
||||
fixed8x8 a = 3 ** 1.5;
|
||||
fixed24x24 b = 2 ** (1/2);
|
||||
ufixed b = 3 ** 2.5;
|
||||
ufixed24x24 b = 2 ** (1/2);
|
||||
fixed40x40 c = 42 ** (-1/4);
|
||||
fixed48x48 d = 16 ** -0.33;
|
||||
}
|
||||
}
|
||||
)";
|
||||
@ -3512,48 +3554,36 @@ BOOST_AUTO_TEST_CASE(fixed_point_casting_exponents)
|
||||
char const* text = R"(
|
||||
contract test {
|
||||
function f() {
|
||||
fixed a = 3 ** fixed(1.5);
|
||||
fixed b = 2 ** fixed(1/2);
|
||||
ufixed a = 3 ** ufixed(1.5);
|
||||
ufixed b = 2 ** ufixed(1/2);
|
||||
fixed c = 42 ** fixed(-1/4);
|
||||
fixed d = 16 ** fixed(-0.33);
|
||||
}
|
||||
}
|
||||
)";
|
||||
BOOST_CHECK(!success(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(var_capable_of_holding_constant_rationals)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract test {
|
||||
function f() {
|
||||
var a = 0.12345678;
|
||||
var b = 12345678.352;
|
||||
var c = 0.00000009;
|
||||
}
|
||||
}
|
||||
)";
|
||||
BOOST_CHECK(success(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(rational_to_bytes_implicit_conversion)
|
||||
BOOST_AUTO_TEST_CASE(var_handle_divided_integers)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract test {
|
||||
function f() {
|
||||
bytes32 c = 3.183;
|
||||
}
|
||||
}
|
||||
)";
|
||||
BOOST_CHECK(!success(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(fixed_to_bytes_implicit_conversion)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract test {
|
||||
function f() {
|
||||
fixed a = 3.183;
|
||||
bytes32 c = a;
|
||||
}
|
||||
}
|
||||
)";
|
||||
BOOST_CHECK(!success(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(rational_unary_operation)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract test {
|
||||
function f() {
|
||||
ufixed8x248 a = +3.5134;
|
||||
fixed8x248 b = -3.5134;
|
||||
var x = 1/3;
|
||||
}
|
||||
}
|
||||
)";
|
||||
@ -3608,6 +3638,19 @@ BOOST_AUTO_TEST_CASE(rational_bitand_binary_operation)
|
||||
BOOST_CHECK(!success(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(zero_handling)
|
||||
{
|
||||
char const* text = R"(
|
||||
contract test {
|
||||
function f() {
|
||||
fixed8x8 a = 0;
|
||||
ufixed8x8 b = 0;
|
||||
}
|
||||
}
|
||||
)";
|
||||
BOOST_CHECK(success(text));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user