aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libsolidity/ast/Types.cpp83
-rw-r--r--libsolidity/ast/Types.h5
-rw-r--r--libsolidity/codegen/CompilerUtils.cpp13
-rw-r--r--libsolidity/parsing/Token.cpp4
-rw-r--r--test/libsolidity/SolidityNameAndTypeResolution.cpp172
5 files changed, 184 insertions, 93 deletions
diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp
index d5e989ac..c9df0086 100644
--- a/libsolidity/ast/Types.cpp
+++ b/libsolidity/ast/Types.cpp
@@ -362,6 +362,7 @@ 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 &&
@@ -469,7 +470,6 @@ bool ConstantNumberType::isValidLiteral(Literal const& _literal)
{
//problem here. If the first digit is a 0 in the string, it won't
//turn it into a integer...Using find if not to count the leading 0s.
-
auto leadingZeroes = find_if_not(
radixPoint + 1,
_literal.value().end(),
@@ -516,18 +516,17 @@ ConstantNumberType::ConstantNumberType(Literal const& _literal)
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;
@@ -574,28 +573,16 @@ bool ConstantNumberType::isImplicitlyConvertibleTo(Type const& _convertTo) const
}
else if (_convertTo.category() == Category::FixedPoint)
{
- auto targetType = dynamic_cast<FixedPointType const*>(&_convertTo);
- if (m_value == 0)
+ cout << "IMPLICIT CONVERSION" << endl;
+ if (fixedPointType() && fixedPointType()->isImplicitlyConvertibleTo(_convertTo))
return true;
- int forSignBit = (targetType->isSigned() ? 1 : 0);
- if (m_value > 0)
- {
- bool properlyScaledBits = m_scalingFactor <= targetType->fractionalBits() ?
- true : m_scalingFactor == 1 && targetType->fractionalBits() == 0 ? true : false;
- if (m_value <= (u256(-1) >> (256 - targetType->numBits() + forSignBit)) && properlyScaledBits)
- return true;
- else if (targetType->isSigned() && -m_value <= (u256(1) << (targetType->numBits() - forSignBit)) && properlyScaledBits)
- return true;
- return false;
- }
+ return false;
}
else if (_convertTo.category() == Category::FixedPoint)
{
- cout << "IMPLICIT CONVERSION" << endl;
if (fixedPointType() && fixedPointType()->isImplicitlyConvertibleTo(_convertTo))
return true;
-
return false;
}
else if (_convertTo.category() == Category::FixedBytes)
@@ -613,6 +600,7 @@ bool ConstantNumberType::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);
}
@@ -628,10 +616,10 @@ TypePointer ConstantNumberType::unaryOperatorResult(Token::Value _operator) cons
value = ~m_value.numerator();
break;
case Token::Add:
- value = m_value;
+ value = +(m_value);
break;
case Token::Sub:
- value = -m_value;
+ value = -(m_value);
break;
case Token::After:
return shared_from_this();
@@ -711,7 +699,6 @@ TypePointer ConstantNumberType::binaryOperatorResult(Token::Value _operator, Typ
value = m_value - other.m_value;
break;
case Token::Mul:
- scale = m_scalingFactor - other.m_scalingFactor;
value = m_value * other.m_value;
break;
case Token::Div:
@@ -734,6 +721,7 @@ TypePointer ConstantNumberType::binaryOperatorResult(Token::Value _operator, Typ
break;
case Token::Exp:
{
+ cout << "Is this the source of the problem" << endl;
bigint newDenominator;
bigint newNumerator;
if (other.m_value.denominator() != 1)
@@ -781,7 +769,7 @@ u256 ConstantNumberType::literalValue(Literal const*) const
{
u256 value;
// we ignore the literal and hope that the type was correctly determined
- solAssert(m_value <= u256(-1), "Number constant too large.");
+
solAssert(m_value >= -(bigint(1) << 255), "Number constant too small.");
if (m_value >= 0)
@@ -807,7 +795,7 @@ TypePointer ConstantNumberType::mobileType() const
shared_ptr<IntegerType const> ConstantNumberType::integerType() const
{
- bigint value = m_value.numerator() / m_value.denominator();
+ bigint value = wholeNumbers();
bool negative = (value < 0);
if (negative) // convert to positive number of same bit requirements
value = ((0 - value) - 1) << 1;
@@ -822,28 +810,51 @@ shared_ptr<IntegerType const> ConstantNumberType::integerType() const
shared_ptr<FixedPointType const> ConstantNumberType::fixedPointType() const
{
- rational value = m_value;
- cout << "Original value: " << value << endl;
- bool negative = (value < 0);
- if (negative) // convert to absolute value
- value = abs(value);
- if (value > u256(-1))
+ //do calculations up here
+ bigint integers = wholeNumbers();
+ //bigint _remainder = abs(m_value.numerator() % m_value.denominator());
+ bool fractionalSignBit = integers == 0; //sign the fractional side or the integer side
+ bool negative = (m_value < 0);
+ //todo: change name
+ bigint fractionalBits = fractionalBitsNeeded();
+
+ if (negative && !fractionalSignBit) // convert to positive number of same bit requirements
+ {
+ integers = ((0 - integers) - 1) << 1;
+ fractionalBits = ((0 - fractionalBits) - 1) << 1;
+ }
+ else if (negative && fractionalSignBit)
+ fractionalBits = ((0 - fractionalBits) - 1) << 1;
+
+ if (fractionalBits > u256(-1))
return shared_ptr<FixedPointType const>();
else
{
- // need to fix this because these aren't the proper M and N
- bigint integerBits = m_value.numerator() / m_value.denominator();
- bigint remains = m_value.numerator() % m_value.denominator();
- cout << "Integer: " << integerBits.str() << endl;
- cout << "Remains: " << remains.str() << endl << endl;
- bigint fractionalBits;
+ unsigned totalBytesRequired = bytesRequired(fractionalBits) * 8;
+ unsigned integerBytesRequired = bytesRequired(integers) * 8;
return make_shared<FixedPointType>(
- max(bytesRequired(integerBits), 1u) * 8, max(bytesRequired(fractionalBits), 1u) * 8,
+ integerBytesRequired, totalBytesRequired - integerBytesRequired,
negative ? FixedPointType::Modifier::Signed : FixedPointType::Modifier::Unsigned
);
}
}
+//todo: change name of function
+bigint ConstantNumberType::fractionalBitsNeeded() const
+{
+ auto value = m_value;
+ for (unsigned fractionalBits = 0; value < boost::multiprecision::pow(bigint(2), 256); fractionalBits += 8, value *= 10)
+ {
+ if (value.denominator() == 1)
+ return value.numerator()/value.denominator();
+ for ( ; value.denominator() != 1 && value < boost::multiprecision::pow(bigint(2), fractionalBits); value *= 10)
+ if (value.denominator() == 1)
+ return value.numerator()/value.denominator();
+ }
+ cout << "too big :(" << endl;
+ return value.numerator()/value.denominator();
+}
+
StringLiteralType::StringLiteralType(Literal const& _literal):
diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h
index e0beabf8..2039c85e 100644
--- a/libsolidity/ast/Types.h
+++ b/libsolidity/ast/Types.h
@@ -387,8 +387,11 @@ public:
std::shared_ptr<IntegerType const> integerType() const;
/// @returns the smallest fixed type that can hold the value or an empty pointer
std::shared_ptr<FixedPointType const> fixedPointType() const;
+
+ bigint fractionalBitsNeeded() const;
bigint denominator() const { return m_value.denominator(); }
-
+ bigint wholeNumbers() const { return m_value.numerator() / m_value.denominator(); }
+
private:
rational m_value;
};
diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp
index a2c44cd3..15446978 100644
--- a/libsolidity/codegen/CompilerUtils.cpp
+++ b/libsolidity/codegen/CompilerUtils.cpp
@@ -436,19 +436,6 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp
);
break;
}
- /*case Type::Category::Fixed:
- {
- if (targetTypeCategory == Type::Category::Integer)
- {
- //need some guidance here
- }
- else if (targetTypeCategory == Type::Category::FixedBytes)
- {
- //need some guidance here
- }
- else
- //need some guidance here
- }*/
case Type::Category::Array:
{
solAssert(targetTypeCategory == stackTypeCategory, "");
diff --git a/libsolidity/parsing/Token.cpp b/libsolidity/parsing/Token.cpp
index cbe0c0de..ef817d5d 100644
--- a/libsolidity/parsing/Token.cpp
+++ b/libsolidity/parsing/Token.cpp
@@ -153,9 +153,9 @@ tuple<Token::Value, unsigned int, unsigned int> Token::fromIdentifierOrKeyword(s
positionM < positionX &&
positionX < _literal.end() &&
*positionX == 'x' &&
- all_of(++positionX, _literal.end(), ::isdigit)
+ all_of(positionX + 1, _literal.end(), ::isdigit)
) {
- int n = parseSize(positionX, _literal.end());
+ int n = parseSize(positionX + 1, _literal.end());
if (
0 <= m && m <= 256 &&
0 <= n && n <= 256 &&
diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp
index 9c41dab8..42d06fd7 100644
--- a/test/libsolidity/SolidityNameAndTypeResolution.cpp
+++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp
@@ -3354,6 +3354,32 @@ BOOST_AUTO_TEST_CASE(fixed_type_literal_expression)
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"(
@@ -3366,7 +3392,6 @@ BOOST_AUTO_TEST_CASE(uint_array_declaration_with_fixed_type)
BOOST_CHECK(!success(text));
}
-
BOOST_AUTO_TEST_CASE(array_declaration_with_fixed_literal)
{
char const* text = R"(
@@ -3404,7 +3429,7 @@ BOOST_AUTO_TEST_CASE(inline_array_fixed_type)
BOOST_CHECK(success(text));
}
-BOOST_AUTO_TEST_CASE(inline_array_fixed_literals)
+BOOST_AUTO_TEST_CASE(inline_array_fixed_rationals)
{
char const* text = R"(
contract test {
@@ -3416,25 +3441,14 @@ BOOST_AUTO_TEST_CASE(inline_array_fixed_literals)
BOOST_CHECK(success(text));
}
-BOOST_AUTO_TEST_CASE(zero_and_eight_variants_fixed)
-{
- char const* text = R"(
- contract A {
- fixed8x0 someInt = 4;
- fixed0x8 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() {
- ufixed0x8 a = 0.12345678;
+ ufixed0x64 a = 0.12345678;
ufixed8x0 b = 12345678.0;
- ufixed0x8 c = 0.00000009;
+ ufixed0x64 c = 0.00000009;
}
}
)";
@@ -3547,18 +3561,18 @@ BOOST_AUTO_TEST_CASE(rational_bitand_binary_operation)
BOOST_CHECK(success(text));
}
-
-BOOST_AUTO_TEST_CASE(invalid_non_mod_8_fixed_types)
+BOOST_AUTO_TEST_CASE(valid_fraction_fixed_type)
{
char const* text = R"(
contract test {
function f(){
- fixed8x10 a = 12345678.1234567890;
+ fixed8x8 a = (2**24)/127;
+ fixed0x8 b = 1/256;
}
}
)";
- BOOST_CHECK(!success(text));
+ BOOST_CHECK(success(text));
}
BOOST_AUTO_TEST_CASE(valid_fixed_types)
@@ -3568,7 +3582,7 @@ BOOST_AUTO_TEST_CASE(valid_fixed_types)
function f(){
fixed8x8 a = 87654321.12345678;
fixed16x16 b = a**2;
- fixed24x24 c = b**(1.5);
+ fixed24x24 c = b**3;
fixed32x32 d = b**2;
fixed40x40 e = a**5;
}
@@ -3630,27 +3644,13 @@ BOOST_AUTO_TEST_CASE(fixed_type_literal_expression)
ufixed d = 599 + .5367;
ufixed e = 35.245 % 12.9;
ufixed f = 1.2 % 2.00000;
- //fixed g = 2 ** -1.5;
- //fixed h = -3 ** -5.8;
+ fixed g = 2 ** -2;
}
}
)";
BOOST_CHECK(success(text));
}
-BOOST_AUTO_TEST_CASE(fixed_type_literal_seconds_and_wei)
-{
- char const* text = R"(
- contract test {
- function f() {
- fixed a = 3.14 wei;
- ufixed b = 4.5 seconds;
- }
- }
- )";
- BOOST_CHECK(!success(text));
-}
-
BOOST_AUTO_TEST_CASE(uint_array_declaration_with_fixed_type)
{
char const* text = R"(
@@ -3664,7 +3664,7 @@ BOOST_AUTO_TEST_CASE(uint_array_declaration_with_fixed_type)
}
-BOOST_AUTO_TEST_CASE(array_declaration_with_fixed_literal)
+BOOST_AUTO_TEST_CASE(array_declaration_with_rational)
{
char const* text = R"(
contract test {
@@ -3706,7 +3706,7 @@ BOOST_AUTO_TEST_CASE(inline_array_fixed_literals)
char const* text = R"(
contract test {
function f() {
- fixed[3] memory a = [3.5, 4.1234, 967.32];
+ ufixed8x16[3] memory a = [3.5, 4.1234, 2.5];
}
}
)";
@@ -3729,16 +3729,16 @@ BOOST_AUTO_TEST_CASE(size_capabilities_of_fixed_point_types)
char const* text = R"(
contract test {
function f() {
- fixed0x8 a = 0.12345678;
- fixed8x0 b = 12345678.0;
- fixed0x8 c = 0.00000009;
+ ufixed0x8 a = 0.12345678;
+ ufixed8x0 b = 12345678.0;
+ ufixed0x8 c = 0.00000009;
}
}
)";
BOOST_CHECK(success(text));
}
-BOOST_AUTO_TEST_CASE(var_capable_of_holding_fixed_constants)
+BOOST_AUTO_TEST_CASE(var_capable_of_holding_constant_rationals)
{
char const* text = R"(
contract test {
@@ -3752,6 +3752,96 @@ BOOST_AUTO_TEST_CASE(var_capable_of_holding_fixed_constants)
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);
+ fixed40x40 c = 42 ** (-1/4);
+ fixed48x48 d = 16 ** -0.33;
+ }
+ }
+ )";
+ BOOST_CHECK(!success(text));
+}
+
+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);
+ fixed c = 42 ** fixed(-1/4);
+ fixed d = 16 ** fixed(-0.33);
+ }
+ }
+ )";
+ BOOST_CHECK(success(text));
+}
+
+BOOST_AUTO_TEST_CASE(rational_unary_operation)
+{
+ char const* text = R"(
+ contract test {
+ function f() {
+ fixed a = +3.5134;
+ fixed b = -2.5145;
+ }
+ }
+ )";
+ BOOST_CHECK(success(text));
+}
+
+BOOST_AUTO_TEST_CASE(rational_bitnot_unary_operation)
+{
+ char const* text = R"(
+ contract test {
+ function f() {
+ fixed a = ~3.56;
+ }
+ }
+ )";
+ BOOST_CHECK(!success(text));
+}
+
+BOOST_AUTO_TEST_CASE(rational_bitor_binary_operation)
+{
+ char const* text = R"(
+ contract test {
+ function f() {
+ fixed a = 1.56 | 3;
+ }
+ }
+ )";
+ BOOST_CHECK(!success(text));
+}
+
+BOOST_AUTO_TEST_CASE(rational_bitxor_binary_operation)
+{
+ char const* text = R"(
+ contract test {
+ function f() {
+ fixed a = 1.56 ^ 3;
+ }
+ }
+ )";
+ BOOST_CHECK(!success(text));
+}
+
+BOOST_AUTO_TEST_CASE(rational_bitand_binary_operation)
+{
+ char const* text = R"(
+ contract test {
+ function f() {
+ fixed a = 1.56 & 3;
+ }
+ }
+ )";
+ BOOST_CHECK(!success(text));
+}
BOOST_AUTO_TEST_SUITE_END()