Browse Source

Possibility for unary operators to change type.

cl-refactor
Christian 10 years ago
parent
commit
cc55936f67
  1. 4
      libsolidity/AST.cpp
  2. 28
      libsolidity/Types.cpp
  3. 16
      libsolidity/Types.h

4
libsolidity/AST.cpp

@ -227,8 +227,8 @@ void UnaryOperation::checkTypeRequirements()
m_subExpression->checkTypeRequirements(); m_subExpression->checkTypeRequirements();
if (m_operator == Token::Value::INC || m_operator == Token::Value::DEC || m_operator == Token::Value::DELETE) if (m_operator == Token::Value::INC || m_operator == Token::Value::DEC || m_operator == Token::Value::DELETE)
m_subExpression->requireLValue(); m_subExpression->requireLValue();
m_type = m_subExpression->getType(); m_type = m_subExpression->getType()->unaryOperatorResult(m_operator);
if (!m_type->acceptsUnaryOperator(m_operator)) if (!m_type)
BOOST_THROW_EXCEPTION(createTypeError("Unary operator not compatible with type.")); BOOST_THROW_EXCEPTION(createTypeError("Unary operator not compatible with type."));
} }

28
libsolidity/Types.cpp

@ -156,18 +156,26 @@ bool IntegerType::isExplicitlyConvertibleTo(Type const& _convertTo) const
return _convertTo.getCategory() == getCategory() || _convertTo.getCategory() == Category::CONTRACT; return _convertTo.getCategory() == getCategory() || _convertTo.getCategory() == Category::CONTRACT;
} }
bool IntegerType::acceptsUnaryOperator(Token::Value _operator) const TypePointer IntegerType::unaryOperatorResult(Token::Value _operator) const
{ {
// "delete" is ok for all integer types
if (_operator == Token::DELETE) if (_operator == Token::DELETE)
return true; return shared_from_this();
if (isAddress()) // no further unary operators for addresses
return false; else if (isAddress())
if (_operator == Token::BIT_NOT) return TypePointer();
return true; // "~" is ok for all other types
if (isHash()) else if (_operator == Token::BIT_NOT)
return false; return shared_from_this();
return _operator == Token::ADD || _operator == Token::SUB || // nothing else for hashes
_operator == Token::INC || _operator == Token::DEC; else if (isHash())
return TypePointer();
// for non-hash integers, we allow +, -, ++ and --
else if (_operator == Token::ADD || _operator == Token::SUB ||
_operator == Token::INC || _operator == Token::DEC)
return shared_from_this();
else
return TypePointer();
} }
bool IntegerType::operator==(Type const& _other) const bool IntegerType::operator==(Type const& _other) const

16
libsolidity/Types.h

@ -99,7 +99,10 @@ public:
{ {
return isImplicitlyConvertibleTo(_convertTo); return isImplicitlyConvertibleTo(_convertTo);
} }
virtual bool acceptsUnaryOperator(Token::Value) const { return false; } /// @returns the resulting type of applying the given unary operator or an empty pointer if
/// this is not possible.
/// The default implementation does not allow any unary operator.
virtual TypePointer unaryOperatorResult(Token::Value) const { return TypePointer(); }
/// @returns the resulting type of applying the given binary operator or an empty pointer if /// @returns the resulting type of applying the given binary operator or an empty pointer if
/// this is not possible. /// this is not possible.
/// The default implementation allows comparison operators if a common type exists /// The default implementation allows comparison operators if a common type exists
@ -163,7 +166,7 @@ public:
virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override; virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override;
virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override; virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override;
virtual bool acceptsUnaryOperator(Token::Value _operator) const override; virtual TypePointer unaryOperatorResult(Token::Value _operator) const override;
virtual TypePointer binaryOperatorResult(Token::Value _operator, TypePointer const& _other) const override; virtual TypePointer binaryOperatorResult(Token::Value _operator, TypePointer const& _other) const override;
virtual bool operator==(Type const& _other) const override; virtual bool operator==(Type const& _other) const override;
@ -225,9 +228,9 @@ public:
BoolType() {} BoolType() {}
virtual Category getCategory() const { return Category::BOOL; } virtual Category getCategory() const { return Category::BOOL; }
virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override; virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override;
virtual bool acceptsUnaryOperator(Token::Value _operator) const override virtual TypePointer unaryOperatorResult(Token::Value _operator) const override
{ {
return _operator == Token::NOT || _operator == Token::DELETE; return (_operator == Token::NOT || _operator == Token::DELETE) ? shared_from_this() : TypePointer();
} }
virtual TypePointer binaryOperatorResult(Token::Value _operator, TypePointer const& _other) const override; virtual TypePointer binaryOperatorResult(Token::Value _operator, TypePointer const& _other) const override;
@ -277,7 +280,10 @@ class StructType: public Type
public: public:
virtual Category getCategory() const override { return Category::STRUCT; } virtual Category getCategory() const override { return Category::STRUCT; }
StructType(StructDefinition const& _struct): m_struct(_struct) {} StructType(StructDefinition const& _struct): m_struct(_struct) {}
virtual bool acceptsUnaryOperator(Token::Value _operator) const override { return _operator == Token::DELETE; } virtual TypePointer unaryOperatorResult(Token::Value _operator) const override
{
return _operator == Token::DELETE ? shared_from_this() : TypePointer();
}
virtual bool operator==(Type const& _other) const override; virtual bool operator==(Type const& _other) const override;
virtual u256 getStorageSize() const override; virtual u256 getStorageSize() const override;

Loading…
Cancel
Save