mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
libsolidity: Introducing TypeProvider API, for clear type system ownership.
This commit is contained in:
committed by
chriseth
parent
862d798047
commit
bf43eebea9
+22
-21
@@ -24,6 +24,7 @@
|
||||
|
||||
#include <libsolidity/ast/ASTVisitor.h>
|
||||
#include <libsolidity/ast/AST_accept.h>
|
||||
#include <libsolidity/ast/TypeProvider.h>
|
||||
#include <libdevcore/Keccak256.h>
|
||||
|
||||
#include <boost/algorithm/string.hpp>
|
||||
@@ -105,7 +106,7 @@ ImportAnnotation& ImportDirective::annotation() const
|
||||
TypePointer ImportDirective::type() const
|
||||
{
|
||||
solAssert(!!annotation().sourceUnit, "");
|
||||
return make_shared<ModuleType>(*annotation().sourceUnit);
|
||||
return TypeProvider::moduleType(*annotation().sourceUnit);
|
||||
}
|
||||
|
||||
map<FixedHash<4>, FunctionTypePointer> ContractDefinition::interfaceFunctions() const
|
||||
@@ -188,10 +189,10 @@ vector<pair<FixedHash<4>, FunctionTypePointer>> const& ContractDefinition::inter
|
||||
vector<FunctionTypePointer> functions;
|
||||
for (FunctionDefinition const* f: contract->definedFunctions())
|
||||
if (f->isPartOfExternalInterface())
|
||||
functions.push_back(make_shared<FunctionType>(*f, false));
|
||||
functions.push_back(TypeProvider::functionType(*f, false));
|
||||
for (VariableDeclaration const* v: contract->stateVariables())
|
||||
if (v->isPartOfExternalInterface())
|
||||
functions.push_back(make_shared<FunctionType>(*v));
|
||||
functions.push_back(TypeProvider::functionType(*v));
|
||||
for (FunctionTypePointer const& fun: functions)
|
||||
{
|
||||
if (!fun->interfaceFunctionType())
|
||||
@@ -246,7 +247,7 @@ vector<Declaration const*> const& ContractDefinition::inheritableMembers() const
|
||||
|
||||
TypePointer ContractDefinition::type() const
|
||||
{
|
||||
return make_shared<TypeType>(make_shared<ContractType>(*this));
|
||||
return TypeProvider::typeType(TypeProvider::contractType(*this));
|
||||
}
|
||||
|
||||
ContractDefinitionAnnotation& ContractDefinition::annotation() const
|
||||
@@ -265,7 +266,7 @@ TypeNameAnnotation& TypeName::annotation() const
|
||||
|
||||
TypePointer StructDefinition::type() const
|
||||
{
|
||||
return make_shared<TypeType>(make_shared<StructType>(*this));
|
||||
return TypeProvider::typeType(TypeProvider::structType(*this));
|
||||
}
|
||||
|
||||
TypeDeclarationAnnotation& StructDefinition::annotation() const
|
||||
@@ -279,12 +280,12 @@ TypePointer EnumValue::type() const
|
||||
{
|
||||
auto parentDef = dynamic_cast<EnumDefinition const*>(scope());
|
||||
solAssert(parentDef, "Enclosing Scope of EnumValue was not set");
|
||||
return make_shared<EnumType>(*parentDef);
|
||||
return TypeProvider::enumType(*parentDef);
|
||||
}
|
||||
|
||||
TypePointer EnumDefinition::type() const
|
||||
{
|
||||
return make_shared<TypeType>(make_shared<EnumType>(*this));
|
||||
return TypeProvider::typeType(TypeProvider::enumType(*this));
|
||||
}
|
||||
|
||||
TypeDeclarationAnnotation& EnumDefinition::annotation() const
|
||||
@@ -312,7 +313,7 @@ FunctionTypePointer FunctionDefinition::functionType(bool _internal) const
|
||||
case Declaration::Visibility::Private:
|
||||
case Declaration::Visibility::Internal:
|
||||
case Declaration::Visibility::Public:
|
||||
return make_shared<FunctionType>(*this, _internal);
|
||||
return TypeProvider::functionType(*this, _internal);
|
||||
case Declaration::Visibility::External:
|
||||
return {};
|
||||
}
|
||||
@@ -328,7 +329,7 @@ FunctionTypePointer FunctionDefinition::functionType(bool _internal) const
|
||||
return {};
|
||||
case Declaration::Visibility::Public:
|
||||
case Declaration::Visibility::External:
|
||||
return make_shared<FunctionType>(*this, _internal);
|
||||
return TypeProvider::functionType(*this, _internal);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -339,12 +340,12 @@ FunctionTypePointer FunctionDefinition::functionType(bool _internal) const
|
||||
TypePointer FunctionDefinition::type() const
|
||||
{
|
||||
solAssert(visibility() != Declaration::Visibility::External, "");
|
||||
return make_shared<FunctionType>(*this);
|
||||
return TypeProvider::functionType(*this);
|
||||
}
|
||||
|
||||
string FunctionDefinition::externalSignature() const
|
||||
{
|
||||
return FunctionType(*this).externalSignature();
|
||||
return TypeProvider::functionType(*this)->externalSignature();
|
||||
}
|
||||
|
||||
FunctionDefinitionAnnotation& FunctionDefinition::annotation() const
|
||||
@@ -356,7 +357,7 @@ FunctionDefinitionAnnotation& FunctionDefinition::annotation() const
|
||||
|
||||
TypePointer ModifierDefinition::type() const
|
||||
{
|
||||
return make_shared<ModifierType>(*this);
|
||||
return TypeProvider::modifierType(*this);
|
||||
}
|
||||
|
||||
ModifierDefinitionAnnotation& ModifierDefinition::annotation() const
|
||||
@@ -368,15 +369,15 @@ ModifierDefinitionAnnotation& ModifierDefinition::annotation() const
|
||||
|
||||
TypePointer EventDefinition::type() const
|
||||
{
|
||||
return make_shared<FunctionType>(*this);
|
||||
return TypeProvider::functionType(*this);
|
||||
}
|
||||
|
||||
FunctionTypePointer EventDefinition::functionType(bool _internal) const
|
||||
{
|
||||
if (_internal)
|
||||
return make_shared<FunctionType>(*this);
|
||||
return TypeProvider::functionType(*this);
|
||||
else
|
||||
return {};
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
EventDefinitionAnnotation& EventDefinition::annotation() const
|
||||
@@ -508,8 +509,8 @@ bool VariableDeclaration::hasReferenceOrMappingType() const
|
||||
{
|
||||
solAssert(typeName(), "");
|
||||
solAssert(typeName()->annotation().type, "Can only be called after reference resolution");
|
||||
TypePointer const& type = typeName()->annotation().type;
|
||||
return type->category() == Type::Category::Mapping || dynamic_cast<ReferenceType const*>(type.get());
|
||||
Type const* type = typeName()->annotation().type;
|
||||
return type->category() == Type::Category::Mapping || dynamic_cast<ReferenceType const*>(type);
|
||||
}
|
||||
|
||||
set<VariableDeclaration::Location> VariableDeclaration::allowedDataLocations() const
|
||||
@@ -557,21 +558,21 @@ TypePointer VariableDeclaration::type() const
|
||||
FunctionTypePointer VariableDeclaration::functionType(bool _internal) const
|
||||
{
|
||||
if (_internal)
|
||||
return {};
|
||||
return nullptr;
|
||||
switch (visibility())
|
||||
{
|
||||
case Declaration::Visibility::Default:
|
||||
solAssert(false, "visibility() should not return Default");
|
||||
case Declaration::Visibility::Private:
|
||||
case Declaration::Visibility::Internal:
|
||||
return {};
|
||||
return nullptr;
|
||||
case Declaration::Visibility::Public:
|
||||
case Declaration::Visibility::External:
|
||||
return make_shared<FunctionType>(*this);
|
||||
return TypeProvider::functionType(*this);
|
||||
}
|
||||
|
||||
// To make the compiler happy
|
||||
return {};
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
VariableDeclarationAnnotation& VariableDeclaration::annotation() const
|
||||
|
||||
@@ -848,8 +848,9 @@ private:
|
||||
class MagicVariableDeclaration: public Declaration
|
||||
{
|
||||
public:
|
||||
MagicVariableDeclaration(ASTString const& _name, std::shared_ptr<Type const> const& _type):
|
||||
MagicVariableDeclaration(ASTString const& _name, Type const* _type):
|
||||
Declaration(SourceLocation(), std::make_shared<ASTString>(_name)), m_type(_type) {}
|
||||
|
||||
void accept(ASTVisitor&) override
|
||||
{
|
||||
solAssert(false, "MagicVariableDeclaration used inside real AST.");
|
||||
@@ -859,15 +860,15 @@ public:
|
||||
solAssert(false, "MagicVariableDeclaration used inside real AST.");
|
||||
}
|
||||
|
||||
FunctionTypePointer functionType(bool) const override
|
||||
FunctionType const* functionType(bool) const override
|
||||
{
|
||||
solAssert(m_type->category() == Type::Category::Function, "");
|
||||
return std::dynamic_pointer_cast<FunctionType const>(m_type);
|
||||
return dynamic_cast<FunctionType const*>(m_type);
|
||||
}
|
||||
TypePointer type() const override { return m_type; }
|
||||
|
||||
private:
|
||||
std::shared_ptr<Type const> m_type;
|
||||
Type const* m_type;
|
||||
};
|
||||
|
||||
/// Types
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace solidity
|
||||
{
|
||||
|
||||
class Type;
|
||||
using TypePointer = std::shared_ptr<Type const>;
|
||||
using TypePointer = Type const*;
|
||||
|
||||
struct ASTAnnotation
|
||||
{
|
||||
@@ -122,7 +122,7 @@ struct ModifierDefinitionAnnotation: ASTAnnotation, DocumentedAnnotation
|
||||
struct VariableDeclarationAnnotation: ASTAnnotation
|
||||
{
|
||||
/// Type of variable (type of identifier referencing this variable).
|
||||
TypePointer type;
|
||||
TypePointer type = nullptr;
|
||||
};
|
||||
|
||||
struct StatementAnnotation: ASTAnnotation, DocumentedAnnotation
|
||||
@@ -155,7 +155,7 @@ struct TypeNameAnnotation: ASTAnnotation
|
||||
{
|
||||
/// Type declared by this type name, i.e. type of a variable where this type name is used.
|
||||
/// Set during reference resolution stage.
|
||||
TypePointer type;
|
||||
TypePointer type = nullptr;
|
||||
};
|
||||
|
||||
struct UserDefinedTypeNameAnnotation: TypeNameAnnotation
|
||||
@@ -170,7 +170,7 @@ struct UserDefinedTypeNameAnnotation: TypeNameAnnotation
|
||||
struct ExpressionAnnotation: ASTAnnotation
|
||||
{
|
||||
/// Inferred type of the expression.
|
||||
TypePointer type;
|
||||
TypePointer type = nullptr;
|
||||
/// Whether the expression is a constant variable
|
||||
bool isConstant = false;
|
||||
/// Whether the expression is pure, i.e. compile-time constant.
|
||||
@@ -203,7 +203,7 @@ struct BinaryOperationAnnotation: ExpressionAnnotation
|
||||
{
|
||||
/// The common type that is used for the operation, not necessarily the result type (which
|
||||
/// e.g. for comparisons is bool).
|
||||
TypePointer commonType;
|
||||
TypePointer commonType = nullptr;
|
||||
};
|
||||
|
||||
enum class FunctionCallKind
|
||||
|
||||
@@ -57,7 +57,7 @@ class Type;
|
||||
struct FuncCallArguments
|
||||
{
|
||||
/// Types of arguments
|
||||
std::vector<std::shared_ptr<Type const>> types;
|
||||
std::vector<Type const*> types;
|
||||
/// Names of the arguments if given, otherwise unset
|
||||
std::vector<ASTPointer<ASTString>> names;
|
||||
|
||||
|
||||
@@ -0,0 +1,423 @@
|
||||
/*
|
||||
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/>.
|
||||
*/
|
||||
|
||||
#include <libsolidity/ast/AST.h>
|
||||
#include <libsolidity/ast/TypeProvider.h>
|
||||
#include <libdevcore/make_array.h>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace dev;
|
||||
using namespace solidity;
|
||||
|
||||
template <size_t... N>
|
||||
constexpr array<IntegerType, sizeof...(N)> createIntegerTypes(IntegerType::Modifier _modifier, index_sequence<N...>)
|
||||
{
|
||||
return make_array<IntegerType>(IntegerType((static_cast<unsigned>(N) + 1) * 8, _modifier)...);
|
||||
}
|
||||
|
||||
template <size_t... N>
|
||||
constexpr array<FixedBytesType, sizeof...(N)> createFixedBytesTypes(index_sequence<N...>)
|
||||
{
|
||||
return make_array<FixedBytesType>(FixedBytesType(static_cast<unsigned>(N) + 1)...);
|
||||
}
|
||||
|
||||
BoolType const TypeProvider::m_boolType{};
|
||||
InaccessibleDynamicType const TypeProvider::m_inaccessibleDynamicType{};
|
||||
ArrayType const TypeProvider::m_bytesStorageType{DataLocation::Storage, false};
|
||||
ArrayType const TypeProvider::m_bytesMemoryType{DataLocation::Memory, false};
|
||||
ArrayType const TypeProvider::m_stringStorageType{DataLocation::Storage, true};
|
||||
ArrayType const TypeProvider::m_stringMemoryType{DataLocation::Memory, true};
|
||||
TupleType const TypeProvider::m_emptyTupleType{};
|
||||
AddressType const TypeProvider::m_payableAddressType{StateMutability::Payable};
|
||||
AddressType const TypeProvider::m_addressType{StateMutability::NonPayable};
|
||||
array<IntegerType, 32> const TypeProvider::m_intM{createIntegerTypes(IntegerType::Modifier::Signed, make_index_sequence<32>{})};
|
||||
array<IntegerType, 32> const TypeProvider::m_uintM{createIntegerTypes(IntegerType::Modifier::Unsigned, make_index_sequence<32>{})};
|
||||
array<FixedBytesType, 32> const TypeProvider::m_bytesM{createFixedBytesTypes(make_index_sequence<32>{})};
|
||||
array<MagicType, 4> const TypeProvider::m_magicTypes{
|
||||
MagicType{MagicType::Kind::Block},
|
||||
MagicType{MagicType::Kind::Message},
|
||||
MagicType{MagicType::Kind::Transaction},
|
||||
MagicType{MagicType::Kind::ABI}
|
||||
// MetaType is stored separately
|
||||
};
|
||||
|
||||
inline void clearCache(Type const& type)
|
||||
{
|
||||
type.clearCache();
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
inline void clearCache(Type const& type, Args&... moreTypes)
|
||||
{
|
||||
clearCache(type);
|
||||
clearCache(moreTypes...);
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
inline void clearAllCaches(Container& container)
|
||||
{
|
||||
for_each(begin(container), end(container), [](Type const& t) { t.clearCache(); });
|
||||
}
|
||||
|
||||
template <typename Container, typename... Args>
|
||||
inline void clearAllCaches(Container& types, Args&... more)
|
||||
{
|
||||
clearAllCaches(types);
|
||||
clearAllCaches(more...);
|
||||
}
|
||||
|
||||
void TypeProvider::reset()
|
||||
{
|
||||
clearCache(
|
||||
m_boolType,
|
||||
m_inaccessibleDynamicType,
|
||||
m_bytesStorageType,
|
||||
m_bytesMemoryType,
|
||||
m_stringStorageType,
|
||||
m_stringMemoryType,
|
||||
m_emptyTupleType,
|
||||
m_payableAddressType,
|
||||
m_addressType
|
||||
);
|
||||
clearAllCaches(instance().m_intM, instance().m_uintM, instance().m_bytesM, instance().m_magicTypes);
|
||||
|
||||
instance().m_generalTypes.clear();
|
||||
instance().m_stringLiteralTypes.clear();
|
||||
instance().m_ufixedMxN.clear();
|
||||
instance().m_fixedMxN.clear();
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
inline T const* TypeProvider::createAndGet(Args&& ... _args)
|
||||
{
|
||||
instance().m_generalTypes.emplace_back(make_unique<T>(std::forward<Args>(_args)...));
|
||||
return static_cast<T const*>(instance().m_generalTypes.back().get());
|
||||
}
|
||||
|
||||
Type const* TypeProvider::fromElementaryTypeName(ElementaryTypeNameToken const& _type)
|
||||
{
|
||||
solAssert(
|
||||
TokenTraits::isElementaryTypeName(_type.token()),
|
||||
"Expected an elementary type name but got " + _type.toString()
|
||||
);
|
||||
|
||||
unsigned const m = _type.firstNumber();
|
||||
unsigned const n = _type.secondNumber();
|
||||
|
||||
switch (_type.token())
|
||||
{
|
||||
case Token::IntM:
|
||||
return integerType(m, IntegerType::Modifier::Signed);
|
||||
case Token::UIntM:
|
||||
return integerType(m, IntegerType::Modifier::Unsigned);
|
||||
case Token::Byte:
|
||||
return byteType();
|
||||
case Token::BytesM:
|
||||
return fixedBytesType(m);
|
||||
case Token::FixedMxN:
|
||||
return fixedPointType(m, n, FixedPointType::Modifier::Signed);
|
||||
case Token::UFixedMxN:
|
||||
return fixedPointType(m, n, FixedPointType::Modifier::Unsigned);
|
||||
case Token::Int:
|
||||
return integerType(256, IntegerType::Modifier::Signed);
|
||||
case Token::UInt:
|
||||
return integerType(256, IntegerType::Modifier::Unsigned);
|
||||
case Token::Fixed:
|
||||
return fixedPointType(128, 18, FixedPointType::Modifier::Signed);
|
||||
case Token::UFixed:
|
||||
return fixedPointType(128, 18, FixedPointType::Modifier::Unsigned);
|
||||
case Token::Address:
|
||||
return addressType();
|
||||
case Token::Bool:
|
||||
return boolType();
|
||||
case Token::Bytes:
|
||||
return bytesType();
|
||||
case Token::String:
|
||||
return stringType();
|
||||
default:
|
||||
solAssert(
|
||||
false,
|
||||
"Unable to convert elementary typename " + _type.toString() + " to type."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
TypePointer TypeProvider::fromElementaryTypeName(string const& _name)
|
||||
{
|
||||
vector<string> nameParts;
|
||||
boost::split(nameParts, _name, boost::is_any_of(" "));
|
||||
solAssert(nameParts.size() == 1 || nameParts.size() == 2, "Cannot parse elementary type: " + _name);
|
||||
|
||||
Token token;
|
||||
unsigned short firstNum, secondNum;
|
||||
tie(token, firstNum, secondNum) = TokenTraits::fromIdentifierOrKeyword(nameParts[0]);
|
||||
|
||||
auto t = fromElementaryTypeName(ElementaryTypeNameToken(token, firstNum, secondNum));
|
||||
if (auto* ref = dynamic_cast<ReferenceType const*>(t))
|
||||
{
|
||||
DataLocation location = DataLocation::Storage;
|
||||
if (nameParts.size() == 2)
|
||||
{
|
||||
if (nameParts[1] == "storage")
|
||||
location = DataLocation::Storage;
|
||||
else if (nameParts[1] == "calldata")
|
||||
location = DataLocation::CallData;
|
||||
else if (nameParts[1] == "memory")
|
||||
location = DataLocation::Memory;
|
||||
else
|
||||
solAssert(false, "Unknown data location: " + nameParts[1]);
|
||||
}
|
||||
return withLocation(ref, location, true);
|
||||
}
|
||||
else if (t->category() == Type::Category::Address)
|
||||
{
|
||||
if (nameParts.size() == 2)
|
||||
{
|
||||
if (nameParts[1] == "payable")
|
||||
return payableAddressType();
|
||||
else
|
||||
solAssert(false, "Invalid state mutability for address type: " + nameParts[1]);
|
||||
}
|
||||
return addressType();
|
||||
}
|
||||
else
|
||||
{
|
||||
solAssert(nameParts.size() == 1, "Storage location suffix only allowed for reference types");
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
TypePointer TypeProvider::forLiteral(Literal const& _literal)
|
||||
{
|
||||
switch (_literal.token())
|
||||
{
|
||||
case Token::TrueLiteral:
|
||||
case Token::FalseLiteral:
|
||||
return boolType();
|
||||
case Token::Number:
|
||||
return rationalNumberType(_literal);
|
||||
case Token::StringLiteral:
|
||||
return stringLiteralType(_literal.value());
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
RationalNumberType const* TypeProvider::rationalNumberType(Literal const& _literal)
|
||||
{
|
||||
solAssert(_literal.token() == Token::Number, "");
|
||||
std::tuple<bool, rational> validLiteral = RationalNumberType::isValidLiteral(_literal);
|
||||
if (std::get<0>(validLiteral))
|
||||
{
|
||||
TypePointer compatibleBytesType = nullptr;
|
||||
if (_literal.isHexNumber())
|
||||
{
|
||||
size_t const digitCount = _literal.valueWithoutUnderscores().length() - 2;
|
||||
if (digitCount % 2 == 0 && (digitCount / 2) <= 32)
|
||||
compatibleBytesType = fixedBytesType(digitCount / 2);
|
||||
}
|
||||
|
||||
return rationalNumberType(std::get<1>(validLiteral), compatibleBytesType);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
StringLiteralType const* TypeProvider::stringLiteralType(string const& literal)
|
||||
{
|
||||
auto i = instance().m_stringLiteralTypes.find(literal);
|
||||
if (i != instance().m_stringLiteralTypes.end())
|
||||
return i->second.get();
|
||||
else
|
||||
return instance().m_stringLiteralTypes.emplace(literal, make_unique<StringLiteralType>(literal)).first->second.get();
|
||||
}
|
||||
|
||||
FixedPointType const* TypeProvider::fixedPointType(unsigned m, unsigned n, FixedPointType::Modifier _modifier)
|
||||
{
|
||||
auto& map = _modifier == FixedPointType::Modifier::Unsigned ? instance().m_ufixedMxN : instance().m_fixedMxN;
|
||||
|
||||
auto i = map.find(make_pair(m, n));
|
||||
if (i != map.end())
|
||||
return i->second.get();
|
||||
|
||||
return map.emplace(
|
||||
make_pair(m, n),
|
||||
make_unique<FixedPointType>(m, n, _modifier)
|
||||
).first->second.get();
|
||||
}
|
||||
|
||||
TupleType const* TypeProvider::tupleType(vector<Type const*> members)
|
||||
{
|
||||
if (members.empty())
|
||||
return &m_emptyTupleType;
|
||||
|
||||
return createAndGet<TupleType>(move(members));
|
||||
}
|
||||
|
||||
ReferenceType const* TypeProvider::withLocation(ReferenceType const* _type, DataLocation _location, bool _isPointer)
|
||||
{
|
||||
if (_type->location() == _location && _type->isPointer() == _isPointer)
|
||||
return _type;
|
||||
|
||||
instance().m_generalTypes.emplace_back(_type->copyForLocation(_location, _isPointer));
|
||||
return static_cast<ReferenceType const*>(instance().m_generalTypes.back().get());
|
||||
}
|
||||
|
||||
FunctionType const* TypeProvider::functionType(FunctionDefinition const& _function, bool _isInternal)
|
||||
{
|
||||
return createAndGet<FunctionType>(_function, _isInternal);
|
||||
}
|
||||
|
||||
FunctionType const* TypeProvider::functionType(VariableDeclaration const& _varDecl)
|
||||
{
|
||||
return createAndGet<FunctionType>(_varDecl);
|
||||
}
|
||||
|
||||
FunctionType const* TypeProvider::functionType(EventDefinition const& _def)
|
||||
{
|
||||
return createAndGet<FunctionType>(_def);
|
||||
}
|
||||
|
||||
FunctionType const* TypeProvider::functionType(FunctionTypeName const& _typeName)
|
||||
{
|
||||
return createAndGet<FunctionType>(_typeName);
|
||||
}
|
||||
|
||||
FunctionType const* TypeProvider::functionType(
|
||||
strings const& _parameterTypes,
|
||||
strings const& _returnParameterTypes,
|
||||
FunctionType::Kind _kind,
|
||||
bool _arbitraryParameters,
|
||||
StateMutability _stateMutability
|
||||
)
|
||||
{
|
||||
return createAndGet<FunctionType>(
|
||||
_parameterTypes, _returnParameterTypes,
|
||||
_kind, _arbitraryParameters, _stateMutability
|
||||
);
|
||||
}
|
||||
|
||||
FunctionType const* TypeProvider::functionType(
|
||||
TypePointers const& _parameterTypes,
|
||||
TypePointers const& _returnParameterTypes,
|
||||
strings _parameterNames,
|
||||
strings _returnParameterNames,
|
||||
FunctionType::Kind _kind,
|
||||
bool _arbitraryParameters,
|
||||
StateMutability _stateMutability,
|
||||
Declaration const* _declaration,
|
||||
bool _gasSet,
|
||||
bool _valueSet,
|
||||
bool _bound
|
||||
)
|
||||
{
|
||||
return createAndGet<FunctionType>(
|
||||
_parameterTypes,
|
||||
_returnParameterTypes,
|
||||
_parameterNames,
|
||||
_returnParameterNames,
|
||||
_kind,
|
||||
_arbitraryParameters,
|
||||
_stateMutability,
|
||||
_declaration,
|
||||
_gasSet,
|
||||
_valueSet,
|
||||
_bound
|
||||
);
|
||||
}
|
||||
|
||||
RationalNumberType const* TypeProvider::rationalNumberType(rational const& _value, Type const* _compatibleBytesType)
|
||||
{
|
||||
return createAndGet<RationalNumberType>(_value, _compatibleBytesType);
|
||||
}
|
||||
|
||||
ArrayType const* TypeProvider::arrayType(DataLocation _location, bool _isString)
|
||||
{
|
||||
if (_isString)
|
||||
{
|
||||
if (_location == DataLocation::Storage)
|
||||
return stringType();
|
||||
if (_location == DataLocation::Memory)
|
||||
return stringMemoryType();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_location == DataLocation::Storage)
|
||||
return bytesType();
|
||||
if (_location == DataLocation::Memory)
|
||||
return bytesMemoryType();
|
||||
}
|
||||
return createAndGet<ArrayType>(_location, _isString);
|
||||
}
|
||||
|
||||
ArrayType const* TypeProvider::arrayType(DataLocation _location, Type const* _baseType)
|
||||
{
|
||||
return createAndGet<ArrayType>(_location, _baseType);
|
||||
}
|
||||
|
||||
ArrayType const* TypeProvider::arrayType(DataLocation _location, Type const* _baseType, u256 const& _length)
|
||||
{
|
||||
return createAndGet<ArrayType>(_location, _baseType, _length);
|
||||
}
|
||||
|
||||
ContractType const* TypeProvider::contractType(ContractDefinition const& _contractDef, bool _isSuper)
|
||||
{
|
||||
return createAndGet<ContractType>(_contractDef, _isSuper);
|
||||
}
|
||||
|
||||
EnumType const* TypeProvider::enumType(EnumDefinition const& _enumDef)
|
||||
{
|
||||
return createAndGet<EnumType>(_enumDef);
|
||||
}
|
||||
|
||||
ModuleType const* TypeProvider::moduleType(SourceUnit const& _source)
|
||||
{
|
||||
return createAndGet<ModuleType>(_source);
|
||||
}
|
||||
|
||||
TypeType const* TypeProvider::typeType(Type const* _actualType)
|
||||
{
|
||||
return createAndGet<TypeType>(_actualType);
|
||||
}
|
||||
|
||||
StructType const* TypeProvider::structType(StructDefinition const& _struct, DataLocation _location)
|
||||
{
|
||||
return createAndGet<StructType>(_struct, _location);
|
||||
}
|
||||
|
||||
ModifierType const* TypeProvider::modifierType(ModifierDefinition const& _def)
|
||||
{
|
||||
return createAndGet<ModifierType>(_def);
|
||||
}
|
||||
|
||||
MagicType const* TypeProvider::magicType(MagicType::Kind _kind)
|
||||
{
|
||||
solAssert(_kind != MagicType::Kind::MetaType, "MetaType is handled separately");
|
||||
return &m_magicTypes.at(static_cast<size_t>(_kind));
|
||||
}
|
||||
|
||||
MagicType const* TypeProvider::metaType(Type const* _type)
|
||||
{
|
||||
solAssert(_type && _type->category() == Type::Category::Contract, "Only contracts supported for now.");
|
||||
return createAndGet<MagicType>(_type);
|
||||
}
|
||||
|
||||
MappingType const* TypeProvider::mappingType(Type const* _keyType, Type const* _valueType)
|
||||
{
|
||||
return createAndGet<MappingType>(_keyType, _valueType);
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
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 <libsolidity/ast/Types.h>
|
||||
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
namespace dev
|
||||
{
|
||||
namespace solidity
|
||||
{
|
||||
|
||||
/**
|
||||
* API for accessing the Solidity Type System.
|
||||
*
|
||||
* This is the Solidity Compiler's type provider. Use it to request for types. The caller does
|
||||
* <b>not</b> own the types.
|
||||
*
|
||||
* It is not recommended to explicitly instantiate types unless you really know what and why
|
||||
* you are doing it.
|
||||
*/
|
||||
class TypeProvider
|
||||
{
|
||||
public:
|
||||
TypeProvider() = default;
|
||||
TypeProvider(TypeProvider&&) = default;
|
||||
TypeProvider(TypeProvider const&) = delete;
|
||||
TypeProvider& operator=(TypeProvider&&) = default;
|
||||
TypeProvider& operator=(TypeProvider const&) = delete;
|
||||
~TypeProvider() = default;
|
||||
|
||||
/// Resets state of this TypeProvider to initial state, wiping all mutable types.
|
||||
/// This invalidates all dangling pointers to types provided by this TypeProvider.
|
||||
static void reset();
|
||||
|
||||
/// @name Factory functions
|
||||
/// Factory functions that convert an AST @ref TypeName to a Type.
|
||||
static Type const* fromElementaryTypeName(ElementaryTypeNameToken const& _type);
|
||||
|
||||
/// Converts a given elementary type name with optional data location
|
||||
/// suffix " storage", " calldata" or " memory" to a type pointer. If suffix not given, defaults to " storage".
|
||||
static TypePointer fromElementaryTypeName(std::string const& _name);
|
||||
|
||||
/// @returns boolean type.
|
||||
static BoolType const* boolType() noexcept { return &m_boolType; }
|
||||
|
||||
static FixedBytesType const* byteType() { return fixedBytesType(1); }
|
||||
static FixedBytesType const* fixedBytesType(unsigned m) { return &m_bytesM.at(m - 1); }
|
||||
|
||||
static ArrayType const* bytesType() noexcept { return &m_bytesStorageType; }
|
||||
static ArrayType const* bytesMemoryType() noexcept { return &m_bytesMemoryType; }
|
||||
static ArrayType const* stringType() noexcept { return &m_stringStorageType; }
|
||||
static ArrayType const* stringMemoryType() noexcept { return &m_stringMemoryType; }
|
||||
|
||||
/// Constructor for a byte array ("bytes") and string.
|
||||
static ArrayType const* arrayType(DataLocation _location, bool _isString = false);
|
||||
|
||||
/// Constructor for a dynamically sized array type ("type[]")
|
||||
static ArrayType const* arrayType(DataLocation _location, Type const* _baseType);
|
||||
|
||||
/// Constructor for a fixed-size array type ("type[20]")
|
||||
static ArrayType const* arrayType(DataLocation _location, Type const* _baseType, u256 const& _length);
|
||||
|
||||
static AddressType const* payableAddressType() noexcept { return &m_payableAddressType; }
|
||||
static AddressType const* addressType() noexcept { return &m_addressType; }
|
||||
|
||||
static IntegerType const* integerType(unsigned _bits = 256, IntegerType::Modifier _modifier = IntegerType::Modifier::Unsigned)
|
||||
{
|
||||
solAssert((_bits % 8) == 0, "");
|
||||
if (_modifier == IntegerType::Modifier::Unsigned)
|
||||
return &m_uintM.at(_bits / 8 - 1);
|
||||
else
|
||||
return &m_intM.at(_bits / 8 - 1);
|
||||
}
|
||||
|
||||
static FixedPointType const* fixedPointType(unsigned m, unsigned n, FixedPointType::Modifier _modifier);
|
||||
|
||||
static StringLiteralType const* stringLiteralType(std::string const& literal);
|
||||
|
||||
/// @param members the member types the tuple type must contain. This is passed by value on purspose.
|
||||
/// @returns a tuple type with the given members.
|
||||
static TupleType const* tupleType(std::vector<Type const*> members);
|
||||
|
||||
static TupleType const* emptyTupleType() noexcept { return &m_emptyTupleType; }
|
||||
|
||||
static ReferenceType const* withLocation(ReferenceType const* _type, DataLocation _location, bool _isPointer);
|
||||
|
||||
/// @returns a copy of @a _type having the same location as this (and is not a pointer type)
|
||||
/// if _type is a reference type and an unmodified copy of _type otherwise.
|
||||
/// This function is mostly useful to modify inner types appropriately.
|
||||
static Type const* withLocationIfReference(DataLocation _location, Type const* _type)
|
||||
{
|
||||
if (auto refType = dynamic_cast<ReferenceType const*>(_type))
|
||||
return withLocation(refType, _location, false);
|
||||
|
||||
return _type;
|
||||
}
|
||||
|
||||
/// @returns the internally-facing or externally-facing type of a function.
|
||||
static FunctionType const* functionType(FunctionDefinition const& _function, bool _isInternal = true);
|
||||
|
||||
/// @returns the accessor function type of a state variable.
|
||||
static FunctionType const* functionType(VariableDeclaration const& _varDecl);
|
||||
|
||||
/// @returns the function type of an event.
|
||||
static FunctionType const* functionType(EventDefinition const& _event);
|
||||
|
||||
/// @returns the type of a function type name.
|
||||
static FunctionType const* functionType(FunctionTypeName const& _typeName);
|
||||
|
||||
/// @returns the function type to be used for a plain type (not derived from a declaration).
|
||||
static FunctionType const* functionType(
|
||||
strings const& _parameterTypes,
|
||||
strings const& _returnParameterTypes,
|
||||
FunctionType::Kind _kind = FunctionType::Kind::Internal,
|
||||
bool _arbitraryParameters = false,
|
||||
StateMutability _stateMutability = StateMutability::NonPayable
|
||||
);
|
||||
|
||||
/// @returns a highly customized FunctionType, use with care.
|
||||
static FunctionType const* functionType(
|
||||
TypePointers const& _parameterTypes,
|
||||
TypePointers const& _returnParameterTypes,
|
||||
strings _parameterNames = strings{},
|
||||
strings _returnParameterNames = strings{},
|
||||
FunctionType::Kind _kind = FunctionType::Kind::Internal,
|
||||
bool _arbitraryParameters = false,
|
||||
StateMutability _stateMutability = StateMutability::NonPayable,
|
||||
Declaration const* _declaration = nullptr,
|
||||
bool _gasSet = false,
|
||||
bool _valueSet = false,
|
||||
bool _bound = false
|
||||
);
|
||||
|
||||
/// Auto-detect the proper type for a literal. @returns an empty pointer if the literal does
|
||||
/// not fit any type.
|
||||
static TypePointer forLiteral(Literal const& _literal);
|
||||
static RationalNumberType const* rationalNumberType(Literal const& _literal);
|
||||
|
||||
static RationalNumberType const* rationalNumberType(
|
||||
rational const& _value,
|
||||
Type const* _compatibleBytesType = nullptr
|
||||
);
|
||||
|
||||
static ContractType const* contractType(ContractDefinition const& _contract, bool _isSuper = false);
|
||||
|
||||
static InaccessibleDynamicType const* inaccessibleDynamicType() noexcept { return &m_inaccessibleDynamicType; }
|
||||
|
||||
/// @returns the type of an enum instance for given definition, there is one distinct type per enum definition.
|
||||
static EnumType const* enumType(EnumDefinition const& _enum);
|
||||
|
||||
/// @returns special type for imported modules. These mainly give access to their scope via members.
|
||||
static ModuleType const* moduleType(SourceUnit const& _source);
|
||||
|
||||
static TypeType const* typeType(Type const* _actualType);
|
||||
|
||||
static StructType const* structType(StructDefinition const& _struct, DataLocation _location = DataLocation::Storage);
|
||||
|
||||
static ModifierType const* modifierType(ModifierDefinition const& _modifierDef);
|
||||
|
||||
static MagicType const* magicType(MagicType::Kind _kind);
|
||||
|
||||
static MagicType const* metaType(Type const* _type);
|
||||
|
||||
static MappingType const* mappingType(Type const* _keyType, Type const* _valueType);
|
||||
|
||||
private:
|
||||
/// Global TypeProvider instance.
|
||||
static TypeProvider& instance()
|
||||
{
|
||||
static TypeProvider _provider;
|
||||
return _provider;
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
static inline T const* createAndGet(Args&& ... _args);
|
||||
|
||||
static BoolType const m_boolType;
|
||||
static InaccessibleDynamicType const m_inaccessibleDynamicType;
|
||||
static ArrayType const m_bytesStorageType;
|
||||
static ArrayType const m_bytesMemoryType;
|
||||
static ArrayType const m_stringStorageType;
|
||||
static ArrayType const m_stringMemoryType;
|
||||
static TupleType const m_emptyTupleType;
|
||||
static AddressType const m_payableAddressType;
|
||||
static AddressType const m_addressType;
|
||||
static std::array<IntegerType, 32> const m_intM;
|
||||
static std::array<IntegerType, 32> const m_uintM;
|
||||
static std::array<FixedBytesType, 32> const m_bytesM;
|
||||
static std::array<MagicType, 4> const m_magicTypes; ///< MagicType's except MetaType
|
||||
|
||||
std::map<std::pair<unsigned, unsigned>, std::unique_ptr<FixedPointType>> m_ufixedMxN{};
|
||||
std::map<std::pair<unsigned, unsigned>, std::unique_ptr<FixedPointType>> m_fixedMxN{};
|
||||
std::map<std::string, std::unique_ptr<StringLiteralType>> m_stringLiteralTypes{};
|
||||
std::vector<std::unique_ptr<Type>> m_generalTypes{};
|
||||
};
|
||||
|
||||
} // namespace solidity
|
||||
} // namespace dev
|
||||
+286
-336
File diff suppressed because it is too large
Load Diff
+164
-150
@@ -45,10 +45,11 @@ namespace dev
|
||||
namespace solidity
|
||||
{
|
||||
|
||||
class TypeProvider;
|
||||
class Type; // forward
|
||||
class FunctionType; // forward
|
||||
using TypePointer = std::shared_ptr<Type const>;
|
||||
using FunctionTypePointer = std::shared_ptr<FunctionType const>;
|
||||
using TypePointer = Type const*;
|
||||
using FunctionTypePointer = FunctionType const*;
|
||||
using TypePointers = std::vector<TypePointer>;
|
||||
using rational = boost::rational<dev::bigint>;
|
||||
using TypeResult = Result<TypePointer>;
|
||||
@@ -94,7 +95,7 @@ class MemberList
|
||||
public:
|
||||
struct Member
|
||||
{
|
||||
Member(std::string const& _name, TypePointer const& _type, Declaration const* _declaration = nullptr):
|
||||
Member(std::string const& _name, Type const* _type, Declaration const* _declaration = nullptr):
|
||||
name(_name),
|
||||
type(_type),
|
||||
declaration(_declaration)
|
||||
@@ -102,17 +103,18 @@ public:
|
||||
}
|
||||
|
||||
std::string name;
|
||||
TypePointer type;
|
||||
Type const* type;
|
||||
Declaration const* declaration = nullptr;
|
||||
};
|
||||
|
||||
using MemberMap = std::vector<Member>;
|
||||
|
||||
explicit MemberList(MemberMap const& _members): m_memberTypes(_members) {}
|
||||
|
||||
void combine(MemberList const& _other);
|
||||
TypePointer memberType(std::string const& _name) const
|
||||
{
|
||||
TypePointer type;
|
||||
TypePointer type = nullptr;
|
||||
for (auto const& it: m_memberTypes)
|
||||
if (it.name == _name)
|
||||
{
|
||||
@@ -148,10 +150,16 @@ static_assert(std::is_nothrow_move_constructible<MemberList>::value, "MemberList
|
||||
/**
|
||||
* Abstract base class that forms the root of the type hierarchy.
|
||||
*/
|
||||
class Type: private boost::noncopyable, public std::enable_shared_from_this<Type>
|
||||
class Type
|
||||
{
|
||||
public:
|
||||
Type() = default;
|
||||
Type(Type const&) = delete;
|
||||
Type(Type&&) = default;
|
||||
Type& operator=(Type const&) = delete;
|
||||
Type& operator=(Type&&) = default;
|
||||
virtual ~Type() = default;
|
||||
|
||||
enum class Category
|
||||
{
|
||||
Address, Integer, RationalNumber, StringLiteral, Bool, FixedPoint, Array,
|
||||
@@ -160,20 +168,8 @@ public:
|
||||
InaccessibleDynamic
|
||||
};
|
||||
|
||||
/// @{
|
||||
/// @name Factory functions
|
||||
/// Factory functions that convert an AST @ref TypeName to a Type.
|
||||
static TypePointer fromElementaryTypeName(ElementaryTypeNameToken const& _type);
|
||||
/// Converts a given elementary type name with optional data location
|
||||
/// suffix " storage", " calldata" or " memory" to a type pointer. If suffix not given, defaults to " storage".
|
||||
static TypePointer fromElementaryTypeName(std::string const& _name);
|
||||
/// @}
|
||||
|
||||
/// Auto-detect the proper type for a literal. @returns an empty pointer if the literal does
|
||||
/// not fit any type.
|
||||
static TypePointer forLiteral(Literal const& _literal);
|
||||
/// @returns a pointer to _a or _b if the other is implicitly convertible to it or nullptr otherwise
|
||||
static TypePointer commonType(TypePointer const& _a, TypePointer const& _b);
|
||||
static TypePointer commonType(Type const* _a, Type const* _b);
|
||||
|
||||
virtual Category category() const = 0;
|
||||
/// @returns a valid solidity identifier such that two types should compare equal if and
|
||||
@@ -201,13 +197,13 @@ public:
|
||||
/// @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 TypeResult unaryOperatorResult(Token) const { return TypePointer(); }
|
||||
virtual TypeResult unaryOperatorResult(Token) const { return nullptr; }
|
||||
/// @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 TypeResult binaryOperatorResult(Token _operator, TypePointer const& _other) const
|
||||
virtual TypeResult binaryOperatorResult(Token _operator, Type const* _other) const
|
||||
{
|
||||
return TokenTraits::isCompareOp(_operator) ? commonType(shared_from_this(), _other) : TypePointer();
|
||||
return TokenTraits::isCompareOp(_operator) ? commonType(this, _other) : nullptr;
|
||||
}
|
||||
|
||||
virtual bool operator==(Type const& _other) const { return category() == _other.category(); }
|
||||
@@ -258,14 +254,14 @@ public:
|
||||
/// This returns the corresponding IntegerType or FixedPointType for RationalNumberType
|
||||
/// and the pointer type for storage reference types.
|
||||
/// Might return a null pointer if there is no fitting type.
|
||||
virtual TypePointer mobileType() const { return shared_from_this(); }
|
||||
virtual TypePointer mobileType() const { return this; }
|
||||
/// @returns true if this is a non-value type and the data of this type is stored at the
|
||||
/// given location.
|
||||
virtual bool dataStoredIn(DataLocation) const { return false; }
|
||||
/// @returns the type of a temporary during assignment to a variable of the given type.
|
||||
/// Specifically, returns the requested itself if it can be dynamically allocated (or is a value type)
|
||||
/// and the mobile type otherwise.
|
||||
virtual TypePointer closestTemporaryType(TypePointer const& _targetType) const
|
||||
virtual TypePointer closestTemporaryType(Type const* _targetType) const
|
||||
{
|
||||
return _targetType->dataStoredIn(DataLocation::Storage) ? mobileType() : _targetType;
|
||||
}
|
||||
@@ -298,7 +294,7 @@ public:
|
||||
/// @returns a (simpler) type that is encoded in the same way for external function calls.
|
||||
/// This for example returns address for contract types.
|
||||
/// If there is no such type, returns an empty shared pointer.
|
||||
virtual TypePointer encodingType() const { return TypePointer(); }
|
||||
virtual TypePointer encodingType() const { return nullptr; }
|
||||
/// @returns the encoding type used under the given circumstances for the type of an expression
|
||||
/// when used for e.g. abi.encode(...) or the empty pointer if the object
|
||||
/// cannot be encoded.
|
||||
@@ -311,7 +307,10 @@ public:
|
||||
/// If there is no such type, returns an empty shared pointer.
|
||||
/// @param _inLibrary if set, returns types as used in a library, e.g. struct and contract types
|
||||
/// are returned without modification.
|
||||
virtual TypeResult interfaceType(bool /*_inLibrary*/) const { return TypePointer(); }
|
||||
virtual TypeResult interfaceType(bool /*_inLibrary*/) const { return nullptr; }
|
||||
|
||||
/// Clears all internally cached values (if any).
|
||||
virtual void clearCache() const;
|
||||
|
||||
private:
|
||||
/// @returns a member list containing all members added to this type by `using for` directives.
|
||||
@@ -335,18 +334,15 @@ protected:
|
||||
class AddressType: public Type
|
||||
{
|
||||
public:
|
||||
static AddressType& address() { static std::shared_ptr<AddressType> addr(std::make_shared<AddressType>(StateMutability::NonPayable)); return *addr; }
|
||||
static AddressType& addressPayable() { static std::shared_ptr<AddressType> addr(std::make_shared<AddressType>(StateMutability::Payable)); return *addr; }
|
||||
explicit AddressType(StateMutability _stateMutability);
|
||||
|
||||
Category category() const override { return Category::Address; }
|
||||
|
||||
explicit AddressType(StateMutability _stateMutability);
|
||||
|
||||
std::string richIdentifier() 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;
|
||||
TypeResult binaryOperatorResult(Token _operator, Type const* _other) const override;
|
||||
|
||||
bool operator==(Type const& _other) const override;
|
||||
|
||||
@@ -362,8 +358,8 @@ public:
|
||||
|
||||
u256 literalValue(Literal const* _literal) const override;
|
||||
|
||||
TypePointer encodingType() const override { return shared_from_this(); }
|
||||
TypeResult interfaceType(bool) const override { return shared_from_this(); }
|
||||
TypePointer encodingType() const override { return this; }
|
||||
TypeResult interfaceType(bool) const override { return this; }
|
||||
|
||||
StateMutability stateMutability(void) const { return m_stateMutability; }
|
||||
|
||||
@@ -382,17 +378,21 @@ public:
|
||||
Unsigned, Signed
|
||||
};
|
||||
|
||||
static IntegerType& uint256() { static std::shared_ptr<IntegerType> uint256(std::make_shared<IntegerType>(256)); return *uint256; }
|
||||
explicit IntegerType(unsigned _bits, Modifier _modifier = Modifier::Unsigned);
|
||||
|
||||
Category category() const override { return Category::Integer; }
|
||||
|
||||
explicit IntegerType(unsigned _bits, Modifier _modifier = Modifier::Unsigned);
|
||||
IntegerType(IntegerType&&) = default;
|
||||
IntegerType& operator=(IntegerType&&) = default;
|
||||
IntegerType(IntegerType const&) = default;
|
||||
IntegerType& operator=(IntegerType const&) = default;
|
||||
~IntegerType() = default;
|
||||
|
||||
std::string richIdentifier() 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;
|
||||
TypeResult binaryOperatorResult(Token _operator, Type const* _other) const override;
|
||||
|
||||
bool operator==(Type const& _other) const override;
|
||||
|
||||
@@ -403,8 +403,8 @@ public:
|
||||
|
||||
std::string toString(bool _short) const override;
|
||||
|
||||
TypePointer encodingType() const override { return shared_from_this(); }
|
||||
TypeResult interfaceType(bool) const override { return shared_from_this(); }
|
||||
TypePointer encodingType() const override { return this; }
|
||||
TypeResult interfaceType(bool) const override { return this; }
|
||||
|
||||
unsigned numBits() const { return m_bits; }
|
||||
bool isSigned() const { return m_modifier == Modifier::Signed; }
|
||||
@@ -413,8 +413,8 @@ public:
|
||||
bigint maxValue() const;
|
||||
|
||||
private:
|
||||
unsigned m_bits;
|
||||
Modifier m_modifier;
|
||||
unsigned const m_bits;
|
||||
Modifier const m_modifier;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -427,15 +427,15 @@ public:
|
||||
{
|
||||
Unsigned, Signed
|
||||
};
|
||||
Category category() const override { return Category::FixedPoint; }
|
||||
|
||||
explicit FixedPointType(unsigned _totalBits, unsigned _fractionalDigits, Modifier _modifier = Modifier::Unsigned);
|
||||
Category category() const override { return Category::FixedPoint; }
|
||||
|
||||
std::string richIdentifier() 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;
|
||||
TypeResult binaryOperatorResult(Token _operator, Type const* _other) const override;
|
||||
|
||||
bool operator==(Type const& _other) const override;
|
||||
|
||||
@@ -446,8 +446,8 @@ public:
|
||||
|
||||
std::string toString(bool _short) const override;
|
||||
|
||||
TypePointer encodingType() const override { return shared_from_this(); }
|
||||
TypeResult interfaceType(bool) const override { return shared_from_this(); }
|
||||
TypePointer encodingType() const override { return this; }
|
||||
TypeResult interfaceType(bool) const override { return this; }
|
||||
|
||||
/// Number of bits used for this type in total.
|
||||
unsigned numBits() const { return m_totalBits; }
|
||||
@@ -462,7 +462,7 @@ public:
|
||||
bigint minIntegerValue() const;
|
||||
|
||||
/// @returns the smallest integer type that can hold this type with fractional parts shifted to integers.
|
||||
std::shared_ptr<IntegerType> asIntegerType() const;
|
||||
IntegerType const* asIntegerType() const;
|
||||
|
||||
private:
|
||||
unsigned m_totalBits;
|
||||
@@ -478,18 +478,16 @@ private:
|
||||
class RationalNumberType: public Type
|
||||
{
|
||||
public:
|
||||
explicit RationalNumberType(rational const& _value, Type const* _compatibleBytesType = nullptr):
|
||||
m_value(_value), m_compatibleBytesType(_compatibleBytesType)
|
||||
{}
|
||||
|
||||
Category category() const override { return Category::RationalNumber; }
|
||||
|
||||
static TypePointer forLiteral(Literal const& _literal);
|
||||
|
||||
explicit RationalNumberType(rational const& _value, TypePointer const& _compatibleBytesType = TypePointer()):
|
||||
m_value(_value), m_compatibleBytesType(_compatibleBytesType)
|
||||
{}
|
||||
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;
|
||||
TypeResult binaryOperatorResult(Token _operator, Type const* _other) const override;
|
||||
|
||||
std::string richIdentifier() const override;
|
||||
bool operator==(Type const& _other) const override;
|
||||
@@ -502,11 +500,11 @@ public:
|
||||
TypePointer mobileType() const override;
|
||||
|
||||
/// @returns the smallest integer type that can hold the value or an empty pointer if not possible.
|
||||
std::shared_ptr<IntegerType const> integerType() const;
|
||||
IntegerType const* integerType() const;
|
||||
/// @returns the smallest fixed type that can hold the value or incurs the least precision loss,
|
||||
/// unless the value was truncated, then a suitable type will be chosen to indicate such event.
|
||||
/// If the integer part does not fit, returns an empty pointer.
|
||||
std::shared_ptr<FixedPointType const> fixedPointType() const;
|
||||
FixedPointType const* fixedPointType() const;
|
||||
|
||||
/// @returns true if the value is not an integer.
|
||||
bool isFractional() const { return m_value.denominator() != 1; }
|
||||
@@ -517,6 +515,9 @@ public:
|
||||
/// @returns true if the value is zero.
|
||||
bool isZero() const { return m_value == 0; }
|
||||
|
||||
/// @returns true if the literal is a valid integer.
|
||||
static std::tuple<bool, rational> isValidLiteral(Literal const& _literal);
|
||||
|
||||
private:
|
||||
rational m_value;
|
||||
|
||||
@@ -524,9 +525,6 @@ private:
|
||||
/// Empty for all rationals that are not directly parsed from hex literals.
|
||||
TypePointer m_compatibleBytesType;
|
||||
|
||||
/// @returns true if the literal is a valid integer.
|
||||
static std::tuple<bool, rational> isValidLiteral(Literal const& _literal);
|
||||
|
||||
/// @returns true if the literal is a valid rational number.
|
||||
static std::tuple<bool, rational> parseRational(std::string const& _value);
|
||||
|
||||
@@ -541,14 +539,15 @@ private:
|
||||
class StringLiteralType: public Type
|
||||
{
|
||||
public:
|
||||
explicit StringLiteralType(Literal const& _literal);
|
||||
explicit StringLiteralType(std::string const& _value);
|
||||
|
||||
Category category() const override { return Category::StringLiteral; }
|
||||
|
||||
explicit StringLiteralType(Literal const& _literal);
|
||||
|
||||
BoolResult isImplicitlyConvertibleTo(Type const& _convertTo) const override;
|
||||
TypeResult binaryOperatorResult(Token, TypePointer const&) const override
|
||||
TypeResult binaryOperatorResult(Token, Type const*) const override
|
||||
{
|
||||
return TypePointer();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::string richIdentifier() const override;
|
||||
@@ -575,16 +574,22 @@ private:
|
||||
class FixedBytesType: public Type
|
||||
{
|
||||
public:
|
||||
explicit FixedBytesType(unsigned _bytes);
|
||||
|
||||
Category category() const override { return Category::FixedBytes; }
|
||||
|
||||
explicit FixedBytesType(unsigned _bytes);
|
||||
FixedBytesType(FixedBytesType const&) = delete;
|
||||
FixedBytesType& operator=(FixedBytesType const&) = delete;
|
||||
FixedBytesType(FixedBytesType&&) = default;
|
||||
FixedBytesType& operator=(FixedBytesType&&) = default;
|
||||
~FixedBytesType() = default;
|
||||
|
||||
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;
|
||||
TypeResult unaryOperatorResult(Token _operator) const override;
|
||||
TypeResult binaryOperatorResult(Token _operator, TypePointer const& _other) const override;
|
||||
TypeResult binaryOperatorResult(Token _operator, Type 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; }
|
||||
@@ -593,8 +598,8 @@ public:
|
||||
|
||||
std::string toString(bool) const override { return "bytes" + dev::toString(m_bytes); }
|
||||
MemberList::MemberMap nativeMembers(ContractDefinition const*) const override;
|
||||
TypePointer encodingType() const override { return shared_from_this(); }
|
||||
TypeResult interfaceType(bool) const override { return shared_from_this(); }
|
||||
TypePointer encodingType() const override { return this; }
|
||||
TypeResult interfaceType(bool) const override { return this; }
|
||||
|
||||
unsigned numBytes() const { return m_bytes; }
|
||||
|
||||
@@ -608,10 +613,12 @@ private:
|
||||
class BoolType: public Type
|
||||
{
|
||||
public:
|
||||
BoolType() = default;
|
||||
|
||||
Category category() const override { return Category::Bool; }
|
||||
std::string richIdentifier() const override { return "t_bool"; }
|
||||
TypeResult unaryOperatorResult(Token _operator) const override;
|
||||
TypeResult binaryOperatorResult(Token _operator, TypePointer const& _other) const override;
|
||||
TypeResult binaryOperatorResult(Token _operator, Type const* _other) const override;
|
||||
|
||||
unsigned calldataEncodedSize(bool _padded) const override{ return _padded ? 32 : 1; }
|
||||
unsigned storageBytes() const override { return 1; }
|
||||
@@ -620,8 +627,8 @@ public:
|
||||
|
||||
std::string toString(bool) const override { return "bool"; }
|
||||
u256 literalValue(Literal const* _literal) const override;
|
||||
TypePointer encodingType() const override { return shared_from_this(); }
|
||||
TypeResult interfaceType(bool) const override { return shared_from_this(); }
|
||||
TypePointer encodingType() const override { return this; }
|
||||
TypeResult interfaceType(bool) const override { return this; }
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -630,22 +637,24 @@ public:
|
||||
*/
|
||||
class ReferenceType: public Type
|
||||
{
|
||||
public:
|
||||
protected:
|
||||
explicit ReferenceType(DataLocation _location): m_location(_location) {}
|
||||
|
||||
public:
|
||||
DataLocation location() const { return m_location; }
|
||||
|
||||
TypeResult unaryOperatorResult(Token _operator) const override;
|
||||
TypeResult binaryOperatorResult(Token, TypePointer const&) const override
|
||||
TypeResult binaryOperatorResult(Token, Type const*) const override
|
||||
{
|
||||
return TypePointer();
|
||||
return nullptr;
|
||||
}
|
||||
unsigned memoryHeadSize() const override { return 32; }
|
||||
|
||||
/// @returns a copy of this type with location (recursively) changed to @a _location,
|
||||
/// whereas isPointer is only shallowly changed - the deep copy is always a bound reference.
|
||||
virtual TypePointer copyForLocation(DataLocation _location, bool _isPointer) const = 0;
|
||||
virtual std::unique_ptr<ReferenceType> copyForLocation(DataLocation _location, bool _isPointer) const = 0;
|
||||
|
||||
TypePointer mobileType() const override { return copyForLocation(m_location, true); }
|
||||
TypePointer mobileType() const override { return withLocation(m_location, true); }
|
||||
bool dataStoredIn(DataLocation _location) const override { return m_location == _location; }
|
||||
bool hasSimpleZeroValueInMemory() const override { return false; }
|
||||
|
||||
@@ -663,10 +672,12 @@ public:
|
||||
/// @returns a copy of @a _type having the same location as this (and is not a pointer type)
|
||||
/// if _type is a reference type and an unmodified copy of _type otherwise.
|
||||
/// This function is mostly useful to modify inner types appropriately.
|
||||
static TypePointer copyForLocationIfReference(DataLocation _location, TypePointer const& _type);
|
||||
static Type const* copyForLocationIfReference(DataLocation _location, Type const* _type);
|
||||
|
||||
Type const* withLocation(DataLocation _location, bool _isPointer) const;
|
||||
|
||||
protected:
|
||||
TypePointer copyForLocationIfReference(TypePointer const& _type) const;
|
||||
Type const* copyForLocationIfReference(Type const* _type) const;
|
||||
/// @returns a human-readable description of the reference part of the type.
|
||||
std::string stringForReferencePart() const;
|
||||
/// @returns the suffix computed from the reference part to be used by identifier();
|
||||
@@ -686,32 +697,26 @@ protected:
|
||||
class ArrayType: public ReferenceType
|
||||
{
|
||||
public:
|
||||
static ArrayType& bytesMemory() { static std::shared_ptr<ArrayType> addr(std::make_shared<ArrayType>(DataLocation::Memory)); return *addr; }
|
||||
static ArrayType& stringMemory() { static std::shared_ptr<ArrayType> addr(std::make_shared<ArrayType>(DataLocation::Memory, true)); return *addr; }
|
||||
|
||||
Category category() const override { return Category::Array; }
|
||||
|
||||
/// Constructor for a byte array ("bytes") and string.
|
||||
explicit ArrayType(DataLocation _location, bool _isString = false):
|
||||
ReferenceType(_location),
|
||||
m_arrayKind(_isString ? ArrayKind::String : ArrayKind::Bytes),
|
||||
m_baseType(std::make_shared<FixedBytesType>(1))
|
||||
{
|
||||
}
|
||||
explicit ArrayType(DataLocation _location, bool _isString = false);
|
||||
|
||||
/// Constructor for a dynamically sized array type ("type[]")
|
||||
ArrayType(DataLocation _location, TypePointer const& _baseType):
|
||||
ArrayType(DataLocation _location, Type const* _baseType):
|
||||
ReferenceType(_location),
|
||||
m_baseType(copyForLocationIfReference(_baseType))
|
||||
{
|
||||
}
|
||||
|
||||
/// Constructor for a fixed-size array type ("type[20]")
|
||||
ArrayType(DataLocation _location, TypePointer const& _baseType, u256 const& _length):
|
||||
ArrayType(DataLocation _location, Type const* _baseType, u256 const& _length):
|
||||
ReferenceType(_location),
|
||||
m_baseType(copyForLocationIfReference(_baseType)),
|
||||
m_hasDynamicLength(false),
|
||||
m_length(_length)
|
||||
{}
|
||||
|
||||
Category category() const override { return Category::Array; }
|
||||
|
||||
BoolResult isImplicitlyConvertibleTo(Type const& _convertTo) const override;
|
||||
BoolResult isExplicitlyConvertibleTo(Type const& _convertTo) const override;
|
||||
std::string richIdentifier() const override;
|
||||
@@ -737,11 +742,11 @@ public:
|
||||
bool isByteArray() const { return m_arrayKind != ArrayKind::Ordinary; }
|
||||
/// @returns true if this is a string
|
||||
bool isString() const { return m_arrayKind == ArrayKind::String; }
|
||||
TypePointer const& baseType() const { solAssert(!!m_baseType, ""); return m_baseType;}
|
||||
Type const* baseType() const { solAssert(!!m_baseType, ""); return m_baseType; }
|
||||
u256 const& length() const { return m_length; }
|
||||
u256 memorySize() const;
|
||||
|
||||
TypePointer copyForLocation(DataLocation _location, bool _isPointer) const override;
|
||||
std::unique_ptr<ReferenceType> copyForLocation(DataLocation _location, bool _isPointer) const override;
|
||||
|
||||
/// The offset to advance in calldata to move from one array element to the next.
|
||||
unsigned calldataStride() const { return isByteArray() ? 1 : m_baseType->calldataEncodedSize(); }
|
||||
@@ -750,6 +755,8 @@ public:
|
||||
/// The offset to advance in storage to move from one array element to the next.
|
||||
unsigned storageStride() const { return isByteArray() ? 1 : m_baseType->storageBytes(); }
|
||||
|
||||
void clearCache() const override;
|
||||
|
||||
private:
|
||||
/// String is interpreted as a subtype of Bytes.
|
||||
enum class ArrayKind { Ordinary, Bytes, String };
|
||||
@@ -758,7 +765,7 @@ private:
|
||||
|
||||
///< Byte arrays ("bytes") and strings have different semantics from ordinary arrays.
|
||||
ArrayKind m_arrayKind = ArrayKind::Ordinary;
|
||||
TypePointer m_baseType;
|
||||
Type const* m_baseType;
|
||||
bool m_hasDynamicLength = true;
|
||||
u256 m_length;
|
||||
mutable boost::optional<TypeResult> m_interfaceType;
|
||||
@@ -771,9 +778,10 @@ private:
|
||||
class ContractType: public Type
|
||||
{
|
||||
public:
|
||||
Category category() const override { return Category::Contract; }
|
||||
explicit ContractType(ContractDefinition const& _contract, bool _super = false):
|
||||
m_contract(_contract), m_super(_super) {}
|
||||
|
||||
Category category() const override { return Category::Contract; }
|
||||
/// Contracts can be implicitly converted only to base contracts.
|
||||
BoolResult isImplicitlyConvertibleTo(Type const& _convertTo) const override;
|
||||
/// Contracts can only be explicitly converted to address types and base contracts.
|
||||
@@ -795,17 +803,14 @@ public:
|
||||
std::string canonicalName() const override;
|
||||
|
||||
MemberList::MemberMap nativeMembers(ContractDefinition const* _currentScope) const override;
|
||||
TypePointer encodingType() const override
|
||||
{
|
||||
if (isSuper())
|
||||
return TypePointer{};
|
||||
return std::make_shared<AddressType>(isPayable() ? StateMutability::Payable : StateMutability::NonPayable);
|
||||
}
|
||||
|
||||
Type const* encodingType() const override;
|
||||
|
||||
TypeResult interfaceType(bool _inLibrary) const override
|
||||
{
|
||||
if (isSuper())
|
||||
return TypePointer{};
|
||||
return _inLibrary ? shared_from_this() : encodingType();
|
||||
return nullptr;
|
||||
return _inLibrary ? this : encodingType();
|
||||
}
|
||||
|
||||
/// See documentation of m_super
|
||||
@@ -817,7 +822,7 @@ public:
|
||||
ContractDefinition const& contractDefinition() const { return m_contract; }
|
||||
|
||||
/// Returns the function type of the constructor modified to return an object of the contract's type.
|
||||
FunctionTypePointer const& newExpressionType() const;
|
||||
FunctionType const* newExpressionType() const;
|
||||
|
||||
/// @returns a list of all state variables (including inherited) of the contract and their
|
||||
/// offsets in storage.
|
||||
@@ -828,7 +833,7 @@ private:
|
||||
/// If true, this is a special "super" type of m_contract containing only members that m_contract inherited
|
||||
bool m_super = false;
|
||||
/// Type of the constructor, @see constructorType. Lazily initialized.
|
||||
mutable FunctionTypePointer m_constructorType;
|
||||
mutable FunctionType const* m_constructorType = nullptr;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -837,9 +842,10 @@ private:
|
||||
class StructType: public ReferenceType
|
||||
{
|
||||
public:
|
||||
Category category() const override { return Category::Struct; }
|
||||
explicit StructType(StructDefinition const& _struct, DataLocation _location = DataLocation::Storage):
|
||||
ReferenceType(_location), m_struct(_struct) {}
|
||||
|
||||
Category category() const override { return Category::Struct; }
|
||||
BoolResult isImplicitlyConvertibleTo(Type const& _convertTo) const override;
|
||||
std::string richIdentifier() const override;
|
||||
bool operator==(Type const& _other) const override;
|
||||
@@ -851,10 +857,8 @@ public:
|
||||
std::string toString(bool _short) const override;
|
||||
|
||||
MemberList::MemberMap nativeMembers(ContractDefinition const* _currentScope) const override;
|
||||
TypePointer encodingType() const override
|
||||
{
|
||||
return location() == DataLocation::Storage ? std::make_shared<IntegerType>(256) : shared_from_this();
|
||||
}
|
||||
|
||||
Type const* encodingType() const override;
|
||||
TypeResult interfaceType(bool _inLibrary) const override;
|
||||
|
||||
bool recursive() const
|
||||
@@ -867,14 +871,14 @@ public:
|
||||
return m_recursive.get();
|
||||
}
|
||||
|
||||
TypePointer copyForLocation(DataLocation _location, bool _isPointer) const override;
|
||||
std::unique_ptr<ReferenceType> copyForLocation(DataLocation _location, bool _isPointer) const override;
|
||||
|
||||
std::string canonicalName() const override;
|
||||
std::string signatureInExternalFunction(bool _structsByName) const override;
|
||||
|
||||
/// @returns a function that performs the type conversion between a list of struct members
|
||||
/// and a memory struct of this type.
|
||||
FunctionTypePointer constructorType() const;
|
||||
FunctionType const* constructorType() const;
|
||||
|
||||
std::pair<u256, unsigned> const& storageOffsetsOfMember(std::string const& _name) const;
|
||||
u256 memoryOffsetOfMember(std::string const& _name) const;
|
||||
@@ -886,6 +890,9 @@ public:
|
||||
TypePointers memoryMemberTypes() const;
|
||||
/// @returns the set of all members that are removed in the memory version (typically mappings).
|
||||
std::set<std::string> membersMissingInMemory() const;
|
||||
|
||||
void clearCache() const override;
|
||||
|
||||
private:
|
||||
StructDefinition const& m_struct;
|
||||
// Caches for interfaceType(bool)
|
||||
@@ -900,8 +907,9 @@ private:
|
||||
class EnumType: public Type
|
||||
{
|
||||
public:
|
||||
Category category() const override { return Category::Enum; }
|
||||
explicit EnumType(EnumDefinition const& _enum): m_enum(_enum) {}
|
||||
|
||||
Category category() const override { return Category::Enum; }
|
||||
TypeResult unaryOperatorResult(Token _operator) const override;
|
||||
std::string richIdentifier() const override;
|
||||
bool operator==(Type const& _other) const override;
|
||||
@@ -917,13 +925,10 @@ public:
|
||||
bool isValueType() const override { return true; }
|
||||
|
||||
BoolResult isExplicitlyConvertibleTo(Type const& _convertTo) const override;
|
||||
TypePointer encodingType() const override
|
||||
{
|
||||
return std::make_shared<IntegerType>(8 * int(storageBytes()));
|
||||
}
|
||||
TypePointer encodingType() const override;
|
||||
TypeResult interfaceType(bool _inLibrary) const override
|
||||
{
|
||||
return _inLibrary ? shared_from_this() : encodingType();
|
||||
return _inLibrary ? this : encodingType();
|
||||
}
|
||||
|
||||
EnumDefinition const& enumDefinition() const { return m_enum; }
|
||||
@@ -942,12 +947,16 @@ private:
|
||||
class TupleType: public Type
|
||||
{
|
||||
public:
|
||||
explicit TupleType(std::vector<TypePointer> _types = {}): m_components(std::move(_types)) {}
|
||||
|
||||
Category category() const override { return Category::Tuple; }
|
||||
explicit TupleType(std::vector<TypePointer> const& _types = std::vector<TypePointer>()): m_components(_types) {}
|
||||
TupleType(TupleType&&) = default;
|
||||
TupleType& operator=(TupleType&) = default;
|
||||
|
||||
BoolResult isImplicitlyConvertibleTo(Type const& _other) const override;
|
||||
std::string richIdentifier() const override;
|
||||
bool operator==(Type const& _other) const override;
|
||||
TypeResult binaryOperatorResult(Token, TypePointer const&) const override { return TypePointer(); }
|
||||
TypeResult binaryOperatorResult(Token, Type const*) const override { return nullptr; }
|
||||
std::string toString(bool) const override;
|
||||
bool canBeStored() const override { return false; }
|
||||
u256 storageSize() const override;
|
||||
@@ -956,7 +965,7 @@ public:
|
||||
bool hasSimpleZeroValueInMemory() const override { return false; }
|
||||
TypePointer mobileType() const override;
|
||||
/// Converts components to their temporary types and performs some wildcard matching.
|
||||
TypePointer closestTemporaryType(TypePointer const& _targetType) const override;
|
||||
TypePointer closestTemporaryType(Type const* _targetType) const override;
|
||||
|
||||
std::vector<TypePointer> const& components() const { return m_components; }
|
||||
|
||||
@@ -1017,8 +1026,6 @@ public:
|
||||
MetaType ///< type(...)
|
||||
};
|
||||
|
||||
Category category() const override { return Category::Function; }
|
||||
|
||||
/// Creates the type of a function.
|
||||
explicit FunctionType(FunctionDefinition const& _function, bool _isInternal = true);
|
||||
/// Creates the accessor function type of a state variable.
|
||||
@@ -1046,9 +1053,6 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
/// @returns the type of the "new Contract" function, i.e. basically the constructor.
|
||||
static FunctionTypePointer newExpressionType(ContractDefinition const& _contract);
|
||||
|
||||
/// Detailed constructor, use with care.
|
||||
FunctionType(
|
||||
TypePointers const& _parameterTypes,
|
||||
@@ -1089,6 +1093,11 @@ public:
|
||||
);
|
||||
}
|
||||
|
||||
Category category() const override { return Category::Function; }
|
||||
|
||||
/// @returns the type of the "new Contract" function, i.e. basically the constructor.
|
||||
static FunctionTypePointer newExpressionType(ContractDefinition const& _contract);
|
||||
|
||||
TypePointers parameterTypes() const;
|
||||
std::vector<std::string> parameterNames() const;
|
||||
TypePointers const& returnParameterTypes() const { return m_returnParameterTypes; }
|
||||
@@ -1097,14 +1106,14 @@ public:
|
||||
TypePointers returnParameterTypesWithoutDynamicTypes() const;
|
||||
std::vector<std::string> const& returnParameterNames() const { return m_returnParameterNames; }
|
||||
/// @returns the "self" parameter type for a bound function
|
||||
TypePointer const& selfType() const;
|
||||
Type const* selfType() const;
|
||||
|
||||
std::string richIdentifier() const override;
|
||||
bool operator==(Type 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, TypePointer const&) const override;
|
||||
TypeResult binaryOperatorResult(Token, Type const*) const override;
|
||||
std::string canonicalName() const override;
|
||||
std::string toString(bool _short) const override;
|
||||
unsigned calldataEncodedSize(bool _padded) const override;
|
||||
@@ -1133,7 +1142,7 @@ public:
|
||||
/// expression the function is called on.
|
||||
bool canTakeArguments(
|
||||
FuncCallArguments const& _arguments,
|
||||
TypePointer const& _selfType = TypePointer()
|
||||
Type const* _selfType = nullptr
|
||||
) const;
|
||||
|
||||
/// @returns true if the types of parameters are equal (does not check return parameter types)
|
||||
@@ -1229,27 +1238,25 @@ private:
|
||||
class MappingType: public Type
|
||||
{
|
||||
public:
|
||||
Category category() const override { return Category::Mapping; }
|
||||
MappingType(TypePointer const& _keyType, TypePointer const& _valueType):
|
||||
MappingType(Type const* _keyType, Type const* _valueType):
|
||||
m_keyType(_keyType), m_valueType(_valueType) {}
|
||||
|
||||
Category category() const override { return Category::Mapping; }
|
||||
|
||||
std::string richIdentifier() const override;
|
||||
bool operator==(Type const& _other) const override;
|
||||
std::string toString(bool _short) const override;
|
||||
std::string canonicalName() const override;
|
||||
bool canLiveOutsideStorage() const override { return false; }
|
||||
TypeResult binaryOperatorResult(Token, TypePointer const&) const override { return TypePointer(); }
|
||||
TypePointer encodingType() const override
|
||||
{
|
||||
return std::make_shared<IntegerType>(256);
|
||||
}
|
||||
TypeResult binaryOperatorResult(Token, Type const*) const override { return nullptr; }
|
||||
Type const* encodingType() const override;
|
||||
TypeResult interfaceType(bool _inLibrary) const override;
|
||||
bool dataStoredIn(DataLocation _location) const override { return _location == DataLocation::Storage; }
|
||||
/// Cannot be stored in memory, but just in case.
|
||||
bool hasSimpleZeroValueInMemory() const override { solAssert(false, ""); }
|
||||
|
||||
TypePointer const& keyType() const { return m_keyType; }
|
||||
TypePointer const& valueType() const { return m_valueType; }
|
||||
Type const* keyType() const { return m_keyType; }
|
||||
Type const* valueType() const { return m_valueType; }
|
||||
|
||||
private:
|
||||
TypePointer m_keyType;
|
||||
@@ -1264,11 +1271,12 @@ private:
|
||||
class TypeType: public Type
|
||||
{
|
||||
public:
|
||||
Category category() const override { return Category::TypeType; }
|
||||
explicit TypeType(TypePointer const& _actualType): m_actualType(_actualType) {}
|
||||
TypePointer const& actualType() const { return m_actualType; }
|
||||
explicit TypeType(Type const* _actualType): m_actualType(_actualType) {}
|
||||
|
||||
TypeResult binaryOperatorResult(Token, TypePointer const&) const override { return TypePointer(); }
|
||||
Category category() const override { return Category::TypeType; }
|
||||
Type const* actualType() const { return m_actualType; }
|
||||
|
||||
TypeResult binaryOperatorResult(Token, Type const*) const override { return nullptr; }
|
||||
std::string richIdentifier() const override;
|
||||
bool operator==(Type const& _other) const override;
|
||||
bool canBeStored() const override { return false; }
|
||||
@@ -1290,10 +1298,11 @@ private:
|
||||
class ModifierType: public Type
|
||||
{
|
||||
public:
|
||||
Category category() const override { return Category::Modifier; }
|
||||
explicit ModifierType(ModifierDefinition const& _modifier);
|
||||
|
||||
TypeResult binaryOperatorResult(Token, TypePointer const&) const override { return TypePointer(); }
|
||||
Category category() const override { return Category::Modifier; }
|
||||
|
||||
TypeResult binaryOperatorResult(Token, Type const*) const override { return nullptr; }
|
||||
bool canBeStored() const override { return false; }
|
||||
u256 storageSize() const override;
|
||||
bool canLiveOutsideStorage() const override { return false; }
|
||||
@@ -1315,11 +1324,11 @@ private:
|
||||
class ModuleType: public Type
|
||||
{
|
||||
public:
|
||||
Category category() const override { return Category::Module; }
|
||||
|
||||
explicit ModuleType(SourceUnit const& _source): m_sourceUnit(_source) {}
|
||||
|
||||
TypeResult binaryOperatorResult(Token, TypePointer const&) const override { return TypePointer(); }
|
||||
Category category() const override { return Category::Module; }
|
||||
|
||||
TypeResult binaryOperatorResult(Token, Type const*) const override { return nullptr; }
|
||||
std::string richIdentifier() const override;
|
||||
bool operator==(Type const& _other) const override;
|
||||
bool canBeStored() const override { return false; }
|
||||
@@ -1347,15 +1356,19 @@ public:
|
||||
ABI, ///< "abi"
|
||||
MetaType ///< "type(...)"
|
||||
};
|
||||
|
||||
public:
|
||||
explicit MagicType(Kind _kind): m_kind(_kind) {}
|
||||
explicit MagicType(Type const* _metaTypeArg): m_kind{Kind::MetaType}, m_typeArgument{_metaTypeArg} {}
|
||||
|
||||
Category category() const override { return Category::Magic; }
|
||||
|
||||
explicit MagicType(Kind _kind): m_kind(_kind) {}
|
||||
/// Factory function for meta type
|
||||
static std::shared_ptr<MagicType> metaType(TypePointer _type);
|
||||
static MagicType const* metaType(TypePointer _type);
|
||||
|
||||
TypeResult binaryOperatorResult(Token, TypePointer const&) const override
|
||||
TypeResult binaryOperatorResult(Token, Type const*) const override
|
||||
{
|
||||
return TypePointer();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::string richIdentifier() const override;
|
||||
@@ -1376,7 +1389,6 @@ private:
|
||||
Kind m_kind;
|
||||
/// Contract type used for contract metadata magic.
|
||||
TypePointer m_typeArgument;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1386,12 +1398,14 @@ private:
|
||||
class InaccessibleDynamicType: public Type
|
||||
{
|
||||
public:
|
||||
InaccessibleDynamicType() = default;
|
||||
|
||||
Category category() const override { return Category::InaccessibleDynamic; }
|
||||
|
||||
std::string richIdentifier() const override { return "t_inaccessible"; }
|
||||
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(); }
|
||||
TypeResult binaryOperatorResult(Token, Type const*) const override { return nullptr; }
|
||||
unsigned calldataEncodedSize(bool _padded) const override { (void)_padded; return 32; }
|
||||
bool canBeStored() const override { return false; }
|
||||
bool canLiveOutsideStorage() const override { return false; }
|
||||
@@ -1399,7 +1413,7 @@ public:
|
||||
unsigned sizeOnStack() const override { return 1; }
|
||||
bool hasSimpleZeroValueInMemory() const override { solAssert(false, ""); }
|
||||
std::string toString(bool) const override { return "inaccessible dynamic type"; }
|
||||
TypePointer decodingType() const override { return std::make_shared<IntegerType>(256); }
|
||||
TypePointer decodingType() const override;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user