diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index 6df9aae07..5ae0443ad 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -774,6 +774,7 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement) solAssert(!var.typeName(), ""); var.annotation().type = valueComponentType->mobileType(); if (!var.annotation().type) + { if (valueComponentType->category() == Type::Category::RationalNumber) fatalTypeError( _statement.initialValue()->location(), @@ -783,6 +784,7 @@ bool TypeChecker::visit(VariableDeclarationStatement const& _statement) ); else solAssert(false, ""); + } var.accept(*this); } else diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 7995e7e3a..0df68d3da 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -32,7 +32,6 @@ using namespace std; using namespace dev; using namespace dev::solidity; -using rational = boost::rational; void StorageOffsets::computeOffsets(TypePointers const& _types) { @@ -769,8 +768,8 @@ shared_ptr RationalNumberType::fixedPointType() const unsigned fractionalBits = 0; rational value = abs(m_value); // We care about the sign later. rational maxValue = negative ? - rational(bigint(1) << 255): - rational((bigint(1) << 256) - 1); + rational(bigint(1) << 255, 1): + rational((bigint(1) << 256) - 1, 1); while (value * 0x100 <= maxValue && value.denominator() != 1 && fractionalBits < 256) { diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 26c0f9026..0c4373169 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -44,7 +44,7 @@ class FunctionType; // forward using TypePointer = std::shared_ptr; using FunctionTypePointer = std::shared_ptr; using TypePointers = std::vector; -using rational = boost::rational; +using rational = boost::rational; enum class DataLocation { Storage, CallData, Memory }; @@ -389,7 +389,7 @@ public: /// If the integer part does not fit, returns an empty pointer. std::shared_ptr fixedPointType() const; - /// @returns true iff the value is not an integer. + /// @returns true if the value is not an integer. bool isFractional() const { return m_value.denominator() != 1; } private: diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index 8589900ed..e35f33741 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -343,10 +343,11 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp case Type::Category::Enum: solAssert(targetTypeCategory == Type::Category::Integer || targetTypeCategory == Type::Category::Enum, ""); break; + case Type::Category::FixedPoint: + solAssert(false, "Not yet implemented - FixedPointType."); case Type::Category::Integer: case Type::Category::Contract: case Type::Category::RationalNumber: - case Type::Category::FixedPoint: if (targetTypeCategory == Type::Category::FixedBytes) { solAssert(stackTypeCategory == Type::Category::Integer || stackTypeCategory == Type::Category::RationalNumber, @@ -375,8 +376,7 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp if (auto typeOnStack = dynamic_cast(&_typeOnStack)) if (targetFixedPointType.integerBits() > typeOnStack->numBits()) cleanHigherOrderBits(*typeOnStack); - //need m_context call here - + solAssert(false, "Not yet implemented - FixedPointType."); } else { @@ -389,6 +389,7 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp RationalNumberType const& constType = dynamic_cast(_typeOnStack); // We know that the stack is clean, we only have to clean for a narrowing conversion // where cleanup is forced. + solAssert(!constType.isFractional(), "Not yet implemented - FixedPointType."); if (targetType.numBits() < constType.integerType()->numBits() && _cleanupNeeded) cleanHigherOrderBits(targetType); } diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index baf587f0c..a01e306e5 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -281,10 +281,6 @@ bool ExpressionCompiler::visit(TupleExpression const& _tuple) bool ExpressionCompiler::visit(UnaryOperation const& _unaryOperation) { CompilerContext::LocationSetter locationSetter(m_context, _unaryOperation); - //@todo type checking and creating code for an operator should be in the same place: - // the operator should know how to convert itself and to which types it applies, so - // put this code together with "Type::acceptsBinary/UnaryOperator" into a class that - // represents the operator if (_unaryOperation.annotation().type->category() == Type::Category::RationalNumber) { m_context << _unaryOperation.annotation().type->literalValue(nullptr); @@ -1306,6 +1302,9 @@ void ExpressionCompiler::appendArithmeticOperatorCode(Token::Value _operator, Ty IntegerType const& type = dynamic_cast(_type); bool const c_isSigned = type.isSigned(); + if (_type.category() == Type::Category::FixedPoint) + solAssert(false, "Not yet implemented - FixedPointType."); + switch (_operator) { case Token::Add: diff --git a/libsolidity/codegen/LValue.cpp b/libsolidity/codegen/LValue.cpp index 1d1956aa2..ea8bc1bae 100644 --- a/libsolidity/codegen/LValue.cpp +++ b/libsolidity/codegen/LValue.cpp @@ -179,6 +179,9 @@ void StorageItem::retrieveValue(SourceLocation const&, bool _remove) const m_context << Instruction::SWAP1 << Instruction::SLOAD << Instruction::SWAP1 << u256(0x100) << Instruction::EXP << Instruction::SWAP1 << Instruction::DIV; + if (m_dataType->category() == Type::Category::FixedPoint) + // implementation should be very similar to the integer case. + solAssert(false, "Not yet implemented - FixedPointType."); if (m_dataType->category() == Type::Category::FixedBytes) m_context << (u256(0x1) << (256 - 8 * m_dataType->storageBytes())) << Instruction::MUL; else if ( @@ -186,7 +189,6 @@ void StorageItem::retrieveValue(SourceLocation const&, bool _remove) const dynamic_cast(*m_dataType).isSigned() ) m_context << u256(m_dataType->storageBytes() - 1) << Instruction::SIGNEXTEND; - //need something here for Fixed...guidance would be nice else m_context << ((u256(0x1) << (8 * m_dataType->storageBytes())) - 1) << Instruction::AND; } @@ -240,9 +242,10 @@ void StorageItem::storeValue(Type const& _sourceType, SourceLocation const& _loc << Instruction::DUP2 << Instruction::MUL << Instruction::DIV; + else if (m_dataType->category() == Type::Category::FixedPoint) + // implementation should be very similar to the integer case. + solAssert(false, "Not yet implemented - FixedPointType."); m_context << Instruction::MUL << Instruction::OR; - //else if (m_dataType->category() == Type::Category::Fixed) - //trying to figure out what this does...going to require some more assistance // stack: value storage_ref updated_value m_context << Instruction::SWAP1 << Instruction::SSTORE; if (_move) diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 67748c1f1..de428f964 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -6634,28 +6634,6 @@ BOOST_AUTO_TEST_CASE(delete_on_array_of_structs) } -/*BOOST_AUTO_TEST_CASE(fixed_data_type) -{ - char const* sourceCode = R"( - contract C { - fixed public pi = 3.141592; - } - )"; - compileAndRun(sourceCode, 0, "C"); -} - -BOOST_AUTO_TEST_CASE(fixed_data_type_expression) -{ - char const* sourceCode = R"( - contract C { - function f(fixed a) returns (fixed) { - return (a + 3); - } - } - )"; - compileAndRun(sourceCode, 0, "C"); -}*/ - BOOST_AUTO_TEST_CASE(internal_library_function) { // tests that internal library functions can be called from outside