aboutsummaryrefslogtreecommitdiffstats
path: root/libsolidity/ast
diff options
context:
space:
mode:
authorchriseth <c@ethdev.com>2016-09-28 03:37:32 +0800
committerchriseth <c@ethdev.com>2016-11-16 21:37:17 +0800
commitcc8583ec7d6fd86ca7e129475fde32b76d102e79 (patch)
treea2df35174d6d95734207add361db5d894fe8592f /libsolidity/ast
parentc811691861eb51520d9fd51d56770f14990b0320 (diff)
downloaddexon-solidity-cc8583ec7d6fd86ca7e129475fde32b76d102e79.tar.gz
dexon-solidity-cc8583ec7d6fd86ca7e129475fde32b76d102e79.tar.zst
dexon-solidity-cc8583ec7d6fd86ca7e129475fde32b76d102e79.zip
Function types.
Diffstat (limited to 'libsolidity/ast')
-rw-r--r--libsolidity/ast/AST.h35
-rw-r--r--libsolidity/ast/ASTForward.h1
-rw-r--r--libsolidity/ast/ASTJsonConverter.cpp14
-rw-r--r--libsolidity/ast/ASTJsonConverter.h2
-rw-r--r--libsolidity/ast/ASTPrinter.cpp12
-rw-r--r--libsolidity/ast/ASTPrinter.h2
-rw-r--r--libsolidity/ast/ASTVisitor.h4
-rw-r--r--libsolidity/ast/AST_accept.h20
-rw-r--r--libsolidity/ast/Types.cpp65
-rw-r--r--libsolidity/ast/Types.h10
10 files changed, 159 insertions, 6 deletions
diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h
index 1b42c499..a2b70fe9 100644
--- a/libsolidity/ast/AST.h
+++ b/libsolidity/ast/AST.h
@@ -823,6 +823,41 @@ private:
};
/**
+ * 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')"
*/
class Mapping: public TypeName
diff --git a/libsolidity/ast/ASTForward.h b/libsolidity/ast/ASTForward.h
index 59fc1b57..52bbf396 100644
--- a/libsolidity/ast/ASTForward.h
+++ b/libsolidity/ast/ASTForward.h
@@ -54,6 +54,7 @@ class MagicVariableDeclaration;
class TypeName;
class ElementaryTypeName;
class UserDefinedTypeName;
+class FunctionTypeName;
class Mapping;
class ArrayTypeName;
class Statement;
diff --git a/libsolidity/ast/ASTJsonConverter.cpp b/libsolidity/ast/ASTJsonConverter.cpp
index 3fce1180..717a80ee 100644
--- a/libsolidity/ast/ASTJsonConverter.cpp
+++ b/libsolidity/ast/ASTJsonConverter.cpp
@@ -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();
diff --git a/libsolidity/ast/ASTJsonConverter.h b/libsolidity/ast/ASTJsonConverter.h
index 7c7b37f8..0a71779c 100644
--- a/libsolidity/ast/ASTJsonConverter.h
+++ b/libsolidity/ast/ASTJsonConverter.h
@@ -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;
diff --git a/libsolidity/ast/ASTPrinter.cpp b/libsolidity/ast/ASTPrinter.cpp
index 27266968..053b9b82 100644
--- a/libsolidity/ast/ASTPrinter.cpp
+++ b/libsolidity/ast/ASTPrinter.cpp
@@ -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--;
diff --git a/libsolidity/ast/ASTPrinter.h b/libsolidity/ast/ASTPrinter.h
index f0ab1098..9f88a1fd 100644
--- a/libsolidity/ast/ASTPrinter.h
+++ b/libsolidity/ast/ASTPrinter.h
@@ -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;
diff --git a/libsolidity/ast/ASTVisitor.h b/libsolidity/ast/ASTVisitor.h
index 3a1b55d3..e72afe69 100644
--- a/libsolidity/ast/ASTVisitor.h
+++ b/libsolidity/ast/ASTVisitor.h
@@ -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); }
diff --git a/libsolidity/ast/AST_accept.h b/libsolidity/ast/AST_accept.h
index b5a3806b..f521e092 100644
--- a/libsolidity/ast/AST_accept.h
+++ b/libsolidity/ast/AST_accept.h
@@ -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))
diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp
index 6ad74d28..808b0c55 100644
--- a/libsolidity/ast/Types.cpp
+++ b/libsolidity/ast/Types.cpp
@@ -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, "");
diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h
index 082e16a6..358c7efc 100644
--- a/libsolidity/ast/Types.h
+++ b/libsolidity/ast/Types.h
@@ -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