Merge pull request #4098 from ethereum/typedResults

Introduce Result<T> for type checker functions
This commit is contained in:
chriseth 2018-12-05 14:10:30 +01:00 committed by GitHub
commit 57eb68a8df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 171 additions and 102 deletions

66
libdevcore/Result.h Normal file
View File

@ -0,0 +1,66 @@
/*
This file is part of solidity.
solidity is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
solidity is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with solidity. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <string>
namespace dev
{
/// Simple generic result that holds a value and an optional error message.
/// Results can be implicitly converted to and created from the type of
/// the value they hold. The class is mainly designed for a result type of
/// bool or pointer type. The idea is that the default constructed value of
/// the result type is interpreted as an error value.
///
/// Result<bool> check()
/// {
/// if (false)
/// return Result<bool>("Error message.")
/// return true;
/// }
///
template <class ResultType>
class Result
{
public:
Result(ResultType _value): Result(_value, std::string{}) {}
Result(std::string _message): Result(ResultType{}, std::move(_message)) {}
/// @{
/// @name Wrapper functions
/// Wrapper functions that provide implicit conversions to and explicit retrieval of
/// the value this result holds.
operator ResultType const&() const { return m_value; }
ResultType const& get() const { return m_value; }
/// @}
/// @returns the error message (can be empty).
std::string const& message() const { return m_message; }
private:
explicit Result(ResultType _value, std::string _message):
m_value(std::move(_value)),
m_message(std::move(_message))
{}
ResultType m_value;
std::string m_message;
};
}

View File

@ -41,7 +41,7 @@ void ConstantEvaluator::endVisit(BinaryOperation const& _operation)
auto right = type(_operation.rightExpression());
if (left && right)
{
auto commonType = left->binaryOperatorResult(_operation.getOperator(), right);
TypePointer commonType = left->binaryOperatorResult(_operation.getOperator(), right);
if (!commonType)
m_errorReporter.fatalTypeError(
_operation.location(),

View File

@ -466,7 +466,7 @@ string AddressType::richIdentifier() const
return "t_address";
}
bool AddressType::isImplicitlyConvertibleTo(Type const& _other) const
BoolResult AddressType::isImplicitlyConvertibleTo(Type const& _other) const
{
if (_other.category() != category())
return false;
@ -475,7 +475,7 @@ bool AddressType::isImplicitlyConvertibleTo(Type const& _other) const
return other.m_stateMutability <= m_stateMutability;
}
bool AddressType::isExplicitlyConvertibleTo(Type const& _convertTo) const
BoolResult AddressType::isExplicitlyConvertibleTo(Type const& _convertTo) const
{
if (auto const* contractType = dynamic_cast<ContractType const*>(&_convertTo))
return (m_stateMutability >= StateMutability::Payable) || !contractType->isPayable();
@ -504,13 +504,13 @@ u256 AddressType::literalValue(Literal const* _literal) const
return u256(_literal->valueWithoutUnderscores());
}
TypePointer AddressType::unaryOperatorResult(Token _operator) const
TypeResult AddressType::unaryOperatorResult(Token _operator) const
{
return _operator == Token::Delete ? make_shared<TupleType>() : TypePointer();
}
TypePointer AddressType::binaryOperatorResult(Token _operator, TypePointer const& _other) const
TypeResult AddressType::binaryOperatorResult(Token _operator, TypePointer const& _other) const
{
// Addresses can only be compared.
if (!TokenTraits::isCompareOp(_operator))
@ -576,7 +576,7 @@ string IntegerType::richIdentifier() const
return "t_" + string(isSigned() ? "" : "u") + "int" + to_string(numBits());
}
bool IntegerType::isImplicitlyConvertibleTo(Type const& _convertTo) const
BoolResult IntegerType::isImplicitlyConvertibleTo(Type const& _convertTo) const
{
if (_convertTo.category() == category())
{
@ -597,7 +597,7 @@ bool IntegerType::isImplicitlyConvertibleTo(Type const& _convertTo) const
return false;
}
bool IntegerType::isExplicitlyConvertibleTo(Type const& _convertTo) const
BoolResult IntegerType::isExplicitlyConvertibleTo(Type const& _convertTo) const
{
return _convertTo.category() == category() ||
_convertTo.category() == Category::Address ||
@ -607,18 +607,18 @@ bool IntegerType::isExplicitlyConvertibleTo(Type const& _convertTo) const
_convertTo.category() == Category::FixedPoint;
}
TypePointer IntegerType::unaryOperatorResult(Token _operator) const
TypeResult IntegerType::unaryOperatorResult(Token _operator) const
{
// "delete" is ok for all integer types
if (_operator == Token::Delete)
return make_shared<TupleType>();
return TypeResult{make_shared<TupleType>()};
// we allow +, -, ++ and --
else if (_operator == Token::Add || _operator == Token::Sub ||
_operator == Token::Inc || _operator == Token::Dec ||
_operator == Token::BitNot)
return shared_from_this();
return TypeResult{shared_from_this()};
else
return TypePointer();
return TypeResult{""};
}
bool IntegerType::operator==(Type const& _other) const
@ -651,7 +651,7 @@ bigint IntegerType::maxValue() const
return (bigint(1) << m_bits) - 1;
}
TypePointer IntegerType::binaryOperatorResult(Token _operator, TypePointer const& _other) const
TypeResult IntegerType::binaryOperatorResult(Token _operator, TypePointer const& _other) const
{
if (
_other->category() != Category::RationalNumber &&
@ -704,7 +704,7 @@ string FixedPointType::richIdentifier() const
return "t_" + string(isSigned() ? "" : "u") + "fixed" + to_string(m_totalBits) + "x" + to_string(m_fractionalDigits);
}
bool FixedPointType::isImplicitlyConvertibleTo(Type const& _convertTo) const
BoolResult FixedPointType::isImplicitlyConvertibleTo(Type const& _convertTo) const
{
if (_convertTo.category() == category())
{
@ -717,18 +717,18 @@ bool FixedPointType::isImplicitlyConvertibleTo(Type const& _convertTo) const
return false;
}
bool FixedPointType::isExplicitlyConvertibleTo(Type const& _convertTo) const
BoolResult FixedPointType::isExplicitlyConvertibleTo(Type const& _convertTo) const
{
return _convertTo.category() == category() || _convertTo.category() == Category::Integer;
}
TypePointer FixedPointType::unaryOperatorResult(Token _operator) const
TypeResult FixedPointType::unaryOperatorResult(Token _operator) const
{
switch(_operator)
{
case Token::Delete:
// "delete" is ok for all fixed types
return make_shared<TupleType>();
return TypeResult(make_shared<TupleType>());
case Token::Add:
case Token::Sub:
case Token::Inc:
@ -771,7 +771,7 @@ bigint FixedPointType::minIntegerValue() const
return bigint(0);
}
TypePointer FixedPointType::binaryOperatorResult(Token _operator, TypePointer const& _other) const
TypeResult FixedPointType::binaryOperatorResult(Token _operator, TypePointer const& _other) const
{
auto commonType = Type::commonType(shared_from_this(), _other);
@ -957,7 +957,7 @@ tuple<bool, rational> RationalNumberType::isValidLiteral(Literal const& _literal
return make_tuple(true, value);
}
bool RationalNumberType::isImplicitlyConvertibleTo(Type const& _convertTo) const
BoolResult RationalNumberType::isImplicitlyConvertibleTo(Type const& _convertTo) const
{
switch (_convertTo.category())
{
@ -995,7 +995,7 @@ bool RationalNumberType::isImplicitlyConvertibleTo(Type const& _convertTo) const
}
}
bool RationalNumberType::isExplicitlyConvertibleTo(Type const& _convertTo) const
BoolResult RationalNumberType::isExplicitlyConvertibleTo(Type const& _convertTo) const
{
if (isImplicitlyConvertibleTo(_convertTo))
return true;
@ -1008,7 +1008,7 @@ bool RationalNumberType::isExplicitlyConvertibleTo(Type const& _convertTo) const
return false;
}
TypePointer RationalNumberType::unaryOperatorResult(Token _operator) const
TypeResult RationalNumberType::unaryOperatorResult(Token _operator) const
{
rational value;
switch (_operator)
@ -1029,10 +1029,10 @@ TypePointer RationalNumberType::unaryOperatorResult(Token _operator) const
default:
return TypePointer();
}
return make_shared<RationalNumberType>(value);
return TypeResult(make_shared<RationalNumberType>(value));
}
TypePointer RationalNumberType::binaryOperatorResult(Token _operator, TypePointer const& _other) const
TypeResult RationalNumberType::binaryOperatorResult(Token _operator, TypePointer const& _other) const
{
if (_other->category() == Category::Integer || _other->category() == Category::FixedPoint)
{
@ -1214,7 +1214,7 @@ TypePointer RationalNumberType::binaryOperatorResult(Token _operator, TypePointe
if (value.numerator() != 0 && max(mostSignificantBit(abs(value.numerator())), mostSignificantBit(abs(value.denominator()))) > 4096)
return TypePointer();
return make_shared<RationalNumberType>(value);
return TypeResult(make_shared<RationalNumberType>(value));
}
}
@ -1354,7 +1354,7 @@ StringLiteralType::StringLiteralType(Literal const& _literal):
{
}
bool StringLiteralType::isImplicitlyConvertibleTo(Type const& _convertTo) const
BoolResult StringLiteralType::isImplicitlyConvertibleTo(Type const& _convertTo) const
{
if (auto fixedBytes = dynamic_cast<FixedBytesType const*>(&_convertTo))
return size_t(fixedBytes->numBytes()) >= m_value.size();
@ -1409,7 +1409,7 @@ FixedBytesType::FixedBytesType(unsigned _bytes): m_bytes(_bytes)
);
}
bool FixedBytesType::isImplicitlyConvertibleTo(Type const& _convertTo) const
BoolResult FixedBytesType::isImplicitlyConvertibleTo(Type const& _convertTo) const
{
if (_convertTo.category() != category())
return false;
@ -1417,7 +1417,7 @@ bool FixedBytesType::isImplicitlyConvertibleTo(Type const& _convertTo) const
return convertTo.m_bytes >= m_bytes;
}
bool FixedBytesType::isExplicitlyConvertibleTo(Type const& _convertTo) const
BoolResult FixedBytesType::isExplicitlyConvertibleTo(Type const& _convertTo) const
{
return (_convertTo.category() == Category::Integer && numBytes() * 8 == dynamic_cast<IntegerType const&>(_convertTo).numBits()) ||
(_convertTo.category() == Category::Address && numBytes() == 20) ||
@ -1425,18 +1425,18 @@ bool FixedBytesType::isExplicitlyConvertibleTo(Type const& _convertTo) const
_convertTo.category() == category();
}
TypePointer FixedBytesType::unaryOperatorResult(Token _operator) const
TypeResult FixedBytesType::unaryOperatorResult(Token _operator) const
{
// "delete" and "~" is okay for FixedBytesType
if (_operator == Token::Delete)
return make_shared<TupleType>();
return TypeResult(make_shared<TupleType>());
else if (_operator == Token::BitNot)
return shared_from_this();
return TypePointer();
}
TypePointer FixedBytesType::binaryOperatorResult(Token _operator, TypePointer const& _other) const
TypeResult FixedBytesType::binaryOperatorResult(Token _operator, TypePointer const& _other) const
{
if (TokenTraits::isShiftOp(_operator))
{
@ -1452,7 +1452,7 @@ TypePointer FixedBytesType::binaryOperatorResult(Token _operator, TypePointer co
// FixedBytes can be compared and have bitwise operators applied to them
if (TokenTraits::isCompareOp(_operator) || TokenTraits::isBitOp(_operator))
return commonType;
return TypeResult(commonType);
return TypePointer();
}
@ -1486,14 +1486,14 @@ u256 BoolType::literalValue(Literal const* _literal) const
solAssert(false, "Bool type constructed from non-boolean literal.");
}
TypePointer BoolType::unaryOperatorResult(Token _operator) const
TypeResult BoolType::unaryOperatorResult(Token _operator) const
{
if (_operator == Token::Delete)
return make_shared<TupleType>();
return TypeResult(make_shared<TupleType>());
return (_operator == Token::Not) ? shared_from_this() : TypePointer();
}
TypePointer BoolType::binaryOperatorResult(Token _operator, TypePointer const& _other) const
TypeResult BoolType::binaryOperatorResult(Token _operator, TypePointer const& _other) const
{
if (category() != _other->category())
return TypePointer();
@ -1503,7 +1503,7 @@ TypePointer BoolType::binaryOperatorResult(Token _operator, TypePointer const& _
return TypePointer();
}
bool ContractType::isImplicitlyConvertibleTo(Type const& _convertTo) const
BoolResult ContractType::isImplicitlyConvertibleTo(Type const& _convertTo) const
{
if (*this == _convertTo)
return true;
@ -1520,7 +1520,7 @@ bool ContractType::isImplicitlyConvertibleTo(Type const& _convertTo) const
return false;
}
bool ContractType::isExplicitlyConvertibleTo(Type const& _convertTo) const
BoolResult ContractType::isExplicitlyConvertibleTo(Type const& _convertTo) const
{
if (auto const* addressType = dynamic_cast<AddressType const*>(&_convertTo))
return isPayable() || (addressType->stateMutability() < StateMutability::Payable);
@ -1533,14 +1533,14 @@ bool ContractType::isPayable() const
return fallbackFunction && fallbackFunction->isPayable();
}
TypePointer ContractType::unaryOperatorResult(Token _operator) const
TypeResult ContractType::unaryOperatorResult(Token _operator) const
{
if (isSuper())
return TypePointer{};
return _operator == Token::Delete ? make_shared<TupleType>() : TypePointer();
}
TypePointer ReferenceType::unaryOperatorResult(Token _operator) const
TypeResult ReferenceType::unaryOperatorResult(Token _operator) const
{
if (_operator != Token::Delete)
return TypePointer();
@ -1551,7 +1551,7 @@ TypePointer ReferenceType::unaryOperatorResult(Token _operator) const
case DataLocation::CallData:
return TypePointer();
case DataLocation::Memory:
return make_shared<TupleType>();
return TypeResult(make_shared<TupleType>());
case DataLocation::Storage:
return m_isPointer ? TypePointer() : make_shared<TupleType>();
}
@ -1605,7 +1605,7 @@ string ReferenceType::identifierLocationSuffix() const
return id;
}
bool ArrayType::isImplicitlyConvertibleTo(const Type& _convertTo) const
BoolResult ArrayType::isImplicitlyConvertibleTo(const Type& _convertTo) const
{
if (_convertTo.category() != category())
return false;
@ -1645,7 +1645,7 @@ bool ArrayType::isImplicitlyConvertibleTo(const Type& _convertTo) const
}
}
bool ArrayType::isExplicitlyConvertibleTo(const Type& _convertTo) const
BoolResult ArrayType::isExplicitlyConvertibleTo(const Type& _convertTo) const
{
if (isImplicitlyConvertibleTo(_convertTo))
return true;
@ -2006,7 +2006,7 @@ vector<tuple<VariableDeclaration const*, u256, unsigned>> ContractType::stateVar
return variablesAndOffsets;
}
bool StructType::isImplicitlyConvertibleTo(const Type& _convertTo) const
BoolResult StructType::isImplicitlyConvertibleTo(const Type& _convertTo) const
{
if (_convertTo.category() != category())
return false;
@ -2249,7 +2249,7 @@ bool StructType::recursive() const
return *m_recursive;
}
TypePointer EnumType::unaryOperatorResult(Token _operator) const
TypeResult EnumType::unaryOperatorResult(Token _operator) const
{
return _operator == Token::Delete ? make_shared<TupleType>() : TypePointer();
}
@ -2291,7 +2291,7 @@ size_t EnumType::numberOfMembers() const
return m_enum.members().size();
};
bool EnumType::isExplicitlyConvertibleTo(Type const& _convertTo) const
BoolResult EnumType::isExplicitlyConvertibleTo(Type const& _convertTo) const
{
return _convertTo == *this || _convertTo.category() == Category::Integer;
}
@ -2308,7 +2308,7 @@ unsigned EnumType::memberValue(ASTString const& _member) const
solAssert(false, "Requested unknown enum value " + _member);
}
bool TupleType::isImplicitlyConvertibleTo(Type const& _other) const
BoolResult TupleType::isImplicitlyConvertibleTo(Type const& _other) const
{
if (auto tupleType = dynamic_cast<TupleType const*>(&_other))
{
@ -2648,14 +2648,14 @@ bool FunctionType::operator==(Type const& _other) const
return true;
}
bool FunctionType::isExplicitlyConvertibleTo(Type const& _convertTo) const
BoolResult FunctionType::isExplicitlyConvertibleTo(Type const& _convertTo) const
{
if (m_kind == Kind::External && _convertTo == AddressType::address())
return true;
return _convertTo.category() == category();
}
bool FunctionType::isImplicitlyConvertibleTo(Type const& _convertTo) const
BoolResult FunctionType::isImplicitlyConvertibleTo(Type const& _convertTo) const
{
if (_convertTo.category() != category())
return false;
@ -2680,14 +2680,14 @@ bool FunctionType::isImplicitlyConvertibleTo(Type const& _convertTo) const
return true;
}
TypePointer FunctionType::unaryOperatorResult(Token _operator) const
TypeResult FunctionType::unaryOperatorResult(Token _operator) const
{
if (_operator == Token::Delete)
return make_shared<TupleType>();
return TypeResult(make_shared<TupleType>());
return TypePointer();
}
TypePointer FunctionType::binaryOperatorResult(Token _operator, TypePointer const& _other) const
TypeResult FunctionType::binaryOperatorResult(Token _operator, TypePointer const& _other) const
{
if (_other->category() != category() || !(_operator == Token::Equal || _operator == Token::NotEqual))
return TypePointer();

View File

@ -29,6 +29,7 @@
#include <libdevcore/Common.h>
#include <libdevcore/CommonIO.h>
#include <libdevcore/Result.h>
#include <boost/noncopyable.hpp>
#include <boost/rational.hpp>
@ -50,6 +51,8 @@ using TypePointer = std::shared_ptr<Type const>;
using FunctionTypePointer = std::shared_ptr<FunctionType const>;
using TypePointers = std::vector<TypePointer>;
using rational = boost::rational<dev::bigint>;
using TypeResult = Result<TypePointer>;
using BoolResult = Result<bool>;
inline rational makeRational(bigint const& _numerator, bigint const& _denominator)
{
@ -63,6 +66,7 @@ inline rational makeRational(bigint const& _numerator, bigint const& _denominato
enum class DataLocation { Storage, CallData, Memory };
/**
* Helper class to compute storage offsets of members of structs and contracts.
*/
@ -189,19 +193,19 @@ public:
/// @returns an escaped identifier (will not contain any parenthesis or commas)
static std::string escapeIdentifier(std::string const& _identifier);
virtual bool isImplicitlyConvertibleTo(Type const& _other) const { return *this == _other; }
virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const
virtual BoolResult isImplicitlyConvertibleTo(Type const& _other) const { return *this == _other; }
virtual BoolResult isExplicitlyConvertibleTo(Type const& _convertTo) const
{
return isImplicitlyConvertibleTo(_convertTo);
}
/// @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) const { return TypePointer(); }
virtual TypeResult unaryOperatorResult(Token) const { return TypePointer(); }
/// @returns the resulting type of applying the given binary operator or an empty pointer if
/// this is not possible.
/// The default implementation allows comparison operators if a common type exists
virtual TypePointer binaryOperatorResult(Token _operator, TypePointer const& _other) const
virtual TypeResult binaryOperatorResult(Token _operator, TypePointer const& _other) const
{
return TokenTraits::isCompareOp(_operator) ? commonType(shared_from_this(), _other) : TypePointer();
}
@ -336,10 +340,10 @@ public:
explicit AddressType(StateMutability _stateMutability);
std::string richIdentifier() const override;
bool isImplicitlyConvertibleTo(Type const& _other) const override;
bool isExplicitlyConvertibleTo(Type const& _convertTo) const override;
TypePointer unaryOperatorResult(Token _operator) const override;
TypePointer binaryOperatorResult(Token _operator, TypePointer const& _other) const override;
BoolResult isImplicitlyConvertibleTo(Type const& _other) const override;
BoolResult isExplicitlyConvertibleTo(Type const& _convertTo) const override;
TypeResult unaryOperatorResult(Token _operator) const override;
TypeResult binaryOperatorResult(Token _operator, TypePointer const& _other) const override;
bool operator==(Type const& _other) const override;
@ -381,10 +385,10 @@ public:
explicit IntegerType(unsigned _bits, Modifier _modifier = Modifier::Unsigned);
std::string richIdentifier() const override;
bool isImplicitlyConvertibleTo(Type const& _convertTo) const override;
bool isExplicitlyConvertibleTo(Type const& _convertTo) const override;
TypePointer unaryOperatorResult(Token _operator) const override;
TypePointer binaryOperatorResult(Token _operator, TypePointer const& _other) const override;
BoolResult isImplicitlyConvertibleTo(Type const& _convertTo) const override;
BoolResult isExplicitlyConvertibleTo(Type const& _convertTo) const override;
TypeResult unaryOperatorResult(Token _operator) const override;
TypeResult binaryOperatorResult(Token _operator, TypePointer const& _other) const override;
bool operator==(Type const& _other) const override;
@ -423,10 +427,10 @@ public:
explicit FixedPointType(unsigned _totalBits, unsigned _fractionalDigits, Modifier _modifier = Modifier::Unsigned);
std::string richIdentifier() const override;
bool isImplicitlyConvertibleTo(Type const& _convertTo) const override;
bool isExplicitlyConvertibleTo(Type const& _convertTo) const override;
TypePointer unaryOperatorResult(Token _operator) const override;
TypePointer binaryOperatorResult(Token _operator, TypePointer const& _other) const override;
BoolResult isImplicitlyConvertibleTo(Type const& _convertTo) const override;
BoolResult isExplicitlyConvertibleTo(Type const& _convertTo) const override;
TypeResult unaryOperatorResult(Token _operator) const override;
TypeResult binaryOperatorResult(Token _operator, TypePointer const& _other) const override;
bool operator==(Type const& _other) const override;
@ -476,11 +480,10 @@ public:
explicit RationalNumberType(rational const& _value, TypePointer const& _compatibleBytesType = TypePointer()):
m_value(_value), m_compatibleBytesType(_compatibleBytesType)
{}
bool isImplicitlyConvertibleTo(Type const& _convertTo) const override;
bool isExplicitlyConvertibleTo(Type const& _convertTo) const override;
TypePointer unaryOperatorResult(Token _operator) const override;
TypePointer binaryOperatorResult(Token _operator, TypePointer const& _other) const override;
BoolResult isImplicitlyConvertibleTo(Type const& _convertTo) const override;
BoolResult isExplicitlyConvertibleTo(Type const& _convertTo) const override;
TypeResult unaryOperatorResult(Token _operator) const override;
TypeResult binaryOperatorResult(Token _operator, TypePointer const& _other) const override;
std::string richIdentifier() const override;
bool operator==(Type const& _other) const override;
@ -536,8 +539,8 @@ public:
explicit StringLiteralType(Literal const& _literal);
bool isImplicitlyConvertibleTo(Type const& _convertTo) const override;
TypePointer binaryOperatorResult(Token, TypePointer const&) const override
BoolResult isImplicitlyConvertibleTo(Type const& _convertTo) const override;
TypeResult binaryOperatorResult(Token, TypePointer const&) const override
{
return TypePointer();
}
@ -570,12 +573,12 @@ public:
explicit FixedBytesType(unsigned _bytes);
bool isImplicitlyConvertibleTo(Type const& _convertTo) const override;
bool isExplicitlyConvertibleTo(Type const& _convertTo) const override;
BoolResult isImplicitlyConvertibleTo(Type const& _convertTo) const override;
BoolResult isExplicitlyConvertibleTo(Type const& _convertTo) const override;
std::string richIdentifier() const override;
bool operator==(Type const& _other) const override;
TypePointer unaryOperatorResult(Token _operator) const override;
TypePointer binaryOperatorResult(Token _operator, TypePointer const& _other) const override;
TypeResult unaryOperatorResult(Token _operator) const override;
TypeResult binaryOperatorResult(Token _operator, TypePointer const& _other) const override;
unsigned calldataEncodedSize(bool _padded) const override { return _padded && m_bytes > 0 ? 32 : m_bytes; }
unsigned storageBytes() const override { return m_bytes; }
@ -601,8 +604,8 @@ public:
BoolType() {}
Category category() const override { return Category::Bool; }
std::string richIdentifier() const override { return "t_bool"; }
TypePointer unaryOperatorResult(Token _operator) const override;
TypePointer binaryOperatorResult(Token _operator, TypePointer const& _other) const override;
TypeResult unaryOperatorResult(Token _operator) const override;
TypeResult binaryOperatorResult(Token _operator, TypePointer const& _other) const override;
unsigned calldataEncodedSize(bool _padded) const override{ return _padded ? 32 : 1; }
unsigned storageBytes() const override { return 1; }
@ -624,8 +627,8 @@ public:
explicit ReferenceType(DataLocation _location): m_location(_location) {}
DataLocation location() const { return m_location; }
TypePointer unaryOperatorResult(Token _operator) const override;
TypePointer binaryOperatorResult(Token, TypePointer const&) const override
TypeResult unaryOperatorResult(Token _operator) const override;
TypeResult binaryOperatorResult(Token, TypePointer const&) const override
{
return TypePointer();
}
@ -702,8 +705,8 @@ public:
m_length(_length)
{}
bool isImplicitlyConvertibleTo(Type const& _convertTo) const override;
bool isExplicitlyConvertibleTo(Type const& _convertTo) const override;
BoolResult isImplicitlyConvertibleTo(Type const& _convertTo) const override;
BoolResult isExplicitlyConvertibleTo(Type const& _convertTo) const override;
std::string richIdentifier() const override;
bool operator==(const Type& _other) const override;
unsigned calldataEncodedSize(bool _padded) const override;
@ -757,10 +760,10 @@ public:
explicit ContractType(ContractDefinition const& _contract, bool _super = false):
m_contract(_contract), m_super(_super) {}
/// Contracts can be implicitly converted only to base contracts.
bool isImplicitlyConvertibleTo(Type const& _convertTo) const override;
BoolResult isImplicitlyConvertibleTo(Type const& _convertTo) const override;
/// Contracts can only be explicitly converted to address types and base contracts.
bool isExplicitlyConvertibleTo(Type const& _convertTo) const override;
TypePointer unaryOperatorResult(Token _operator) const override;
BoolResult isExplicitlyConvertibleTo(Type const& _convertTo) const override;
TypeResult unaryOperatorResult(Token _operator) const override;
std::string richIdentifier() const override;
bool operator==(Type const& _other) const override;
unsigned calldataEncodedSize(bool _padded ) const override
@ -821,7 +824,7 @@ public:
Category category() const override { return Category::Struct; }
explicit StructType(StructDefinition const& _struct, DataLocation _location = DataLocation::Storage):
ReferenceType(_location), m_struct(_struct) {}
bool isImplicitlyConvertibleTo(const Type& _convertTo) const override;
BoolResult isImplicitlyConvertibleTo(const Type& _convertTo) const override;
std::string richIdentifier() const override;
bool operator==(Type const& _other) const override;
unsigned calldataEncodedSize(bool _padded) const override;
@ -876,7 +879,7 @@ class EnumType: public Type
public:
Category category() const override { return Category::Enum; }
explicit EnumType(EnumDefinition const& _enum): m_enum(_enum) {}
TypePointer unaryOperatorResult(Token _operator) const override;
TypeResult unaryOperatorResult(Token _operator) const override;
std::string richIdentifier() const override;
bool operator==(Type const& _other) const override;
unsigned calldataEncodedSize(bool _padded) const override
@ -889,7 +892,7 @@ public:
std::string canonicalName() const override;
bool isValueType() const override { return true; }
bool isExplicitlyConvertibleTo(Type const& _convertTo) const override;
BoolResult isExplicitlyConvertibleTo(Type const& _convertTo) const override;
TypePointer encodingType() const override
{
return std::make_shared<IntegerType>(8 * int(storageBytes()));
@ -917,10 +920,10 @@ class TupleType: public Type
public:
Category category() const override { return Category::Tuple; }
explicit TupleType(std::vector<TypePointer> const& _types = std::vector<TypePointer>()): m_components(_types) {}
bool isImplicitlyConvertibleTo(Type const& _other) const override;
BoolResult isImplicitlyConvertibleTo(Type const& _other) const override;
std::string richIdentifier() const override;
bool operator==(Type const& _other) const override;
TypePointer binaryOperatorResult(Token, TypePointer const&) const override { return TypePointer(); }
TypeResult binaryOperatorResult(Token, TypePointer const&) const override { return TypePointer(); }
std::string toString(bool) const override;
bool canBeStored() const override { return false; }
u256 storageSize() const override;
@ -1065,10 +1068,10 @@ public:
std::string richIdentifier() const override;
bool operator==(Type const& _other) const override;
bool isImplicitlyConvertibleTo(Type const& _convertTo) const override;
bool isExplicitlyConvertibleTo(Type const& _convertTo) const override;
TypePointer unaryOperatorResult(Token _operator) const override;
TypePointer binaryOperatorResult(Token, TypePointer const&) const override;
BoolResult isImplicitlyConvertibleTo(Type const& _convertTo) const override;
BoolResult isExplicitlyConvertibleTo(Type const& _convertTo) const override;
TypeResult unaryOperatorResult(Token _operator) const override;
TypeResult binaryOperatorResult(Token, TypePointer const&) const override;
std::string canonicalName() const override;
std::string toString(bool _short) const override;
unsigned calldataEncodedSize(bool _padded) const override;
@ -1197,7 +1200,7 @@ public:
std::string toString(bool _short) const override;
std::string canonicalName() const override;
bool canLiveOutsideStorage() const override { return false; }
TypePointer binaryOperatorResult(Token, TypePointer const&) const override { return TypePointer(); }
TypeResult binaryOperatorResult(Token, TypePointer const&) const override { return TypePointer(); }
TypePointer encodingType() const override
{
return std::make_shared<IntegerType>(256);
@ -1230,7 +1233,7 @@ public:
explicit TypeType(TypePointer const& _actualType): m_actualType(_actualType) {}
TypePointer const& actualType() const { return m_actualType; }
TypePointer binaryOperatorResult(Token, TypePointer const&) const override { return TypePointer(); }
TypeResult binaryOperatorResult(Token, TypePointer const&) const override { return TypePointer(); }
std::string richIdentifier() const override;
bool operator==(Type const& _other) const override;
bool canBeStored() const override { return false; }
@ -1255,7 +1258,7 @@ public:
Category category() const override { return Category::Modifier; }
explicit ModifierType(ModifierDefinition const& _modifier);
TypePointer binaryOperatorResult(Token, TypePointer const&) const override { return TypePointer(); }
TypeResult binaryOperatorResult(Token, TypePointer const&) const override { return TypePointer(); }
bool canBeStored() const override { return false; }
u256 storageSize() const override;
bool canLiveOutsideStorage() const override { return false; }
@ -1281,7 +1284,7 @@ public:
explicit ModuleType(SourceUnit const& _source): m_sourceUnit(_source) {}
TypePointer binaryOperatorResult(Token, TypePointer const&) const override { return TypePointer(); }
TypeResult binaryOperatorResult(Token, TypePointer const&) const override { return TypePointer(); }
std::string richIdentifier() const override;
bool operator==(Type const& _other) const override;
bool canBeStored() const override { return false; }
@ -1308,7 +1311,7 @@ public:
explicit MagicType(Kind _kind): m_kind(_kind) {}
TypePointer binaryOperatorResult(Token, TypePointer const&) const override
TypeResult binaryOperatorResult(Token, TypePointer const&) const override
{
return TypePointer();
}
@ -1339,9 +1342,9 @@ public:
Category category() const override { return Category::InaccessibleDynamic; }
std::string richIdentifier() const override { return "t_inaccessible"; }
bool isImplicitlyConvertibleTo(Type const&) const override { return false; }
bool isExplicitlyConvertibleTo(Type const&) const override { return false; }
TypePointer binaryOperatorResult(Token, TypePointer const&) const override { return TypePointer(); }
BoolResult isImplicitlyConvertibleTo(Type const&) const override { return false; }
BoolResult isExplicitlyConvertibleTo(Type const&) const override { return false; }
TypeResult binaryOperatorResult(Token, TypePointer const&) const override { return TypePointer(); }
unsigned calldataEncodedSize(bool _padded) const override { (void)_padded; return 32; }
bool canBeStored() const override { return false; }
bool canLiveOutsideStorage() const override { return false; }