diff options
author | Alex Beregszaszi <alex@rtfs.hu> | 2017-07-01 17:09:24 +0800 |
---|---|---|
committer | Alex Beregszaszi <alex@rtfs.hu> | 2017-08-14 21:21:47 +0800 |
commit | 2a9ba937ba74ed8351b0590222ba2ac8a6e097c5 (patch) | |
tree | 70125a96fea1eb6541d2565485e0c120b8392ffb /libsolidity | |
parent | 4d9790b6d5a490d30ed55b69fa117bc568fa4c64 (diff) | |
download | dexon-solidity-2a9ba937ba74ed8351b0590222ba2ac8a6e097c5.tar.gz dexon-solidity-2a9ba937ba74ed8351b0590222ba2ac8a6e097c5.tar.zst dexon-solidity-2a9ba937ba74ed8351b0590222ba2ac8a6e097c5.zip |
Replace constant/payable with StateMutability in AST
Diffstat (limited to 'libsolidity')
-rw-r--r-- | libsolidity/ast/AST.h | 28 | ||||
-rw-r--r-- | libsolidity/ast/ASTEnums.h | 52 | ||||
-rw-r--r-- | libsolidity/ast/ASTForward.h | 1 | ||||
-rw-r--r-- | libsolidity/ast/Types.cpp | 38 | ||||
-rw-r--r-- | libsolidity/ast/Types.h | 18 | ||||
-rw-r--r-- | libsolidity/parsing/Parser.cpp | 54 | ||||
-rw-r--r-- | libsolidity/parsing/Parser.h | 5 | ||||
-rw-r--r-- | libsolidity/parsing/Token.h | 1 |
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); } |