mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Contracts as types and framework for special global variables.
This commit is contained in:
parent
fa987e0a20
commit
c50cd646ce
36
AST.cpp
36
AST.cpp
@ -51,6 +51,40 @@ void StructDefinition::accept(ASTVisitor& _visitor)
|
||||
_visitor.endVisit(*this);
|
||||
}
|
||||
|
||||
void StructDefinition::checkValidityOfMembers()
|
||||
{
|
||||
checkMemberTypes();
|
||||
checkRecursion();
|
||||
}
|
||||
|
||||
void StructDefinition::checkMemberTypes()
|
||||
{
|
||||
for (ASTPointer<VariableDeclaration> const& member: getMembers())
|
||||
if (!member->getType()->canBeStored())
|
||||
BOOST_THROW_EXCEPTION(member->createTypeError("Type cannot be used in struct."));
|
||||
}
|
||||
|
||||
void StructDefinition::checkRecursion()
|
||||
{
|
||||
set<StructDefinition const*> definitionsSeen;
|
||||
vector<StructDefinition const*> queue = {this};
|
||||
while (!queue.empty())
|
||||
{
|
||||
StructDefinition const* def = queue.back();
|
||||
queue.pop_back();
|
||||
if (definitionsSeen.count(def))
|
||||
BOOST_THROW_EXCEPTION(ParserError() << errinfo_sourceLocation(def->getLocation())
|
||||
<< errinfo_comment("Recursive struct definition."));
|
||||
definitionsSeen.insert(def);
|
||||
for (ASTPointer<VariableDeclaration> const& member: def->getMembers())
|
||||
if (member->getType()->getCategory() == Type::Category::STRUCT)
|
||||
{
|
||||
UserDefinedTypeName const& typeName = dynamic_cast<UserDefinedTypeName&>(*member->getTypeName());
|
||||
queue.push_back(&dynamic_cast<StructDefinition const&>(*typeName.getReferencedDeclaration()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ParameterList::accept(ASTVisitor& _visitor)
|
||||
{
|
||||
if (_visitor.visit(*this))
|
||||
@ -258,7 +292,7 @@ void Literal::accept(ASTVisitor& _visitor)
|
||||
_visitor.endVisit(*this);
|
||||
}
|
||||
|
||||
TypeError ASTNode::createTypeError(string const& _description)
|
||||
TypeError ASTNode::createTypeError(string const& _description) const
|
||||
{
|
||||
return TypeError() << errinfo_sourceLocation(getLocation()) << errinfo_comment(_description);
|
||||
}
|
||||
|
20
AST.h
20
AST.h
@ -66,7 +66,7 @@ public:
|
||||
|
||||
/// Creates a @ref TypeError exception and decorates it with the location of the node and
|
||||
/// the given description
|
||||
TypeError createTypeError(std::string const& _description);
|
||||
TypeError createTypeError(std::string const& _description) const;
|
||||
|
||||
///@{
|
||||
///@name equality operators
|
||||
@ -139,7 +139,14 @@ public:
|
||||
|
||||
std::vector<ASTPointer<VariableDeclaration>> const& getMembers() const { return m_members; }
|
||||
|
||||
/// Checks that the members do not include any recursive structs and have valid types
|
||||
/// (e.g. no functions).
|
||||
void checkValidityOfMembers();
|
||||
|
||||
private:
|
||||
void checkMemberTypes();
|
||||
void checkRecursion();
|
||||
|
||||
std::vector<ASTPointer<VariableDeclaration>> m_members;
|
||||
};
|
||||
|
||||
@ -210,7 +217,6 @@ public:
|
||||
Declaration(_location, _name), m_typeName(_type) {}
|
||||
virtual void accept(ASTVisitor& _visitor) override;
|
||||
|
||||
bool isTypeGivenExplicitly() const { return bool(m_typeName); }
|
||||
TypeName* getTypeName() const { return m_typeName.get(); }
|
||||
|
||||
/// Returns the declared or inferred type. Can be an empty pointer if no type was explicitly
|
||||
@ -238,6 +244,7 @@ public:
|
||||
|
||||
/// Retrieve the element of the type hierarchy this node refers to. Can return an empty shared
|
||||
/// pointer until the types have been resolved using the @ref NameAndTypeResolver.
|
||||
/// If it returns an empty shared pointer after that, this indicates that the type was not found.
|
||||
virtual std::shared_ptr<Type> toType() const = 0;
|
||||
};
|
||||
|
||||
@ -263,8 +270,7 @@ private:
|
||||
};
|
||||
|
||||
/**
|
||||
* Name referring to a user-defined type (i.e. a struct).
|
||||
* @todo some changes are necessary if this is also used to refer to contract types later
|
||||
* Name referring to a user-defined type (i.e. a struct, contract, etc.).
|
||||
*/
|
||||
class UserDefinedTypeName: public TypeName
|
||||
{
|
||||
@ -275,13 +281,13 @@ public:
|
||||
virtual std::shared_ptr<Type> toType() const override { return Type::fromUserDefinedTypeName(*this); }
|
||||
|
||||
ASTString const& getName() const { return *m_name; }
|
||||
void setReferencedStruct(StructDefinition& _referencedStruct) { m_referencedStruct = &_referencedStruct; }
|
||||
StructDefinition const* getReferencedStruct() const { return m_referencedStruct; }
|
||||
void setReferencedDeclaration(Declaration& _referencedDeclaration) { m_referencedDeclaration = &_referencedDeclaration; }
|
||||
Declaration const* getReferencedDeclaration() const { return m_referencedDeclaration; }
|
||||
|
||||
private:
|
||||
ASTPointer<ASTString> m_name;
|
||||
|
||||
StructDefinition* m_referencedStruct;
|
||||
Declaration* m_referencedDeclaration;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <libsolidity/AST.h>
|
||||
#include <libsolidity/Scanner.h>
|
||||
#include <libsolidity/Parser.h>
|
||||
#include <libsolidity/GlobalContext.h>
|
||||
#include <libsolidity/NameAndTypeResolver.h>
|
||||
#include <libsolidity/Compiler.h>
|
||||
#include <libsolidity/CompilerStack.h>
|
||||
@ -45,7 +46,9 @@ void CompilerStack::parse()
|
||||
if (!m_scanner)
|
||||
BOOST_THROW_EXCEPTION(CompilerError() << errinfo_comment("Source not available."));
|
||||
m_contractASTNode = Parser().parse(m_scanner);
|
||||
NameAndTypeResolver().resolveNamesAndTypes(*m_contractASTNode);
|
||||
m_globalContext = make_shared<GlobalContext>();
|
||||
m_globalContext->setCurrentContract(*m_contractASTNode);
|
||||
NameAndTypeResolver(m_globalContext->getDeclarations()).resolveNamesAndTypes(*m_contractASTNode);
|
||||
m_parseSuccessful = true;
|
||||
}
|
||||
|
||||
|
@ -30,9 +30,11 @@
|
||||
namespace dev {
|
||||
namespace solidity {
|
||||
|
||||
class Scanner; // forward
|
||||
class ContractDefinition; // forward
|
||||
class Compiler; // forward
|
||||
// forward declarations
|
||||
class Scanner;
|
||||
class ContractDefinition;
|
||||
class Compiler;
|
||||
class GlobalContext;
|
||||
|
||||
/**
|
||||
* Easy to use and self-contained Solidity compiler with as few header dependencies as possible.
|
||||
@ -71,6 +73,7 @@ public:
|
||||
|
||||
private:
|
||||
std::shared_ptr<Scanner> m_scanner;
|
||||
std::shared_ptr<GlobalContext> m_globalContext;
|
||||
std::shared_ptr<ContractDefinition> m_contractASTNode;
|
||||
bool m_parseSuccessful;
|
||||
std::string m_interface;
|
||||
|
@ -167,7 +167,15 @@ bool ExpressionCompiler::visit(FunctionCall& _functionCall)
|
||||
BOOST_THROW_EXCEPTION(InternalCompilerError());
|
||||
Expression& firstArgument = *_functionCall.getArguments().front();
|
||||
firstArgument.accept(*this);
|
||||
appendTypeConversion(*firstArgument.getType(), *_functionCall.getType());
|
||||
if (firstArgument.getType()->getCategory() == Type::Category::CONTRACT &&
|
||||
_functionCall.getType()->getCategory() == Type::Category::INTEGER)
|
||||
{
|
||||
// explicit type conversion contract -> address, nothing to do.
|
||||
}
|
||||
else
|
||||
{
|
||||
appendTypeConversion(*firstArgument.getType(), *_functionCall.getType());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -466,7 +474,7 @@ void ExpressionCompiler::LValue::storeValue(Expression const& _expression, bool
|
||||
}
|
||||
}
|
||||
|
||||
void ExpressionCompiler::LValue::retrieveValueIfLValueNotRequested(const Expression& _expression)
|
||||
void ExpressionCompiler::LValue::retrieveValueIfLValueNotRequested(Expression const& _expression)
|
||||
{
|
||||
if (!_expression.lvalueRequested())
|
||||
{
|
||||
@ -475,7 +483,7 @@ void ExpressionCompiler::LValue::retrieveValueIfLValueNotRequested(const Express
|
||||
}
|
||||
}
|
||||
|
||||
void ExpressionCompiler::LValue::fromDeclaration( Expression const& _expression, Declaration const& _declaration)
|
||||
void ExpressionCompiler::LValue::fromDeclaration(Expression const& _expression, Declaration const& _declaration)
|
||||
{
|
||||
if (m_context->isLocalVariable(&_declaration))
|
||||
{
|
||||
|
70
GlobalContext.cpp
Normal file
70
GlobalContext.cpp
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
This file is part of cpp-ethereum.
|
||||
|
||||
cpp-ethereum 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.
|
||||
|
||||
cpp-ethereum 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/**
|
||||
* @author Christian <c@ethdev.com>
|
||||
* @date 2014
|
||||
* Container of the (implicit and explicit) global objects.
|
||||
*/
|
||||
|
||||
#include <memory>
|
||||
#include <libsolidity/GlobalContext.h>
|
||||
#include <libsolidity/AST.h>
|
||||
#include <libsolidity/Types.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace dev
|
||||
{
|
||||
namespace solidity
|
||||
{
|
||||
|
||||
GlobalContext::GlobalContext()
|
||||
{
|
||||
// CurrentContract this; // @todo type depends on context -> switch prior to entering contract
|
||||
// Message msg;
|
||||
// Transaction tx;
|
||||
// Block block;
|
||||
|
||||
//@todo type will be a custom complex type, maybe the same type class for msg tx and block.
|
||||
//addVariable("msg", );
|
||||
}
|
||||
|
||||
void GlobalContext::setCurrentContract(ContractDefinition const& _contract)
|
||||
{
|
||||
m_this = createVariable("this", make_shared<ContractType>(_contract));
|
||||
}
|
||||
|
||||
vector<Declaration*> GlobalContext::getDeclarations() const
|
||||
{
|
||||
vector<Declaration*> declarations;
|
||||
declarations.reserve(m_objects.size() + 1);
|
||||
for (ASTPointer<Declaration> const& declaration: m_objects)
|
||||
declarations.push_back(declaration.get());
|
||||
declarations.push_back(m_this.get());
|
||||
return declarations;
|
||||
}
|
||||
|
||||
ASTPointer<VariableDeclaration> GlobalContext::createVariable(const string& _name, shared_ptr<const Type> const& _type)
|
||||
{
|
||||
ASTPointer<VariableDeclaration> variable = make_shared<VariableDeclaration>(Location(), ASTPointer<TypeName>(),
|
||||
make_shared<ASTString>(_name));
|
||||
variable->setType(_type);
|
||||
return variable;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
61
GlobalContext.h
Normal file
61
GlobalContext.h
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
This file is part of cpp-ethereum.
|
||||
|
||||
cpp-ethereum 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.
|
||||
|
||||
cpp-ethereum 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
/**
|
||||
* @author Christian <c@ethdev.com>
|
||||
* @date 2014
|
||||
* Container of the (implicit and explicit) global objects.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <libsolidity/ASTForward.h>
|
||||
|
||||
namespace dev
|
||||
{
|
||||
namespace solidity
|
||||
{
|
||||
|
||||
class Type; // forward
|
||||
|
||||
/**
|
||||
* Container for all global objects which look like AST nodes, but are not part of the AST
|
||||
* that is currently being compiled.
|
||||
* @note must not be destroyed or moved during compilation as its objects can be referenced from
|
||||
* other objects.
|
||||
*/
|
||||
class GlobalContext: private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
GlobalContext();
|
||||
void setCurrentContract(ContractDefinition const& _contract);
|
||||
|
||||
std::vector<Declaration*> getDeclarations() const;
|
||||
|
||||
private:
|
||||
/// Creates a virtual variable declaration with the given name and type.
|
||||
static ASTPointer<VariableDeclaration> createVariable(std::string const& _name, std::shared_ptr<Type const> const& _type);
|
||||
|
||||
std::vector<ASTPointer<Declaration>> m_objects;
|
||||
ASTPointer<Declaration> m_this;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
@ -32,15 +32,20 @@ namespace solidity
|
||||
{
|
||||
|
||||
|
||||
NameAndTypeResolver::NameAndTypeResolver(std::vector<Declaration*> const& _globals)
|
||||
{
|
||||
for (Declaration* declaration: _globals)
|
||||
m_scopes[nullptr].registerDeclaration(*declaration);
|
||||
}
|
||||
|
||||
void NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract)
|
||||
{
|
||||
reset();
|
||||
DeclarationRegistrationHelper registrar(m_scopes, _contract);
|
||||
m_currentScope = &m_scopes[&_contract];
|
||||
for (ASTPointer<StructDefinition> const& structDef: _contract.getDefinedStructs())
|
||||
ReferencesResolver resolver(*structDef, *this, nullptr);
|
||||
for (ASTPointer<StructDefinition> const& structDef: _contract.getDefinedStructs())
|
||||
checkForRecursion(*structDef);
|
||||
structDef->checkValidityOfMembers();
|
||||
for (ASTPointer<VariableDeclaration> const& variable: _contract.getStateVariables())
|
||||
ReferencesResolver resolver(*variable, *this, nullptr);
|
||||
for (ASTPointer<FunctionDefinition> const& function: _contract.getDefinedFunctions())
|
||||
@ -73,30 +78,6 @@ Declaration* NameAndTypeResolver::getNameFromCurrentScope(ASTString const& _name
|
||||
return m_currentScope->resolveName(_name, _recursive);
|
||||
}
|
||||
|
||||
void NameAndTypeResolver::checkForRecursion(StructDefinition const& _struct)
|
||||
{
|
||||
set<StructDefinition const*> definitionsSeen;
|
||||
vector<StructDefinition const*> queue = {&_struct};
|
||||
while (!queue.empty())
|
||||
{
|
||||
StructDefinition const* def = queue.back();
|
||||
queue.pop_back();
|
||||
if (definitionsSeen.count(def))
|
||||
BOOST_THROW_EXCEPTION(ParserError() << errinfo_sourceLocation(def->getLocation())
|
||||
<< errinfo_comment("Recursive struct definition."));
|
||||
definitionsSeen.insert(def);
|
||||
for (ASTPointer<VariableDeclaration> const& member: def->getMembers())
|
||||
if (member->getType()->getCategory() == Type::Category::STRUCT)
|
||||
queue.push_back(dynamic_cast<UserDefinedTypeName&>(*member->getTypeName()).getReferencedStruct());
|
||||
}
|
||||
}
|
||||
|
||||
void NameAndTypeResolver::reset()
|
||||
{
|
||||
m_scopes.clear();
|
||||
m_currentScope = nullptr;
|
||||
}
|
||||
|
||||
DeclarationRegistrationHelper::DeclarationRegistrationHelper(map<ASTNode const*, Scope>& _scopes,
|
||||
ASTNode& _astRoot):
|
||||
m_scopes(_scopes), m_currentScope(&m_scopes[nullptr])
|
||||
@ -195,7 +176,11 @@ void ReferencesResolver::endVisit(VariableDeclaration& _variable)
|
||||
// endVisit because the internal type needs resolving if it is a user defined type
|
||||
// or mapping
|
||||
if (_variable.getTypeName())
|
||||
{
|
||||
_variable.setType(_variable.getTypeName()->toType());
|
||||
if (!_variable.getType())
|
||||
BOOST_THROW_EXCEPTION(_variable.getTypeName()->createTypeError("Invalid type name"));
|
||||
}
|
||||
else if (!m_allowLazyTypes)
|
||||
BOOST_THROW_EXCEPTION(_variable.createTypeError("Explicit type needed."));
|
||||
// otherwise we have a "var"-declaration whose type is resolved by the first assignment
|
||||
@ -221,11 +206,7 @@ bool ReferencesResolver::visit(UserDefinedTypeName& _typeName)
|
||||
if (!declaration)
|
||||
BOOST_THROW_EXCEPTION(DeclarationError() << errinfo_sourceLocation(_typeName.getLocation())
|
||||
<< errinfo_comment("Undeclared identifier."));
|
||||
StructDefinition* referencedStruct = dynamic_cast<StructDefinition*>(declaration);
|
||||
//@todo later, contracts are also valid types
|
||||
if (!referencedStruct)
|
||||
BOOST_THROW_EXCEPTION(_typeName.createTypeError("Identifier does not name a type name."));
|
||||
_typeName.setReferencedStruct(*referencedStruct);
|
||||
_typeName.setReferencedDeclaration(*declaration);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -41,8 +41,7 @@ namespace solidity
|
||||
class NameAndTypeResolver: private boost::noncopyable
|
||||
{
|
||||
public:
|
||||
NameAndTypeResolver() {}
|
||||
|
||||
explicit NameAndTypeResolver(std::vector<Declaration*> const& _globals);
|
||||
void resolveNamesAndTypes(ContractDefinition& _contract);
|
||||
|
||||
/// Resolves the given @a _name inside the scope @a _scope. If @a _scope is omitted,
|
||||
|
@ -683,7 +683,6 @@ Token::Value Scanner::scanNumber(char _charSeen)
|
||||
KEYWORD("switch", Token::SWITCH) \
|
||||
KEYWORD_GROUP('t') \
|
||||
KEYWORD("text", Token::TEXT) \
|
||||
KEYWORD("this", Token::THIS) \
|
||||
KEYWORD("true", Token::TRUE_LITERAL) \
|
||||
KEYWORD_GROUP('u') \
|
||||
KEYWORD("uint", Token::UINT) \
|
||||
|
1
Token.h
1
Token.h
@ -160,7 +160,6 @@ namespace solidity
|
||||
K(RETURNS, "returns", 0) \
|
||||
K(STRUCT, "struct", 0) \
|
||||
K(SWITCH, "switch", 0) \
|
||||
K(THIS, "this", 0) \
|
||||
K(VAR, "var", 0) \
|
||||
K(WHILE, "while", 0) \
|
||||
\
|
||||
|
30
Types.cpp
30
Types.cpp
@ -60,13 +60,24 @@ shared_ptr<Type> Type::fromElementaryTypeName(Token::Value _typeToken)
|
||||
|
||||
shared_ptr<Type> Type::fromUserDefinedTypeName(UserDefinedTypeName const& _typeName)
|
||||
{
|
||||
return make_shared<StructType>(*_typeName.getReferencedStruct());
|
||||
Declaration const* declaration = _typeName.getReferencedDeclaration();
|
||||
if (StructDefinition const* structDef = dynamic_cast<StructDefinition const*>(declaration))
|
||||
return make_shared<StructType>(*structDef);
|
||||
else if (FunctionDefinition const* function = dynamic_cast<FunctionDefinition const*>(declaration))
|
||||
return make_shared<FunctionType>(*function);
|
||||
else if (ContractDefinition const* contract = dynamic_cast<ContractDefinition const*>(declaration))
|
||||
return make_shared<ContractType>(*contract);
|
||||
return shared_ptr<Type>();
|
||||
}
|
||||
|
||||
shared_ptr<Type> Type::fromMapping(Mapping const& _typeName)
|
||||
{
|
||||
shared_ptr<Type const> keyType = _typeName.getKeyType().toType();
|
||||
if (!keyType)
|
||||
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Error resolving type name."));
|
||||
shared_ptr<Type const> valueType = _typeName.getValueType().toType();
|
||||
if (!valueType)
|
||||
BOOST_THROW_EXCEPTION(_typeName.getValueType().createTypeError("Invalid type name"));
|
||||
return make_shared<MappingType>(keyType, valueType);
|
||||
}
|
||||
|
||||
@ -201,6 +212,15 @@ u256 BoolType::literalValue(Literal const& _literal) const
|
||||
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Bool type constructed from non-boolean literal."));
|
||||
}
|
||||
|
||||
bool ContractType::isExplicitlyConvertibleTo(Type const& _convertTo) const
|
||||
{
|
||||
if (isImplicitlyConvertibleTo(_convertTo))
|
||||
return true;
|
||||
if (_convertTo.getCategory() == Category::INTEGER)
|
||||
return dynamic_cast<IntegerType const&>(_convertTo).isAddress();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ContractType::operator==(Type const& _other) const
|
||||
{
|
||||
if (_other.getCategory() != getCategory())
|
||||
@ -217,6 +237,11 @@ u256 ContractType::getStorageSize() const
|
||||
return max<u256>(1, size);
|
||||
}
|
||||
|
||||
string ContractType::toString() const
|
||||
{
|
||||
return "contract " + m_contract.getName();
|
||||
}
|
||||
|
||||
bool StructType::operator==(Type const& _other) const
|
||||
{
|
||||
if (_other.getCategory() != getCategory())
|
||||
@ -282,8 +307,7 @@ bool FunctionType::operator==(Type const& _other) const
|
||||
|
||||
string FunctionType::toString() const
|
||||
{
|
||||
//@todo nice string for function types
|
||||
return "function(...)returns(...)";
|
||||
return "function " + m_function.getName();
|
||||
}
|
||||
|
||||
bool MappingType::operator==(Type const& _other) const
|
||||
|
32
Types.h
32
Types.h
@ -106,6 +106,8 @@ public:
|
||||
/// @returns number of bytes required to hold this value in storage.
|
||||
/// For dynamically "allocated" types, it returns the size of the statically allocated head,
|
||||
virtual u256 getStorageSize() const { return 1; }
|
||||
/// Returns true if the type can be stored in storage.
|
||||
virtual bool canBeStored() const { return true; }
|
||||
/// Returns false if the type cannot live outside the storage, i.e. if it includes some mapping.
|
||||
virtual bool canLiveOutsideStorage() const { return true; }
|
||||
|
||||
@ -151,7 +153,7 @@ public:
|
||||
|
||||
virtual bool operator==(Type const& _other) const override;
|
||||
|
||||
virtual unsigned getCalldataEncodedSize() const { return m_bits / 8; }
|
||||
virtual unsigned getCalldataEncodedSize() const override { return m_bits / 8; }
|
||||
|
||||
virtual std::string toString() const override;
|
||||
virtual u256 literalValue(Literal const& _literal) const override;
|
||||
@ -197,10 +199,11 @@ class ContractType: public Type
|
||||
public:
|
||||
virtual Category getCategory() const override { return Category::CONTRACT; }
|
||||
ContractType(ContractDefinition const& _contract): m_contract(_contract) {}
|
||||
|
||||
/// Contracts can be converted to themselves and to addresses.
|
||||
virtual bool isExplicitlyConvertibleTo(Type const& _convertTo) const override;
|
||||
virtual bool operator==(Type const& _other) const override;
|
||||
virtual u256 getStorageSize() const;
|
||||
virtual std::string toString() const override { return "contract{...}"; }
|
||||
virtual u256 getStorageSize() const override;
|
||||
virtual std::string toString() const override;
|
||||
|
||||
private:
|
||||
ContractDefinition const& m_contract;
|
||||
@ -220,8 +223,8 @@ public:
|
||||
}
|
||||
|
||||
virtual bool operator==(Type const& _other) const override;
|
||||
virtual u256 getStorageSize() const;
|
||||
virtual bool canLiveOutsideStorage() const;
|
||||
virtual u256 getStorageSize() const override;
|
||||
virtual bool canLiveOutsideStorage() const override;
|
||||
virtual std::string toString() const override;
|
||||
|
||||
virtual MemberList const& getMembers() const override;
|
||||
@ -247,8 +250,9 @@ public:
|
||||
|
||||
virtual bool operator==(Type const& _other) const override;
|
||||
virtual std::string toString() const override;
|
||||
virtual u256 getStorageSize() const { BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Storage size of non-storable function type requested.")); }
|
||||
virtual bool canLiveOutsideStorage() const { return false; }
|
||||
virtual bool canBeStored() const override { return false; }
|
||||
virtual u256 getStorageSize() const override { BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Storage size of non-storable function type requested.")); }
|
||||
virtual bool canLiveOutsideStorage() const override { return false; }
|
||||
|
||||
private:
|
||||
FunctionDefinition const& m_function;
|
||||
@ -266,7 +270,7 @@ public:
|
||||
|
||||
virtual bool operator==(Type const& _other) const override;
|
||||
virtual std::string toString() const override;
|
||||
virtual bool canLiveOutsideStorage() const { return false; }
|
||||
virtual bool canLiveOutsideStorage() const override { return false; }
|
||||
|
||||
std::shared_ptr<Type const> getKeyType() const { return m_keyType; }
|
||||
std::shared_ptr<Type const> getValueType() const { return m_valueType; }
|
||||
@ -287,8 +291,9 @@ public:
|
||||
VoidType() {}
|
||||
|
||||
virtual std::string toString() const override { return "void"; }
|
||||
virtual u256 getStorageSize() const { BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Storage size of non-storable void type requested.")); }
|
||||
virtual bool canLiveOutsideStorage() const { return false; }
|
||||
virtual bool canBeStored() const override { return false; }
|
||||
virtual u256 getStorageSize() const override { BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Storage size of non-storable void type requested.")); }
|
||||
virtual bool canLiveOutsideStorage() const override { return false; }
|
||||
};
|
||||
|
||||
/**
|
||||
@ -304,8 +309,9 @@ public:
|
||||
std::shared_ptr<Type const> const& getActualType() const { return m_actualType; }
|
||||
|
||||
virtual bool operator==(Type const& _other) const override;
|
||||
virtual u256 getStorageSize() const { BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Storage size of non-storable type type requested.")); }
|
||||
virtual bool canLiveOutsideStorage() const { return false; }
|
||||
virtual bool canBeStored() const override { return false; }
|
||||
virtual u256 getStorageSize() const override { BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Storage size of non-storable type type requested.")); }
|
||||
virtual bool canLiveOutsideStorage() const override { return false; }
|
||||
virtual std::string toString() const override { return "type(" + m_actualType->toString() + ")"; }
|
||||
|
||||
private:
|
||||
|
Loading…
Reference in New Issue
Block a user