aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity/ast
diff options
context:
space:
mode:
Diffstat (limited to 'libsolidity/ast')
-rw-r--r--libsolidity/ast/AST.h2
-rw-r--r--libsolidity/ast/Types.cpp101
-rw-r--r--libsolidity/ast/Types.h23
3 files changed, 62 insertions, 64 deletions
diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h
index cde14ea0..81ddc754 100644
--- a/libsolidity/ast/AST.h
+++ b/libsolidity/ast/AST.h
@@ -704,7 +704,7 @@ public:
ASTPointer<ParameterList> const& _parameters,
ASTPointer<Block> const& _body
):
- CallableDeclaration(_location, _name, Visibility::Default, _parameters),
+ CallableDeclaration(_location, _name, Visibility::Internal, _parameters),
Documented(_documentation),
m_body(_body)
{
diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp
index 76bfb1a8..bcfccc3e 100644
--- a/libsolidity/ast/Types.cpp
+++ b/libsolidity/ast/Types.cpp
@@ -196,9 +196,9 @@ TypePointer Type::fromElementaryTypeName(ElementaryTypeNameToken const& _type)
case Token::UInt:
return make_shared<IntegerType>(256, IntegerType::Modifier::Unsigned);
case Token::Fixed:
- return make_shared<FixedPointType>(128, 128, FixedPointType::Modifier::Signed);
+ return make_shared<FixedPointType>(128, 19, FixedPointType::Modifier::Signed);
case Token::UFixed:
- return make_shared<FixedPointType>(128, 128, FixedPointType::Modifier::Unsigned);
+ return make_shared<FixedPointType>(128, 19, FixedPointType::Modifier::Unsigned);
case Token::Byte:
return make_shared<FixedBytesType>(1);
case Token::Address:
@@ -352,12 +352,11 @@ bool IntegerType::isImplicitlyConvertibleTo(Type const& _convertTo) const
else if (_convertTo.category() == Category::FixedPoint)
{
FixedPointType const& convertTo = dynamic_cast<FixedPointType const&>(_convertTo);
- if (convertTo.integerBits() < m_bits || isAddress())
+
+ if (isAddress())
return false;
- else if (isSigned())
- return convertTo.isSigned();
else
- return !convertTo.isSigned() || convertTo.integerBits() > m_bits;
+ return maxValue() <= convertTo.maxIntegerValue() && minValue() >= convertTo.minIntegerValue();
}
else
return false;
@@ -487,22 +486,20 @@ MemberList::MemberMap IntegerType::nativeMembers(ContractDefinition const*) cons
return MemberList::MemberMap();
}
-FixedPointType::FixedPointType(int _integerBits, int _fractionalBits, FixedPointType::Modifier _modifier):
- m_integerBits(_integerBits), m_fractionalBits(_fractionalBits), m_modifier(_modifier)
+FixedPointType::FixedPointType(int _totalBits, int _fractionalDigits, FixedPointType::Modifier _modifier):
+ m_totalBits(_totalBits), m_fractionalDigits(_fractionalDigits), m_modifier(_modifier)
{
solAssert(
- m_integerBits + m_fractionalBits > 0 &&
- m_integerBits + m_fractionalBits <= 256 &&
- m_integerBits % 8 == 0 &&
- m_fractionalBits % 8 == 0,
+ 8 <= m_totalBits && m_totalBits <= 256 && m_totalBits % 8 == 0 &&
+ 0 <= m_fractionalDigits && m_fractionalDigits <= 80,
"Invalid bit number(s) for fixed type: " +
- dev::toString(_integerBits) + "x" + dev::toString(_fractionalBits)
- );
+ dev::toString(_totalBits) + "x" + dev::toString(_fractionalDigits)
+ );
}
string FixedPointType::identifier() const
{
- return "t_" + string(isSigned() ? "" : "u") + "fixed" + std::to_string(integerBits()) + "x" + std::to_string(fractionalBits());
+ return "t_" + string(isSigned() ? "" : "u") + "fixed" + std::to_string(m_totalBits) + "x" + std::to_string(m_fractionalDigits);
}
bool FixedPointType::isImplicitlyConvertibleTo(Type const& _convertTo) const
@@ -510,12 +507,10 @@ bool FixedPointType::isImplicitlyConvertibleTo(Type const& _convertTo) const
if (_convertTo.category() == category())
{
FixedPointType const& convertTo = dynamic_cast<FixedPointType const&>(_convertTo);
- if (convertTo.m_integerBits < m_integerBits || convertTo.m_fractionalBits < m_fractionalBits)
+ if (convertTo.numBits() < m_totalBits || convertTo.fractionalDigits() < m_fractionalDigits)
return false;
- else if (isSigned())
- return convertTo.isSigned();
else
- return !convertTo.isSigned() || (convertTo.m_integerBits > m_integerBits);
+ return convertTo.maxIntegerValue() >= maxIntegerValue() && convertTo.minIntegerValue() <= minIntegerValue();
}
return false;
}
@@ -549,13 +544,30 @@ bool FixedPointType::operator==(Type const& _other) const
if (_other.category() != category())
return false;
FixedPointType const& other = dynamic_cast<FixedPointType const&>(_other);
- return other.m_integerBits == m_integerBits && other.m_fractionalBits == m_fractionalBits && other.m_modifier == m_modifier;
+ return other.m_totalBits == m_totalBits && other.m_fractionalDigits == m_fractionalDigits && other.m_modifier == m_modifier;
}
string FixedPointType::toString(bool) const
{
string prefix = isSigned() ? "fixed" : "ufixed";
- return prefix + dev::toString(m_integerBits) + "x" + dev::toString(m_fractionalBits);
+ return prefix + dev::toString(m_totalBits) + "x" + dev::toString(m_fractionalDigits);
+}
+
+bigint FixedPointType::maxIntegerValue() const
+{
+ bigint maxValue = (bigint(1) << (m_totalBits - (isSigned() ? 1 : 0))) - 1;
+ return maxValue / pow(bigint(10), m_fractionalDigits);
+}
+
+bigint FixedPointType::minIntegerValue() const
+{
+ if (isSigned())
+ {
+ bigint minValue = -(bigint(1) << (m_totalBits - (isSigned() ? 1 : 0)));
+ return minValue / pow(bigint(10), m_fractionalDigits);
+ }
+ else
+ return bigint(0);
}
TypePointer FixedPointType::binaryOperatorResult(Token::Value _operator, TypePointer const& _other) const
@@ -743,13 +755,9 @@ bool RationalNumberType::isImplicitlyConvertibleTo(Type const& _convertTo) const
else if (_convertTo.category() == Category::FixedPoint)
{
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 * (bigint(1) << fixed->fractionalBits());
- return value.denominator() == 1 && fixed->isImplicitlyConvertibleTo(_convertTo);
- }
- return false;
+ return fixed->isImplicitlyConvertibleTo(_convertTo);
+ else
+ return false;
}
else if (_convertTo.category() == Category::FixedBytes)
{
@@ -953,10 +961,9 @@ u256 RationalNumberType::literalValue(Literal const*) const
else
{
auto fixed = fixedPointType();
- solAssert(!!fixed, "");
- rational shifted = m_value * (bigint(1) << fixed->fractionalBits());
- // truncate
- shiftedValue = shifted.numerator() / shifted.denominator();
+ solAssert(fixed, "");
+ int fractionalDigits = fixed->fractionalDigits();
+ shiftedValue = (m_value.numerator() / m_value.denominator()) * pow(bigint(10), fractionalDigits);
}
// we ignore the literal and hope that the type was correctly determined
@@ -997,22 +1004,21 @@ shared_ptr<IntegerType const> RationalNumberType::integerType() const
shared_ptr<FixedPointType const> RationalNumberType::fixedPointType() const
{
bool negative = (m_value < 0);
- unsigned fractionalBits = 0;
+ unsigned fractionalDigits = 0;
rational value = abs(m_value); // We care about the sign later.
rational maxValue = negative ?
rational(bigint(1) << 255, 1):
rational((bigint(1) << 256) - 1, 1);
- while (value * 0x100 <= maxValue && value.denominator() != 1 && fractionalBits < 256)
+ while (value * 10 <= maxValue && value.denominator() != 1 && fractionalDigits < 80)
{
- value *= 0x100;
- fractionalBits += 8;
+ value *= 10;
+ fractionalDigits++;
}
if (value > maxValue)
return shared_ptr<FixedPointType const>();
- // u256(v) is the actual value that will be put on the stack
- // From here on, very similar to integerType()
+ // This means we round towards zero for positive and negative values.
bigint v = value.numerator() / value.denominator();
if (negative)
// modify value to satisfy bit requirements for negative numbers:
@@ -1022,26 +1028,11 @@ shared_ptr<FixedPointType const> RationalNumberType::fixedPointType() const
if (v > u256(-1))
return shared_ptr<FixedPointType const>();
- unsigned totalBits = bytesRequired(v) * 8;
+ unsigned totalBits = max(bytesRequired(v), 1u) * 8;
solAssert(totalBits <= 256, "");
- unsigned integerBits = totalBits >= fractionalBits ? totalBits - fractionalBits : 0;
- // Special case: Numbers between -1 and 0 have their sign bit in the fractional part.
- if (negative && abs(m_value) < 1 && totalBits > fractionalBits)
- {
- fractionalBits += 8;
- integerBits = 0;
- }
-
- if (integerBits > 256 || fractionalBits > 256 || fractionalBits + integerBits > 256)
- return shared_ptr<FixedPointType const>();
- if (integerBits == 0 && fractionalBits == 0)
- {
- integerBits = 0;
- fractionalBits = 8;
- }
return make_shared<FixedPointType>(
- integerBits, fractionalBits,
+ totalBits, fractionalDigits,
negative ? FixedPointType::Modifier::Signed : FixedPointType::Modifier::Unsigned
);
}
diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h
index c24cc11a..3d7dad16 100644
--- a/libsolidity/ast/Types.h
+++ b/libsolidity/ast/Types.h
@@ -342,7 +342,7 @@ public:
};
virtual Category category() const override { return Category::FixedPoint; }
- explicit FixedPointType(int _integerBits, int _fractionalBits, Modifier _modifier = Modifier::Unsigned);
+ explicit FixedPointType(int _totalBits, int _fractionalDigits, Modifier _modifier = Modifier::Unsigned);
virtual std::string identifier() const override;
virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override;
@@ -352,8 +352,8 @@ public:
virtual bool operator==(Type const& _other) const override;
- virtual unsigned calldataEncodedSize(bool _padded = true) const override { return _padded ? 32 : (m_integerBits + m_fractionalBits) / 8; }
- virtual unsigned storageBytes() const override { return (m_integerBits + m_fractionalBits) / 8; }
+ virtual unsigned calldataEncodedSize(bool _padded = true) const override { return _padded ? 32 : m_totalBits / 8; }
+ virtual unsigned storageBytes() const override { return m_totalBits / 8; }
virtual bool isValueType() const override { return true; }
virtual std::string toString(bool _short) const override;
@@ -361,14 +361,21 @@ public:
virtual TypePointer encodingType() const override { return shared_from_this(); }
virtual TypePointer interfaceType(bool) const override { return shared_from_this(); }
- int numBits() const { return m_integerBits + m_fractionalBits; }
- int integerBits() const { return m_integerBits; }
- int fractionalBits() const { return m_fractionalBits; }
+ /// Number of bits used for this type in total.
+ int numBits() const { return m_totalBits; }
+ /// Number of decimal digits after the radix point.
+ int fractionalDigits() const { return m_fractionalDigits; }
bool isSigned() const { return m_modifier == Modifier::Signed; }
+ /// @returns the largest integer value this type con hold. Note that this is not the
+ /// largest value in general.
+ bigint maxIntegerValue() const;
+ /// @returns the smallest integer value this type can hold. Note hat this is not the
+ /// smallest value in general.
+ bigint minIntegerValue() const;
private:
- int m_integerBits;
- int m_fractionalBits;
+ int m_totalBits;
+ int m_fractionalDigits;
Modifier m_modifier;
};