diff options
author | Christian <c@ethdev.com> | 2015-01-29 21:35:28 +0800 |
---|---|---|
committer | Christian <c@ethdev.com> | 2015-01-30 04:26:11 +0800 |
commit | 4a6ed84386ed7bc3abd2b4cf2441b29a5af38816 (patch) | |
tree | a4428b3bd31d3b05383b61e060cd768c4a7604db | |
parent | 3701543ae8dd8ffbfd58e5648d45699468f10a55 (diff) | |
download | dexon-solidity-4a6ed84386ed7bc3abd2b4cf2441b29a5af38816.tar dexon-solidity-4a6ed84386ed7bc3abd2b4cf2441b29a5af38816.tar.gz dexon-solidity-4a6ed84386ed7bc3abd2b4cf2441b29a5af38816.tar.bz2 dexon-solidity-4a6ed84386ed7bc3abd2b4cf2441b29a5af38816.tar.lz dexon-solidity-4a6ed84386ed7bc3abd2b4cf2441b29a5af38816.tar.xz dexon-solidity-4a6ed84386ed7bc3abd2b4cf2441b29a5af38816.tar.zst dexon-solidity-4a6ed84386ed7bc3abd2b4cf2441b29a5af38816.zip |
Parsing of events.
-rw-r--r-- | AST.cpp | 14 | ||||
-rwxr-xr-x | AST.h | 48 | ||||
-rw-r--r-- | ASTForward.h | 1 | ||||
-rw-r--r-- | ASTPrinter.cpp | 12 | ||||
-rw-r--r-- | ASTPrinter.h | 2 | ||||
-rw-r--r-- | ASTVisitor.h | 4 | ||||
-rw-r--r-- | AST_accept.h | 20 | ||||
-rw-r--r-- | NameAndTypeResolver.cpp | 8 | ||||
-rw-r--r-- | NameAndTypeResolver.h | 1 | ||||
-rw-r--r-- | Parser.cpp | 59 | ||||
-rw-r--r-- | Parser.h | 13 | ||||
-rw-r--r-- | Token.h | 2 | ||||
-rw-r--r-- | Types.cpp | 16 | ||||
-rw-r--r-- | Types.h | 4 |
14 files changed, 180 insertions, 24 deletions
@@ -271,6 +271,20 @@ void ModifierInvocation::checkTypeRequirements() BOOST_THROW_EXCEPTION(createTypeError("Invalid type for argument in modifier invocation.")); } +void EventDefinition::checkTypeRequirements() +{ + int numIndexed = 0; + for (ASTPointer<VariableDeclaration> const& var: getParameters()) + { + if (var->isIndexed()) + numIndexed++; + if (!var->getType()->canLiveOutsideStorage()) + BOOST_THROW_EXCEPTION(var->createTypeError("Type is required to live outside storage.")); + } + if (numIndexed > 3) + BOOST_THROW_EXCEPTION(createTypeError("More than 3 indexed arguments for event.")); +} + void Block::checkTypeRequirements() { for (shared_ptr<Statement> const& statement: m_statements) @@ -202,13 +202,15 @@ public: std::vector<ASTPointer<StructDefinition>> const& _definedStructs, std::vector<ASTPointer<VariableDeclaration>> const& _stateVariables, std::vector<ASTPointer<FunctionDefinition>> const& _definedFunctions, - std::vector<ASTPointer<ModifierDefinition>> const& _functionModifiers): + std::vector<ASTPointer<ModifierDefinition>> const& _functionModifiers, + std::vector<ASTPointer<EventDefinition>> const& _events): Declaration(_location, _name), Documented(_documentation), m_baseContracts(_baseContracts), m_definedStructs(_definedStructs), m_stateVariables(_stateVariables), m_definedFunctions(_definedFunctions), - m_functionModifiers(_functionModifiers) + m_functionModifiers(_functionModifiers), + m_events(_events) {} virtual void accept(ASTVisitor& _visitor) override; @@ -219,6 +221,7 @@ public: std::vector<ASTPointer<VariableDeclaration>> const& getStateVariables() const { return m_stateVariables; } std::vector<ASTPointer<ModifierDefinition>> const& getFunctionModifiers() const { return m_functionModifiers; } std::vector<ASTPointer<FunctionDefinition>> const& getDefinedFunctions() const { return m_definedFunctions; } + std::vector<ASTPointer<EventDefinition>> const& getEvents() const { return m_events; } virtual TypePointer getType(ContractDefinition const* m_currentContract) const override; @@ -248,6 +251,7 @@ private: std::vector<ASTPointer<VariableDeclaration>> m_stateVariables; std::vector<ASTPointer<FunctionDefinition>> m_definedFunctions; std::vector<ASTPointer<ModifierDefinition>> m_functionModifiers; + std::vector<ASTPointer<EventDefinition>> m_events; std::vector<ContractDefinition const*> m_linearizedBaseContracts; mutable std::unique_ptr<std::vector<std::pair<FixedHash<4>, FunctionTypePointer>>> m_interfaceFunctionList; @@ -380,8 +384,10 @@ class VariableDeclaration: public Declaration { public: VariableDeclaration(Location const& _location, ASTPointer<TypeName> const& _type, - ASTPointer<ASTString> const& _name, bool _isPublic, bool _isStateVar = false): - Declaration(_location, _name), m_typeName(_type), m_isPublic(_isPublic), m_isStateVariable(_isStateVar) {} + ASTPointer<ASTString> const& _name, bool _isPublic, bool _isStateVar = false, + bool _isIndexed = false): + Declaration(_location, _name), m_typeName(_type), + m_isPublic(_isPublic), m_isStateVariable(_isStateVar), m_isIndexed(_isIndexed) {} virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTConstVisitor& _visitor) const override; @@ -396,12 +402,14 @@ public: bool isLocalVariable() const { return !!dynamic_cast<FunctionDefinition const*>(getScope()); } bool isPublic() const { return m_isPublic; } bool isStateVariable() const { return m_isStateVariable; } + bool isIndexed() const { return m_isIndexed; } private: ASTPointer<TypeName> m_typeName; ///< can be empty ("var") bool m_isPublic; ///< Whether there is an accessor for it or not bool m_isStateVariable; ///< Whether or not this is a contract state variable + bool m_isIndexed; ///< Whether this is an indexed variable (used by events). std::shared_ptr<Type const> m_type; ///< derived type, initially empty }; @@ -429,7 +437,6 @@ public: virtual TypePointer getType(ContractDefinition const* = nullptr) const override; - void checkTypeRequirements(); private: @@ -461,6 +468,37 @@ private: }; /** + * Definition of a (loggable) event. + */ +class EventDefinition: public Declaration, public Documented +{ +public: + EventDefinition(Location const& _location, + ASTPointer<ASTString> const& _name, + ASTPointer<ASTString> const& _documentation, + ASTPointer<ParameterList> const& _parameters): + Declaration(_location, _name), Documented(_documentation), m_parameters(_parameters) {} + + virtual void accept(ASTVisitor& _visitor) override; + virtual void accept(ASTConstVisitor& _visitor) const override; + + std::vector<ASTPointer<VariableDeclaration>> const& getParameters() const { return m_parameters->getParameters(); } + ParameterList const& getParameterList() const { return *m_parameters; } + Block const& getBody() const { return *m_body; } + + virtual TypePointer getType(ContractDefinition const* = nullptr) const override + { + return std::make_shared<FunctionType>(*this); + } + + void checkTypeRequirements(); + +private: + ASTPointer<ParameterList> m_parameters; + ASTPointer<Block> m_body; +}; + +/** * Pseudo AST node that is used as declaration for "this", "msg", "tx", "block" and the global * functions when such an identifier is encountered. Will never have a valid location in the source code. */ diff --git a/ASTForward.h b/ASTForward.h index aa5cd49c..22015f26 100644 --- a/ASTForward.h +++ b/ASTForward.h @@ -45,6 +45,7 @@ class FunctionDefinition; class VariableDeclaration; class ModifierDefinition; class ModifierInvocation; +class EventDefinition; class MagicVariableDeclaration; class TypeName; class ElementaryTypeName; diff --git a/ASTPrinter.cpp b/ASTPrinter.cpp index 05b24c63..949740e8 100644 --- a/ASTPrinter.cpp +++ b/ASTPrinter.cpp @@ -108,6 +108,13 @@ bool ASTPrinter::visit(ModifierInvocation const& _node) return goDeeper(); } +bool ASTPrinter::visit(EventDefinition const& _node) +{ + writeLine("EventDefinition \"" + _node.getName() + "\""); + printSourcePart(_node); + return goDeeper(); +} + bool ASTPrinter::visit(TypeName const& _node) { writeLine("TypeName"); @@ -365,6 +372,11 @@ void ASTPrinter::endVisit(ModifierInvocation const&) m_indentation--; } +void ASTPrinter::endVisit(EventDefinition const&) +{ + m_indentation--; +} + void ASTPrinter::endVisit(TypeName const&) { m_indentation--; diff --git a/ASTPrinter.h b/ASTPrinter.h index 77025b2d..ebc163e3 100644 --- a/ASTPrinter.h +++ b/ASTPrinter.h @@ -51,6 +51,7 @@ public: bool visit(VariableDeclaration const& _node) override; bool visit(ModifierDefinition const& _node) override; bool visit(ModifierInvocation const& _node) override; + bool visit(EventDefinition const& _node) override; bool visit(TypeName const& _node) override; bool visit(ElementaryTypeName const& _node) override; bool visit(UserDefinedTypeName const& _node) override; @@ -89,6 +90,7 @@ public: void endVisit(VariableDeclaration const&) override; void endVisit(ModifierDefinition const&) override; void endVisit(ModifierInvocation const&) override; + void endVisit(EventDefinition const&) override; void endVisit(TypeName const&) override; void endVisit(ElementaryTypeName const&) override; void endVisit(UserDefinedTypeName const&) override; diff --git a/ASTVisitor.h b/ASTVisitor.h index 53fbd191..29490277 100644 --- a/ASTVisitor.h +++ b/ASTVisitor.h @@ -52,6 +52,7 @@ public: virtual bool visit(VariableDeclaration&) { return true; } virtual bool visit(ModifierDefinition&) { return true; } virtual bool visit(ModifierInvocation&) { return true; } + virtual bool visit(EventDefinition&) { return true; } virtual bool visit(TypeName&) { return true; } virtual bool visit(ElementaryTypeName&) { return true; } virtual bool visit(UserDefinedTypeName&) { return true; } @@ -92,6 +93,7 @@ public: virtual void endVisit(VariableDeclaration&) { } virtual void endVisit(ModifierDefinition&) { } virtual void endVisit(ModifierInvocation&) { } + virtual void endVisit(EventDefinition&) { } virtual void endVisit(TypeName&) { } virtual void endVisit(ElementaryTypeName&) { } virtual void endVisit(UserDefinedTypeName&) { } @@ -136,6 +138,7 @@ public: virtual bool visit(VariableDeclaration const&) { return true; } virtual bool visit(ModifierDefinition const&) { return true; } virtual bool visit(ModifierInvocation const&) { return true; } + virtual bool visit(EventDefinition const&) { return true; } virtual bool visit(TypeName const&) { return true; } virtual bool visit(ElementaryTypeName const&) { return true; } virtual bool visit(UserDefinedTypeName const&) { return true; } @@ -176,6 +179,7 @@ public: virtual void endVisit(VariableDeclaration const&) { } virtual void endVisit(ModifierDefinition const&) { } virtual void endVisit(ModifierInvocation const&) { } + virtual void endVisit(EventDefinition const&) { } virtual void endVisit(TypeName const&) { } virtual void endVisit(ElementaryTypeName const&) { } virtual void endVisit(UserDefinedTypeName const&) { } diff --git a/AST_accept.h b/AST_accept.h index 481b150b..38108cd7 100644 --- a/AST_accept.h +++ b/AST_accept.h @@ -64,8 +64,9 @@ void ContractDefinition::accept(ASTVisitor& _visitor) listAccept(m_baseContracts, _visitor); listAccept(m_definedStructs, _visitor); listAccept(m_stateVariables, _visitor); - listAccept(m_definedFunctions, _visitor); + listAccept(m_events, _visitor); listAccept(m_functionModifiers, _visitor); + listAccept(m_definedFunctions, _visitor); } _visitor.endVisit(*this); } @@ -77,8 +78,9 @@ void ContractDefinition::accept(ASTConstVisitor& _visitor) const listAccept(m_baseContracts, _visitor); listAccept(m_definedStructs, _visitor); listAccept(m_stateVariables, _visitor); - listAccept(m_definedFunctions, _visitor); + listAccept(m_events, _visitor); listAccept(m_functionModifiers, _visitor); + listAccept(m_definedFunctions, _visitor); } _visitor.endVisit(*this); } @@ -219,6 +221,20 @@ void ModifierInvocation::accept(ASTConstVisitor& _visitor) const _visitor.endVisit(*this); } +void EventDefinition::accept(ASTVisitor& _visitor) +{ + if (_visitor.visit(*this)) + m_parameters->accept(_visitor); + _visitor.endVisit(*this); +} + +void EventDefinition::accept(ASTConstVisitor& _visitor) const +{ + if (_visitor.visit(*this)) + m_parameters->accept(_visitor); + _visitor.endVisit(*this); +} + void TypeName::accept(ASTVisitor& _visitor) { _visitor.visit(*this); diff --git a/NameAndTypeResolver.cpp b/NameAndTypeResolver.cpp index 43201fe1..75df637c 100644 --- a/NameAndTypeResolver.cpp +++ b/NameAndTypeResolver.cpp @@ -60,6 +60,8 @@ void NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract) ReferencesResolver resolver(*structDef, *this, &_contract, nullptr); for (ASTPointer<VariableDeclaration> const& variable: _contract.getStateVariables()) ReferencesResolver resolver(*variable, *this, &_contract, nullptr); + for (ASTPointer<EventDefinition> const& event: _contract.getEvents()) + ReferencesResolver resolver(*event, *this, &_contract, nullptr); for (ASTPointer<ModifierDefinition> const& modifier: _contract.getFunctionModifiers()) { m_currentScope = &m_scopes[modifier.get()]; @@ -259,6 +261,12 @@ bool DeclarationRegistrationHelper::visit(VariableDeclaration& _declaration) return true; } +bool DeclarationRegistrationHelper::visit(EventDefinition& _event) +{ + registerDeclaration(_event, false); + return true; +} + void DeclarationRegistrationHelper::enterNewSubScope(Declaration const& _declaration) { map<ASTNode const*, DeclarationContainer>::iterator iter; diff --git a/NameAndTypeResolver.h b/NameAndTypeResolver.h index ba327a59..4555491f 100644 --- a/NameAndTypeResolver.h +++ b/NameAndTypeResolver.h @@ -104,6 +104,7 @@ private: void endVisit(ModifierDefinition& _modifier); void endVisit(VariableDefinition& _variableDefinition); bool visit(VariableDeclaration& _declaration); + bool visit(EventDefinition& _event); void enterNewSubScope(Declaration const& _declaration); void closeCurrentScope(); @@ -122,6 +122,7 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition() vector<ASTPointer<VariableDeclaration>> stateVariables; vector<ASTPointer<FunctionDefinition>> functions; vector<ASTPointer<ModifierDefinition>> modifiers; + vector<ASTPointer<EventDefinition>> events; if (m_scanner->getCurrentToken() == Token::IS) do { @@ -149,19 +150,23 @@ ASTPointer<ContractDefinition> Parser::parseContractDefinition() else if (currentToken == Token::IDENTIFIER || currentToken == Token::MAPPING || Token::isElementaryTypeName(currentToken)) { - bool const allowVar = false; - stateVariables.push_back(parseVariableDeclaration(allowVar, visibilityIsPublic, true)); + VarDeclParserOptions options; + options.isPublic = visibilityIsPublic; + options.isStateVariable = true; + stateVariables.push_back(parseVariableDeclaration(options)); expectToken(Token::SEMICOLON); } else if (currentToken == Token::MODIFIER) modifiers.push_back(parseModifierDefinition()); + else if (currentToken == Token::EVENT) + events.push_back(parseEventDefinition()); else BOOST_THROW_EXCEPTION(createParserError("Function, variable, struct or modifier declaration expected.")); } nodeFactory.markEndPosition(); expectToken(Token::RBRACE); return nodeFactory.createNode<ContractDefinition>(name, docString, baseContracts, structs, - stateVariables, functions, modifiers); + stateVariables, functions, modifiers, events); } ASTPointer<InheritanceSpecifier> Parser::parseInheritanceSpecifier() @@ -236,8 +241,7 @@ ASTPointer<StructDefinition> Parser::parseStructDefinition() expectToken(Token::LBRACE); while (m_scanner->getCurrentToken() != Token::RBRACE) { - bool const allowVar = false; - members.push_back(parseVariableDeclaration(allowVar)); + members.push_back(parseVariableDeclaration()); expectToken(Token::SEMICOLON); } nodeFactory.markEndPosition(); @@ -245,12 +249,20 @@ ASTPointer<StructDefinition> Parser::parseStructDefinition() return nodeFactory.createNode<StructDefinition>(name, members); } -ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(bool _allowVar, bool _isPublic, bool _isStateVariable) +ASTPointer<VariableDeclaration> Parser::parseVariableDeclaration(VarDeclParserOptions const& _options) { ASTNodeFactory nodeFactory(*this); - ASTPointer<TypeName> type = parseTypeName(_allowVar); + ASTPointer<TypeName> type = parseTypeName(_options.allowVar); + bool isIndexed = false; + if (_options.allowIndexed && m_scanner->getCurrentToken() == Token::INDEXED) + { + isIndexed = true; + m_scanner->next(); + } nodeFactory.markEndPosition(); - return nodeFactory.createNode<VariableDeclaration>(type, expectIdentifierToken(), _isPublic, _isStateVariable); + return nodeFactory.createNode<VariableDeclaration>(type, expectIdentifierToken(), + _options.isPublic, _options.isStateVariable, + isIndexed); } ASTPointer<ModifierDefinition> Parser::parseModifierDefinition() @@ -280,6 +292,23 @@ ASTPointer<ModifierDefinition> Parser::parseModifierDefinition() return nodeFactory.createNode<ModifierDefinition>(name, docstring, parameters, block); } +ASTPointer<EventDefinition> Parser::parseEventDefinition() +{ + ASTNodeFactory nodeFactory(*this); + ASTPointer<ASTString> docstring; + if (m_scanner->getCurrentCommentLiteral() != "") + docstring = make_shared<ASTString>(m_scanner->getCurrentCommentLiteral()); + + expectToken(Token::EVENT); + ASTPointer<ASTString> name(expectIdentifierToken()); + ASTPointer<ParameterList> parameters; + if (m_scanner->getCurrentToken() == Token::LPAREN) + parameters = parseParameterList(true, true); + nodeFactory.markEndPosition(); + expectToken(Token::SEMICOLON); + return nodeFactory.createNode<EventDefinition>(name, docstring, parameters); +} + ASTPointer<ModifierInvocation> Parser::parseModifierInvocation() { ASTNodeFactory nodeFactory(*this); @@ -352,19 +381,20 @@ ASTPointer<Mapping> Parser::parseMapping() return nodeFactory.createNode<Mapping>(keyType, valueType); } -ASTPointer<ParameterList> Parser::parseParameterList(bool _allowEmpty) +ASTPointer<ParameterList> Parser::parseParameterList(bool _allowEmpty, bool _allowIndexed) { ASTNodeFactory nodeFactory(*this); vector<ASTPointer<VariableDeclaration>> parameters; + VarDeclParserOptions options; + options.allowIndexed = _allowIndexed; expectToken(Token::LPAREN); if (!_allowEmpty || m_scanner->getCurrentToken() != Token::RPAREN) { - bool const allowVar = false; - parameters.push_back(parseVariableDeclaration(allowVar)); + parameters.push_back(parseVariableDeclaration(options)); while (m_scanner->getCurrentToken() != Token::RPAREN) { expectToken(Token::COMMA); - parameters.push_back(parseVariableDeclaration(allowVar)); + parameters.push_back(parseVariableDeclaration(options)); } } nodeFactory.markEndPosition(); @@ -506,8 +536,9 @@ ASTPointer<Statement> Parser::parseVarDefOrExprStmt() ASTPointer<VariableDefinition> Parser::parseVariableDefinition() { ASTNodeFactory nodeFactory(*this); - bool const allowVar = true; - ASTPointer<VariableDeclaration> variable = parseVariableDeclaration(allowVar); + VarDeclParserOptions options; + options.allowVar = true; + ASTPointer<VariableDeclaration> variable = parseVariableDeclaration(options); ASTPointer<Expression> value; if (m_scanner->getCurrentToken() == Token::ASSIGN) { @@ -45,6 +45,14 @@ private: /// End position of the current token int getEndPosition() const; + struct VarDeclParserOptions { + VarDeclParserOptions() {} + bool allowVar = false; + bool isPublic = false; + bool isStateVariable = false; + bool allowIndexed = false; + }; + ///@{ ///@name Parsing functions for the AST nodes ASTPointer<ImportDirective> parseImportDirective(); @@ -52,13 +60,14 @@ private: ASTPointer<InheritanceSpecifier> parseInheritanceSpecifier(); ASTPointer<FunctionDefinition> parseFunctionDefinition(bool _isPublic, ASTString const* _contractName); ASTPointer<StructDefinition> parseStructDefinition(); - ASTPointer<VariableDeclaration> parseVariableDeclaration(bool _allowVar, bool _isPublic = false, bool _isStateVar = false); + ASTPointer<VariableDeclaration> parseVariableDeclaration(VarDeclParserOptions const& _options = VarDeclParserOptions()); ASTPointer<ModifierDefinition> parseModifierDefinition(); + ASTPointer<EventDefinition> parseEventDefinition(); ASTPointer<ModifierInvocation> parseModifierInvocation(); ASTPointer<Identifier> parseIdentifier(); ASTPointer<TypeName> parseTypeName(bool _allowVar); ASTPointer<Mapping> parseMapping(); - ASTPointer<ParameterList> parseParameterList(bool _allowEmpty = true); + ASTPointer<ParameterList> parseParameterList(bool _allowEmpty = true, bool _allowIndexed = false); ASTPointer<Block> parseBlock(); ASTPointer<Statement> parseStatement(); ASTPointer<IfStatement> parseIfStatement(); @@ -153,7 +153,9 @@ namespace solidity K(DEFAULT, "default", 0) \ K(DO, "do", 0) \ K(ELSE, "else", 0) \ + K(EVENT, "event", 0) \ K(IS, "is", 0) \ + K(INDEXED, "indexed", 0) \ K(FOR, "for", 0) \ K(FUNCTION, "function", 0) \ K(IF, "if", 0) \ @@ -633,6 +633,22 @@ FunctionType::FunctionType(VariableDeclaration const& _varDecl): swap(retParamNames, m_returnParameterNames); } +FunctionType::FunctionType(const EventDefinition& _event): + m_location(Location::EVENT), m_declaration(&_event) +{ + TypePointers params; + vector<string> paramNames; + params.reserve(_event.getParameters().size()); + paramNames.reserve(_event.getParameters().size()); + for (ASTPointer<VariableDeclaration> const& var: _event.getParameters()) + { + paramNames.push_back(var->getName()); + params.push_back(var->getType()); + } + swap(params, m_parameterTypes); + swap(paramNames, m_parameterNames); +} + bool FunctionType::operator==(Type const& _other) const { if (_other.getCategory() != getCategory()) @@ -350,16 +350,18 @@ public: /// INTERNAL: jump tag, EXTERNAL: contract address + function identifier, /// BARE: contract address (non-abi contract call) /// OTHERS: special virtual function, nothing on the stack + /// @todo This documentation is outdated, and Location should rather be named "Type" enum class Location { INTERNAL, EXTERNAL, CREATION, SEND, SHA3, SUICIDE, ECRECOVER, SHA256, RIPEMD160, - LOG0, LOG1, LOG2, LOG3, LOG4, + LOG0, LOG1, LOG2, LOG3, LOG4, EVENT, SET_GAS, SET_VALUE, BLOCKHASH, BARE }; virtual Category getCategory() const override { return Category::FUNCTION; } explicit FunctionType(FunctionDefinition const& _function, bool _isInternal = true); explicit FunctionType(VariableDeclaration const& _varDecl); + explicit FunctionType(EventDefinition const& _event); FunctionType(strings const& _parameterTypes, strings const& _returnParameterTypes, Location _location = Location::INTERNAL): FunctionType(parseElementaryTypeVector(_parameterTypes), parseElementaryTypeVector(_returnParameterTypes), |