mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Function types.
This commit is contained in:
@@ -822,6 +822,41 @@ private:
|
||||
std::vector<ASTString> m_namePath;
|
||||
};
|
||||
|
||||
/**
|
||||
* A literal function type. Its source form is "function (paramType1, paramType2) internal / external returns (retType1, retType2)"
|
||||
*/
|
||||
class FunctionTypeName: public TypeName
|
||||
{
|
||||
public:
|
||||
FunctionTypeName(
|
||||
SourceLocation const& _location,
|
||||
ASTPointer<ParameterList> const& _parameterTypes,
|
||||
ASTPointer<ParameterList> const& _returnTypes,
|
||||
Declaration::Visibility _visibility,
|
||||
bool _isDeclaredConst,
|
||||
bool _isPayable
|
||||
):
|
||||
TypeName(_location), m_parameterTypes(_parameterTypes), m_returnTypes(_returnTypes),
|
||||
m_visibility(_visibility), m_isDeclaredConst(_isDeclaredConst), m_isPayable(_isPayable)
|
||||
{}
|
||||
virtual void accept(ASTVisitor& _visitor) override;
|
||||
virtual void accept(ASTConstVisitor& _visitor) const override;
|
||||
|
||||
std::vector<ASTPointer<VariableDeclaration>> const& parameterTypes() const { return m_parameterTypes->parameters(); }
|
||||
std::vector<ASTPointer<VariableDeclaration>> const& returnParameterTypes() const { return m_returnTypes->parameters(); }
|
||||
|
||||
Declaration::Visibility visibility() const { return m_visibility; }
|
||||
bool isDeclaredConst() const { return m_isDeclaredConst; }
|
||||
bool isPayable() const { return m_isPayable; }
|
||||
|
||||
private:
|
||||
ASTPointer<ParameterList> m_parameterTypes;
|
||||
ASTPointer<ParameterList> m_returnTypes;
|
||||
Declaration::Visibility m_visibility;
|
||||
bool m_isDeclaredConst;
|
||||
bool m_isPayable;
|
||||
};
|
||||
|
||||
/**
|
||||
* A mapping type. Its source form is "mapping('keyType' => 'valueType')"
|
||||
*/
|
||||
|
||||
@@ -54,6 +54,7 @@ class MagicVariableDeclaration;
|
||||
class TypeName;
|
||||
class ElementaryTypeName;
|
||||
class UserDefinedTypeName;
|
||||
class FunctionTypeName;
|
||||
class Mapping;
|
||||
class ArrayTypeName;
|
||||
class Statement;
|
||||
|
||||
@@ -226,6 +226,15 @@ bool ASTJsonConverter::visit(UserDefinedTypeName const& _node)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ASTJsonConverter::visit(FunctionTypeName const& _node)
|
||||
{
|
||||
addJsonNode(_node, "FunctionTypeName", {
|
||||
make_pair("payable", _node.isPayable()),
|
||||
make_pair("constant", _node.isDeclaredConst())
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ASTJsonConverter::visit(Mapping const& _node)
|
||||
{
|
||||
addJsonNode(_node, "Mapping", {}, true);
|
||||
@@ -507,6 +516,11 @@ void ASTJsonConverter::endVisit(UserDefinedTypeName const&)
|
||||
{
|
||||
}
|
||||
|
||||
void ASTJsonConverter::endVisit(FunctionTypeName const&)
|
||||
{
|
||||
goUp();
|
||||
}
|
||||
|
||||
void ASTJsonConverter::endVisit(Mapping const&)
|
||||
{
|
||||
goUp();
|
||||
|
||||
@@ -69,6 +69,7 @@ public:
|
||||
bool visit(TypeName const& _node) override;
|
||||
bool visit(ElementaryTypeName const& _node) override;
|
||||
bool visit(UserDefinedTypeName const& _node) override;
|
||||
bool visit(FunctionTypeName const& _node) override;
|
||||
bool visit(Mapping const& _node) override;
|
||||
bool visit(ArrayTypeName const& _node) override;
|
||||
bool visit(InlineAssembly const& _node) override;
|
||||
@@ -114,6 +115,7 @@ public:
|
||||
void endVisit(TypeName const&) override;
|
||||
void endVisit(ElementaryTypeName const&) override;
|
||||
void endVisit(UserDefinedTypeName const&) override;
|
||||
void endVisit(FunctionTypeName const&) override;
|
||||
void endVisit(Mapping const&) override;
|
||||
void endVisit(ArrayTypeName const&) override;
|
||||
void endVisit(InlineAssembly const&) override;
|
||||
|
||||
@@ -164,6 +164,13 @@ bool ASTPrinter::visit(UserDefinedTypeName const& _node)
|
||||
return goDeeper();
|
||||
}
|
||||
|
||||
bool ASTPrinter::visit(FunctionTypeName const& _node)
|
||||
{
|
||||
writeLine("FunctionTypeName");
|
||||
printSourcePart(_node);
|
||||
return goDeeper();
|
||||
}
|
||||
|
||||
bool ASTPrinter::visit(Mapping const& _node)
|
||||
{
|
||||
writeLine("Mapping");
|
||||
@@ -442,6 +449,11 @@ void ASTPrinter::endVisit(UserDefinedTypeName const&)
|
||||
m_indentation--;
|
||||
}
|
||||
|
||||
void ASTPrinter::endVisit(FunctionTypeName const&)
|
||||
{
|
||||
m_indentation--;
|
||||
}
|
||||
|
||||
void ASTPrinter::endVisit(Mapping const&)
|
||||
{
|
||||
m_indentation--;
|
||||
|
||||
@@ -63,6 +63,7 @@ public:
|
||||
bool visit(TypeName const& _node) override;
|
||||
bool visit(ElementaryTypeName const& _node) override;
|
||||
bool visit(UserDefinedTypeName const& _node) override;
|
||||
bool visit(FunctionTypeName const& _node) override;
|
||||
bool visit(Mapping const& _node) override;
|
||||
bool visit(ArrayTypeName const& _node) override;
|
||||
bool visit(InlineAssembly const& _node) override;
|
||||
@@ -106,6 +107,7 @@ public:
|
||||
void endVisit(TypeName const&) override;
|
||||
void endVisit(ElementaryTypeName const&) override;
|
||||
void endVisit(UserDefinedTypeName const&) override;
|
||||
void endVisit(FunctionTypeName const&) override;
|
||||
void endVisit(Mapping const&) override;
|
||||
void endVisit(ArrayTypeName const&) override;
|
||||
void endVisit(InlineAssembly const&) override;
|
||||
|
||||
@@ -61,6 +61,7 @@ public:
|
||||
virtual bool visit(TypeName& _node) { return visitNode(_node); }
|
||||
virtual bool visit(ElementaryTypeName& _node) { return visitNode(_node); }
|
||||
virtual bool visit(UserDefinedTypeName& _node) { return visitNode(_node); }
|
||||
virtual bool visit(FunctionTypeName& _node) { return visitNode(_node); }
|
||||
virtual bool visit(Mapping& _node) { return visitNode(_node); }
|
||||
virtual bool visit(ArrayTypeName& _node) { return visitNode(_node); }
|
||||
virtual bool visit(InlineAssembly& _node) { return visitNode(_node); }
|
||||
@@ -106,6 +107,7 @@ public:
|
||||
virtual void endVisit(TypeName& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(ElementaryTypeName& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(UserDefinedTypeName& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(FunctionTypeName& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(Mapping& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(ArrayTypeName& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(InlineAssembly& _node) { endVisitNode(_node); }
|
||||
@@ -163,6 +165,7 @@ public:
|
||||
virtual bool visit(TypeName const& _node) { return visitNode(_node); }
|
||||
virtual bool visit(ElementaryTypeName const& _node) { return visitNode(_node); }
|
||||
virtual bool visit(UserDefinedTypeName const& _node) { return visitNode(_node); }
|
||||
virtual bool visit(FunctionTypeName const& _node) { return visitNode(_node); }
|
||||
virtual bool visit(Mapping const& _node) { return visitNode(_node); }
|
||||
virtual bool visit(ArrayTypeName const& _node) { return visitNode(_node); }
|
||||
virtual bool visit(Block const& _node) { return visitNode(_node); }
|
||||
@@ -208,6 +211,7 @@ public:
|
||||
virtual void endVisit(TypeName const& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(ElementaryTypeName const& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(UserDefinedTypeName const& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(FunctionTypeName const& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(Mapping const& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(ArrayTypeName const& _node) { endVisitNode(_node); }
|
||||
virtual void endVisit(Block const& _node) { endVisitNode(_node); }
|
||||
|
||||
@@ -327,6 +327,26 @@ void UserDefinedTypeName::accept(ASTConstVisitor& _visitor) const
|
||||
_visitor.endVisit(*this);
|
||||
}
|
||||
|
||||
void FunctionTypeName::accept(ASTVisitor& _visitor)
|
||||
{
|
||||
if (_visitor.visit(*this))
|
||||
{
|
||||
m_parameterTypes->accept(_visitor);
|
||||
m_returnTypes->accept(_visitor);
|
||||
}
|
||||
_visitor.endVisit(*this);
|
||||
}
|
||||
|
||||
void FunctionTypeName::accept(ASTConstVisitor& _visitor) const
|
||||
{
|
||||
if (_visitor.visit(*this))
|
||||
{
|
||||
m_parameterTypes->accept(_visitor);
|
||||
m_returnTypes->accept(_visitor);
|
||||
}
|
||||
_visitor.endVisit(*this);
|
||||
}
|
||||
|
||||
void Mapping::accept(ASTVisitor& _visitor)
|
||||
{
|
||||
if (_visitor.visit(*this))
|
||||
|
||||
@@ -1805,6 +1805,23 @@ FunctionType::FunctionType(EventDefinition const& _event):
|
||||
swap(paramNames, m_parameterNames);
|
||||
}
|
||||
|
||||
FunctionType::FunctionType(FunctionTypeName const& _typeName):
|
||||
m_location(_typeName.visibility() == VariableDeclaration::Visibility::External ? Location::External : Location::Internal),
|
||||
m_isConstant(_typeName.isDeclaredConst()),
|
||||
m_isPayable(_typeName.isPayable())
|
||||
{
|
||||
for (auto const& t: _typeName.parameterTypes())
|
||||
{
|
||||
solAssert(t->annotation().type, "Type not set for parameter.");
|
||||
m_parameterTypes.push_back(t->annotation().type);
|
||||
}
|
||||
for (auto const& t: _typeName.returnParameterTypes())
|
||||
{
|
||||
solAssert(t->annotation().type, "Type not set for return parameter.");
|
||||
m_returnParameterTypes.push_back(t->annotation().type);
|
||||
}
|
||||
}
|
||||
|
||||
FunctionTypePointer FunctionType::newExpressionType(ContractDefinition const& _contract)
|
||||
{
|
||||
FunctionDefinition const* constructor = _contract.constructor();
|
||||
@@ -1885,17 +1902,47 @@ string FunctionType::toString(bool _short) const
|
||||
string name = "function (";
|
||||
for (auto it = m_parameterTypes.begin(); it != m_parameterTypes.end(); ++it)
|
||||
name += (*it)->toString(_short) + (it + 1 == m_parameterTypes.end() ? "" : ",");
|
||||
name += ") returns (";
|
||||
name += ") ";
|
||||
if (m_isConstant)
|
||||
name += "constant ";
|
||||
if (m_isPayable)
|
||||
name += "payable ";
|
||||
if (m_location == Location::External)
|
||||
name += "external ";
|
||||
name += "returns (";
|
||||
for (auto it = m_returnParameterTypes.begin(); it != m_returnParameterTypes.end(); ++it)
|
||||
name += (*it)->toString(_short) + (it + 1 == m_returnParameterTypes.end() ? "" : ",");
|
||||
return name + ")";
|
||||
}
|
||||
|
||||
unsigned FunctionType::calldataEncodedSize(bool _padded) const
|
||||
{
|
||||
unsigned size = storageBytes();
|
||||
if (_padded)
|
||||
size = ((size + 31) / 32) * 32;
|
||||
return size;
|
||||
}
|
||||
|
||||
u256 FunctionType::storageSize() const
|
||||
{
|
||||
BOOST_THROW_EXCEPTION(
|
||||
InternalCompilerError()
|
||||
<< errinfo_comment("Storage size of non-storable function type requested."));
|
||||
if (m_location == Location::External || m_location == Location::Internal)
|
||||
return 1;
|
||||
else
|
||||
BOOST_THROW_EXCEPTION(
|
||||
InternalCompilerError()
|
||||
<< errinfo_comment("Storage size of non-storable function type requested."));
|
||||
}
|
||||
|
||||
unsigned FunctionType::storageBytes() const
|
||||
{
|
||||
if (m_location == Location::External)
|
||||
return 20 + 4;
|
||||
else if (m_location == Location::Internal)
|
||||
return 8; // it should really not be possible to create larger programs
|
||||
else
|
||||
BOOST_THROW_EXCEPTION(
|
||||
InternalCompilerError()
|
||||
<< errinfo_comment("Storage size of non-storable function type requested."));
|
||||
}
|
||||
|
||||
unsigned FunctionType::sizeOnStack() const
|
||||
@@ -2018,6 +2065,16 @@ MemberList::MemberMap FunctionType::nativeMembers(ContractDefinition const*) con
|
||||
}
|
||||
}
|
||||
|
||||
TypePointer FunctionType::interfaceType(bool _inLibrary) const
|
||||
{
|
||||
if (m_location != Location::External && m_location != Location::Internal)
|
||||
return TypePointer();
|
||||
if (_inLibrary)
|
||||
return shared_from_this();
|
||||
else
|
||||
return make_shared<FixedBytesType>(storageBytes());
|
||||
}
|
||||
|
||||
bool FunctionType::canTakeArguments(TypePointers const& _argumentTypes, TypePointer const& _selfType) const
|
||||
{
|
||||
solAssert(!bound() || _selfType, "");
|
||||
|
||||
@@ -821,6 +821,8 @@ public:
|
||||
explicit FunctionType(VariableDeclaration const& _varDecl);
|
||||
/// Creates the function type of an event.
|
||||
explicit FunctionType(EventDefinition const& _event);
|
||||
/// Creates the type of a function type name.
|
||||
explicit FunctionType(FunctionTypeName const& _typeName);
|
||||
/// Function type constructor to be used for a plain type (not derived from a declaration).
|
||||
FunctionType(
|
||||
strings const& _parameterTypes,
|
||||
@@ -891,11 +893,15 @@ public:
|
||||
|
||||
virtual bool operator==(Type const& _other) const override;
|
||||
virtual std::string toString(bool _short) const override;
|
||||
virtual bool canBeStored() const override { return false; }
|
||||
virtual unsigned calldataEncodedSize(bool _padded) const override;
|
||||
virtual bool canBeStored() const override { return m_location == Location::Internal || m_location == Location::External; }
|
||||
virtual u256 storageSize() const override;
|
||||
virtual bool canLiveOutsideStorage() const override { return false; }
|
||||
virtual unsigned storageBytes() const override;
|
||||
virtual bool isValueType() const override { return true; }
|
||||
virtual bool canLiveOutsideStorage() const override { return m_location == Location::Internal || m_location == Location::External; }
|
||||
virtual unsigned sizeOnStack() const override;
|
||||
virtual MemberList::MemberMap nativeMembers(ContractDefinition const* _currentScope) const override;
|
||||
virtual TypePointer interfaceType(bool _inLibrary) const override;
|
||||
|
||||
/// @returns TypePointer of a new FunctionType object. All input/return parameters are an
|
||||
/// appropriate external types (i.e. the interfaceType()s) of input/return parameters of
|
||||
|
||||
Reference in New Issue
Block a user