aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Beregszaszi <alex@rtfs.hu>2017-07-01 17:09:24 +0800
committerAlex Beregszaszi <alex@rtfs.hu>2017-08-14 21:21:47 +0800
commit2a9ba937ba74ed8351b0590222ba2ac8a6e097c5 (patch)
tree70125a96fea1eb6541d2565485e0c120b8392ffb
parent4d9790b6d5a490d30ed55b69fa117bc568fa4c64 (diff)
downloaddexon-solidity-2a9ba937ba74ed8351b0590222ba2ac8a6e097c5.tar
dexon-solidity-2a9ba937ba74ed8351b0590222ba2ac8a6e097c5.tar.gz
dexon-solidity-2a9ba937ba74ed8351b0590222ba2ac8a6e097c5.tar.bz2
dexon-solidity-2a9ba937ba74ed8351b0590222ba2ac8a6e097c5.tar.lz
dexon-solidity-2a9ba937ba74ed8351b0590222ba2ac8a6e097c5.tar.xz
dexon-solidity-2a9ba937ba74ed8351b0590222ba2ac8a6e097c5.tar.zst
dexon-solidity-2a9ba937ba74ed8351b0590222ba2ac8a6e097c5.zip
Replace constant/payable with StateMutability in AST
-rw-r--r--libsolidity/ast/AST.h28
-rw-r--r--libsolidity/ast/ASTEnums.h52
-rw-r--r--libsolidity/ast/ASTForward.h1
-rw-r--r--libsolidity/ast/Types.cpp38
-rw-r--r--libsolidity/ast/Types.h18
-rw-r--r--libsolidity/parsing/Parser.cpp54
-rw-r--r--libsolidity/parsing/Parser.h5
-rw-r--r--libsolidity/parsing/Token.h1
8 files changed, 129 insertions, 68 deletions
diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h
index d32cf573..8a577c0c 100644
--- a/libsolidity/ast/AST.h
+++ b/libsolidity/ast/AST.h
@@ -28,6 +28,7 @@
#include <libsolidity/ast/Types.h>
#include <libsolidity/interface/Exceptions.h>
#include <libsolidity/ast/ASTAnnotations.h>
+#include <libsolidity/ast/ASTEnums.h>
#include <libevmasm/SourceLocation.h>
#include <libevmasm/Instruction.h>
@@ -584,21 +585,19 @@ public:
SourceLocation const& _location,
ASTPointer<ASTString> const& _name,
Declaration::Visibility _visibility,
+ StateMutability _stateMutability,
bool _isConstructor,
ASTPointer<ASTString> const& _documentation,
ASTPointer<ParameterList> const& _parameters,
- bool _isDeclaredConst,
std::vector<ASTPointer<ModifierInvocation>> const& _modifiers,
ASTPointer<ParameterList> const& _returnParameters,
- bool _isPayable,
ASTPointer<Block> const& _body
):
CallableDeclaration(_location, _name, _visibility, _parameters, _returnParameters),
Documented(_documentation),
ImplementationOptional(_body != nullptr),
+ m_stateMutability(_stateMutability),
m_isConstructor(_isConstructor),
- m_isDeclaredConst(_isDeclaredConst),
- m_isPayable(_isPayable),
m_functionModifiers(_modifiers),
m_body(_body)
{}
@@ -606,10 +605,11 @@ public:
virtual void accept(ASTVisitor& _visitor) override;
virtual void accept(ASTConstVisitor& _visitor) const override;
+ StateMutability stateMutability() const { return m_stateMutability; }
bool isConstructor() const { return m_isConstructor; }
bool isFallback() const { return name().empty(); }
- bool isDeclaredConst() const { return m_isDeclaredConst; }
- bool isPayable() const { return m_isPayable; }
+ bool isDeclaredConst() const { return m_stateMutability == StateMutability::View; }
+ bool isPayable() const { return m_stateMutability == StateMutability::Payable; }
std::vector<ASTPointer<ModifierInvocation>> const& modifiers() const { return m_functionModifiers; }
std::vector<ASTPointer<VariableDeclaration>> const& returnParameters() const { return m_returnParameters->parameters(); }
Block const& body() const { solAssert(m_body, ""); return *m_body; }
@@ -634,9 +634,8 @@ public:
virtual FunctionDefinitionAnnotation& annotation() const override;
private:
+ StateMutability m_stateMutability;
bool m_isConstructor;
- bool m_isDeclaredConst;
- bool m_isPayable;
std::vector<ASTPointer<ModifierInvocation>> m_functionModifiers;
ASTPointer<Block> m_body;
};
@@ -896,11 +895,10 @@ public:
ASTPointer<ParameterList> const& _parameterTypes,
ASTPointer<ParameterList> const& _returnTypes,
Declaration::Visibility _visibility,
- bool _isDeclaredConst,
- bool _isPayable
+ StateMutability _stateMutability
):
TypeName(_location), m_parameterTypes(_parameterTypes), m_returnTypes(_returnTypes),
- m_visibility(_visibility), m_isDeclaredConst(_isDeclaredConst), m_isPayable(_isPayable)
+ m_visibility(_visibility), m_stateMutability(_stateMutability)
{}
virtual void accept(ASTVisitor& _visitor) override;
virtual void accept(ASTConstVisitor& _visitor) const override;
@@ -914,15 +912,15 @@ public:
{
return m_visibility == Declaration::Visibility::Default ? Declaration::Visibility::Internal : m_visibility;
}
- bool isDeclaredConst() const { return m_isDeclaredConst; }
- bool isPayable() const { return m_isPayable; }
+ StateMutability stateMutability() const { return m_stateMutability; }
+ bool isDeclaredConst() const { return m_stateMutability == StateMutability::View; }
+ bool isPayable() const { return m_stateMutability == StateMutability::Payable; }
private:
ASTPointer<ParameterList> m_parameterTypes;
ASTPointer<ParameterList> m_returnTypes;
Declaration::Visibility m_visibility;
- bool m_isDeclaredConst;
- bool m_isPayable;
+ StateMutability m_stateMutability;
};
/**
diff --git a/libsolidity/ast/ASTEnums.h b/libsolidity/ast/ASTEnums.h
new file mode 100644
index 00000000..f7c75878
--- /dev/null
+++ b/libsolidity/ast/ASTEnums.h
@@ -0,0 +1,52 @@
+/*
+ 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/>.
+*/
+/**
+ * @date 2017
+ * Enums for AST classes.
+ */
+
+#pragma once
+
+#include <libsolidity/interface/Exceptions.h>
+
+#include <string>
+
+namespace dev
+{
+namespace solidity
+{
+
+// How a function can mutate the EVM state.
+enum class StateMutability { View, NonPayable, Payable };
+
+inline std::string stateMutabilityToString(StateMutability const& _stateMutability)
+{
+ switch(_stateMutability)
+ {
+ case StateMutability::View:
+ return "view";
+ case StateMutability::NonPayable:
+ return "nonpayable";
+ case StateMutability::Payable:
+ return "payable";
+ default:
+ solAssert(false, "Unknown state mutability.");
+ }
+}
+
+}
+}
diff --git a/libsolidity/ast/ASTForward.h b/libsolidity/ast/ASTForward.h
index cfeeaa58..15735368 100644
--- a/libsolidity/ast/ASTForward.h
+++ b/libsolidity/ast/ASTForward.h
@@ -95,6 +95,5 @@ using ASTPointer = std::shared_ptr<T>;
using ASTString = std::string;
-
}
}
diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp
index a66ccda5..35dddebb 100644
--- a/libsolidity/ast/Types.cpp
+++ b/libsolidity/ast/Types.cpp
@@ -2000,8 +2000,7 @@ TypePointer TupleType::closestTemporaryType(TypePointer const& _targetType) cons
FunctionType::FunctionType(FunctionDefinition const& _function, bool _isInternal):
m_kind(_isInternal ? Kind::Internal : Kind::External),
- m_isConstant(_function.isDeclaredConst()),
- m_isPayable(_isInternal ? false : _function.isPayable()),
+ m_stateMutability(_function.stateMutability()),
m_declaration(&_function)
{
TypePointers params;
@@ -2009,6 +2008,9 @@ FunctionType::FunctionType(FunctionDefinition const& _function, bool _isInternal
TypePointers retParams;
vector<string> retParamNames;
+ if (_isInternal && m_stateMutability == StateMutability::Payable)
+ m_stateMutability = StateMutability::NonPayable;
+
params.reserve(_function.parameters().size());
paramNames.reserve(_function.parameters().size());
for (ASTPointer<VariableDeclaration> const& var: _function.parameters())
@@ -2030,7 +2032,7 @@ FunctionType::FunctionType(FunctionDefinition const& _function, bool _isInternal
}
FunctionType::FunctionType(VariableDeclaration const& _varDecl):
- m_kind(Kind::External), m_isConstant(true), m_declaration(&_varDecl)
+ m_kind(Kind::External), m_stateMutability(StateMutability::View), m_declaration(&_varDecl)
{
TypePointers paramTypes;
vector<string> paramNames;
@@ -2090,7 +2092,7 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl):
}
FunctionType::FunctionType(EventDefinition const& _event):
- m_kind(Kind::Event), m_isConstant(true), m_declaration(&_event)
+ m_kind(Kind::Event), m_stateMutability(StateMutability::View), m_declaration(&_event)
{
TypePointers params;
vector<string> paramNames;
@@ -2107,14 +2109,10 @@ FunctionType::FunctionType(EventDefinition const& _event):
FunctionType::FunctionType(FunctionTypeName const& _typeName):
m_kind(_typeName.visibility() == VariableDeclaration::Visibility::External ? Kind::External : Kind::Internal),
- m_isConstant(_typeName.isDeclaredConst()),
- m_isPayable(_typeName.isPayable())
+ m_stateMutability(_typeName.stateMutability())
{
if (_typeName.isPayable())
- {
solAssert(m_kind == Kind::External, "Internal payable function type used.");
- solAssert(!m_isConstant, "Payable constant function");
- }
for (auto const& t: _typeName.parameterTypes())
{
solAssert(t->annotation().type, "Type not set for parameter.");
@@ -2241,8 +2239,8 @@ bool FunctionType::operator==(Type const& _other) const
FunctionType const& other = dynamic_cast<FunctionType const&>(_other);
if (
m_kind != other.m_kind ||
- m_isConstant != other.isConstant() ||
- m_isPayable != other.isPayable() ||
+ isConstant() != other.isConstant() ||
+ isPayable() != other.isPayable() ||
m_parameterTypes.size() != other.m_parameterTypes.size() ||
m_returnParameterTypes.size() != other.m_returnParameterTypes.size()
)
@@ -2304,9 +2302,9 @@ string FunctionType::toString(bool _short) const
for (auto it = m_parameterTypes.begin(); it != m_parameterTypes.end(); ++it)
name += (*it)->toString(_short) + (it + 1 == m_parameterTypes.end() ? "" : ",");
name += ")";
- if (m_isConstant)
+ if (isConstant())
name += " constant";
- if (m_isPayable)
+ if (isPayable())
name += " payable";
if (m_kind == Kind::External)
name += " external";
@@ -2420,8 +2418,8 @@ FunctionTypePointer FunctionType::interfaceFunctionType() const
m_kind,
m_arbitraryParameters,
m_declaration,
- m_isConstant,
- m_isPayable
+ isConstant(),
+ isPayable()
);
}
@@ -2438,7 +2436,7 @@ MemberList::MemberMap FunctionType::nativeMembers(ContractDefinition const*) con
MemberList::MemberMap members;
if (m_kind != Kind::BareDelegateCall && m_kind != Kind::DelegateCall)
{
- if (m_isPayable)
+ if (isPayable())
members.push_back(MemberList::Member(
"value",
make_shared<FunctionType>(
@@ -2604,8 +2602,8 @@ TypePointer FunctionType::copyAndSetGasOrValue(bool _setGas, bool _setValue) con
m_kind,
m_arbitraryParameters,
m_declaration,
- m_isConstant,
- m_isPayable,
+ isConstant(),
+ isPayable(),
m_gasSet || _setGas,
m_valueSet || _setValue,
m_bound
@@ -2654,8 +2652,8 @@ FunctionTypePointer FunctionType::asMemberFunction(bool _inLibrary, bool _bound)
kind,
m_arbitraryParameters,
m_declaration,
- m_isConstant,
- m_isPayable,
+ isConstant(),
+ isPayable(),
m_gasSet,
m_valueSet,
_bound
diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h
index 8c9232c6..64b07e4e 100644
--- a/libsolidity/ast/Types.h
+++ b/libsolidity/ast/Types.h
@@ -24,6 +24,7 @@
#include <libsolidity/interface/Exceptions.h>
#include <libsolidity/ast/ASTForward.h>
+#include <libsolidity/ast/ASTEnums.h>
#include <libsolidity/parsing/Token.h>
#include <libdevcore/Common.h>
@@ -932,10 +933,15 @@ public:
m_gasSet(_gasSet),
m_valueSet(_valueSet),
m_bound(_bound),
- m_isConstant(_isConstant),
- m_isPayable(_isPayable),
m_declaration(_declaration)
{
+ solAssert(!(_isConstant && _isPayable), "");
+ if (_isPayable)
+ m_stateMutability = StateMutability::Payable;
+ else if (_isConstant)
+ m_stateMutability = StateMutability::View;
+ else
+ m_stateMutability = StateMutability::NonPayable;
solAssert(
!m_bound || !m_parameterTypes.empty(),
"Attempted construction of bound function without self type"
@@ -985,6 +991,7 @@ public:
/// @returns true if the ABI is used for this call (only meaningful for external calls)
bool isBareCall() const;
Kind const& kind() const { return m_kind; }
+ StateMutability stateMutability() const { return m_stateMutability; }
/// @returns the external signature of this function type given the function name
std::string externalSignature() const;
/// @returns the external identifier of this function (the hash of the signature).
@@ -995,12 +1002,12 @@ public:
return *m_declaration;
}
bool hasDeclaration() const { return !!m_declaration; }
- bool isConstant() const { return m_isConstant; }
+ bool isConstant() const { return m_stateMutability == StateMutability::View; }
/// @returns true if the the result of this function only depends on its arguments
/// and it does not modify the state.
/// Currently, this will only return true for internal functions like keccak and ecrecover.
bool isPure() const;
- bool isPayable() const { return m_isPayable; }
+ bool isPayable() const { return m_stateMutability == StateMutability::Payable; }
/// @return A shared pointer of an ASTString.
/// Can contain a nullptr in which case indicates absence of documentation
ASTPointer<ASTString> documentation() const;
@@ -1033,13 +1040,12 @@ private:
std::vector<std::string> m_parameterNames;
std::vector<std::string> m_returnParameterNames;
Kind const m_kind;
+ StateMutability m_stateMutability = StateMutability::NonPayable;
/// true if the function takes an arbitrary number of arguments of arbitrary types
bool const m_arbitraryParameters = false;
bool const m_gasSet = false; ///< true iff the gas value to be used is on the stack
bool const m_valueSet = false; ///< true iff the value to be sent is on the stack
bool const m_bound = false; ///< true iff the function is called as arg1.fun(arg2, ..., argn)
- bool m_isConstant = false;
- bool m_isPayable = false;
Declaration const* m_declaration = nullptr;
};
diff --git a/libsolidity/parsing/Parser.cpp b/libsolidity/parsing/Parser.cpp
index 066e3a29..32bd0966 100644
--- a/libsolidity/parsing/Parser.cpp
+++ b/libsolidity/parsing/Parser.cpp
@@ -307,6 +307,19 @@ Declaration::Visibility Parser::parseVisibilitySpecifier(Token::Value _token)
return visibility;
}
+StateMutability Parser::parseStateMutability(Token::Value _token)
+{
+ StateMutability stateMutability(StateMutability::NonPayable);
+ if (_token == Token::Payable)
+ stateMutability = StateMutability::Payable;
+ else if (_token == Token::Constant)
+ stateMutability = StateMutability::View;
+ else
+ solAssert(false, "Invalid state mutability specifier.");
+ m_scanner->next();
+ return stateMutability;
+}
+
Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(bool _forceEmptyName, bool _allowModifiers)
{
FunctionHeaderParserResult result;
@@ -321,23 +334,7 @@ Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(bool _forceEmptyN
while (true)
{
Token::Value token = m_scanner->currentToken();
- if (token == Token::Constant)
- {
- if (result.isDeclaredConst)
- parserError(string("Multiple \"constant\" specifiers."));
-
- result.isDeclaredConst = true;
- m_scanner->next();
- }
- else if (m_scanner->currentToken() == Token::Payable)
- {
- if (result.isPayable)
- parserError(string("Multiple \"payable\" specifiers."));
-
- result.isPayable = true;
- m_scanner->next();
- }
- else if (_allowModifiers && token == Token::Identifier)
+ if (_allowModifiers && token == Token::Identifier)
{
// This can either be a modifier (function declaration) or the name of the
// variable (function type name plus variable).
@@ -364,6 +361,20 @@ Parser::FunctionHeaderParserResult Parser::parseFunctionHeader(bool _forceEmptyN
else
result.visibility = parseVisibilitySpecifier(token);
}
+ else if (Token::isStateMutabilitySpecifier(token))
+ {
+ if (result.stateMutability != StateMutability::NonPayable)
+ {
+ parserError(string(
+ "State mutability already specified as \"" +
+ stateMutabilityToString(result.stateMutability) +
+ "\"."
+ ));
+ m_scanner->next();
+ }
+ else
+ result.stateMutability = parseStateMutability(token);
+ }
else
break;
}
@@ -408,13 +419,12 @@ ASTPointer<ASTNode> Parser::parseFunctionDefinitionOrFunctionTypeStateVariable(A
return nodeFactory.createNode<FunctionDefinition>(
header.name,
header.visibility,
+ header.stateMutability,
c_isConstructor,
docstring,
header.parameters,
- header.isDeclaredConst,
header.modifiers,
header.returnParameters,
- header.isPayable,
block
);
}
@@ -425,8 +435,7 @@ ASTPointer<ASTNode> Parser::parseFunctionDefinitionOrFunctionTypeStateVariable(A
header.parameters,
header.returnParameters,
header.visibility,
- header.isDeclaredConst,
- header.isPayable
+ header.stateMutability
);
type = parseTypeNameSuffix(type, nodeFactory);
VarDeclParserOptions options;
@@ -751,8 +760,7 @@ ASTPointer<FunctionTypeName> Parser::parseFunctionType()
header.parameters,
header.returnParameters,
header.visibility,
- header.isDeclaredConst,
- header.isPayable
+ header.stateMutability
);
}
diff --git a/libsolidity/parsing/Parser.h b/libsolidity/parsing/Parser.h
index 82ab91a6..97e60baa 100644
--- a/libsolidity/parsing/Parser.h
+++ b/libsolidity/parsing/Parser.h
@@ -60,8 +60,7 @@ private:
ASTPointer<ParameterList> parameters;
ASTPointer<ParameterList> returnParameters;
Declaration::Visibility visibility = Declaration::Visibility::Default;
- bool isDeclaredConst = false;
- bool isPayable = false;
+ StateMutability stateMutability = StateMutability::NonPayable;
std::vector<ASTPointer<ModifierInvocation>> modifiers;
};
@@ -73,7 +72,7 @@ private:
ASTPointer<ContractDefinition> parseContractDefinition(Token::Value _expectedKind);
ASTPointer<InheritanceSpecifier> parseInheritanceSpecifier();
Declaration::Visibility parseVisibilitySpecifier(Token::Value _token);
- std::string visibilitySpecifierName(Declaration::Visibility _visibility);
+ StateMutability parseStateMutability(Token::Value _token);
FunctionHeaderParserResult parseFunctionHeader(bool _forceEmptyName, bool _allowModifiers);
ASTPointer<ASTNode> parseFunctionDefinitionOrFunctionTypeStateVariable(ASTString const* _contractName);
ASTPointer<FunctionDefinition> parseFunctionDefinition(ASTString const* _contractName);
diff --git a/libsolidity/parsing/Token.h b/libsolidity/parsing/Token.h
index 468cbcb7..efbe5e9e 100644
--- a/libsolidity/parsing/Token.h
+++ b/libsolidity/parsing/Token.h
@@ -290,6 +290,7 @@ public:
static bool isVisibilitySpecifier(Value op) { return isVariableVisibilitySpecifier(op) || op == External; }
static bool isVariableVisibilitySpecifier(Value op) { return op == Public || op == Private || op == Internal; }
static bool isLocationSpecifier(Value op) { return op == Memory || op == Storage; }
+ static bool isStateMutabilitySpecifier(Value op) { return op == Constant || op == Payable; }
static bool isEtherSubdenomination(Value op) { return op == SubWei || op == SubSzabo || op == SubFinney || op == SubEther; }
static bool isTimeSubdenomination(Value op) { return op == SubSecond || op == SubMinute || op == SubHour || op == SubDay || op == SubWeek || op == SubYear; }
static bool isReservedKeyword(Value op) { return (Abstract <= op && op <= TypeOf); }