From 2a5c2578bd7e07326412ac0345ed5f5283908ccb Mon Sep 17 00:00:00 2001 From: Liana Husikyan Date: Mon, 9 Feb 2015 02:06:30 +0100 Subject: [PATCH] - implemented Empty parameter name story. Now the name of input/return parameters of function can be not specified. - added appropriate tests Conflicts: test/SolidityEndToEndTest.cpp test/SolidityNameAndTypeResolution.cpp --- AST.cpp | 19 +++++++++++++++---- AST.h | 2 +- DeclarationContainer.cpp | 4 ++++ DeclarationContainer.h | 4 ++-- Parser.cpp | 20 ++++++++++++++++---- Parser.h | 1 + 6 files changed, 39 insertions(+), 11 deletions(-) diff --git a/AST.cpp b/AST.cpp index 6f5b1f387..dbc326642 100644 --- a/AST.cpp +++ b/AST.cpp @@ -58,10 +58,21 @@ void ContractDefinition::checkTypeRequirements() BOOST_THROW_EXCEPTION(constructor->getReturnParameterList()->createTypeError( "Non-empty \"returns\" directive for constructor.")); - FunctionDefinition const* fallbackFunction = getFallbackFunction(); - if (fallbackFunction && fallbackFunction->getScope() == this && !fallbackFunction->getParameters().empty()) - BOOST_THROW_EXCEPTION(fallbackFunction->getParameterList().createTypeError( - "Fallback function cannot take parameters.")); + FunctionDefinition const* fallbackFunction = nullptr; + for (ASTPointer const& function: getDefinedFunctions()) + { + if (function->getName().empty()) + { + if (fallbackFunction) + BOOST_THROW_EXCEPTION(DeclarationError() << errinfo_comment("Only one fallback function is allowed.")); + else + { + fallbackFunction = function.get(); + if (!fallbackFunction->getParameters().empty()) + BOOST_THROW_EXCEPTION(fallbackFunction->getParameterList().createTypeError("Fallback function cannot take parameters.")); + } + } + } for (ASTPointer const& modifier: getFunctionModifiers()) modifier->checkTypeRequirements(); diff --git a/AST.h b/AST.h index 47f2a40ca..98f28afb0 100644 --- a/AST.h +++ b/AST.h @@ -250,7 +250,7 @@ public: /// Returns the constructor or nullptr if no constructor was specified. FunctionDefinition const* getConstructor() const; - /// Returns the fallback function or nullptr if no constructor was specified. + /// Returns the fallback function or nullptr if no fallback function was specified. FunctionDefinition const* getFallbackFunction() const; private: diff --git a/DeclarationContainer.cpp b/DeclarationContainer.cpp index c7081bc78..2e810a4cf 100644 --- a/DeclarationContainer.cpp +++ b/DeclarationContainer.cpp @@ -30,6 +30,9 @@ namespace solidity bool DeclarationContainer::registerDeclaration(Declaration const& _declaration, bool _update) { + if (_declaration.getName().empty()) + return true; + if (!_update && m_declarations.find(_declaration.getName()) != m_declarations.end()) return false; m_declarations[_declaration.getName()] = &_declaration; @@ -38,6 +41,7 @@ bool DeclarationContainer::registerDeclaration(Declaration const& _declaration, Declaration const* DeclarationContainer::resolveName(ASTString const& _name, bool _recursive) const { + solAssert(!_name.empty(), "Attempt to resolve empty name."); auto result = m_declarations.find(_name); if (result != m_declarations.end()) return result->second; diff --git a/DeclarationContainer.h b/DeclarationContainer.h index e4b793259..1216fcef2 100644 --- a/DeclarationContainer.h +++ b/DeclarationContainer.h @@ -42,8 +42,8 @@ public: explicit DeclarationContainer(Declaration const* _enclosingDeclaration = nullptr, DeclarationContainer const* _enclosingContainer = nullptr): m_enclosingDeclaration(_enclosingDeclaration), m_enclosingContainer(_enclosingContainer) {} - /// Registers the declaration in the scope unless its name is already declared. - /// @returns true iff it was not yet declared. + /// Registers the declaration in the scope unless its name is already declared or the name is empty. + /// @returns false if the name was already declared. bool registerDeclaration(Declaration const& _declaration, bool _update = false); Declaration const* resolveName(ASTString const& _name, bool _recursive = false) const; Declaration const* getEnclosingDeclaration() const { return m_enclosingDeclaration; } diff --git a/Parser.cpp b/Parser.cpp index d8c15c36d..2f5b18a04 100644 --- a/Parser.cpp +++ b/Parser.cpp @@ -268,17 +268,28 @@ ASTPointer Parser::parseVariableDeclaration(VarDeclParserOp ASTNodeFactory nodeFactory(*this); ASTPointer type = parseTypeName(_options.allowVar); bool isIndexed = false; + ASTPointer identifier; Token::Value token = m_scanner->getCurrentToken(); + Declaration::Visibility visibility(Declaration::Visibility::DEFAULT); + if (_options.isStateVariable && Token::isVisibilitySpecifier(token)) + visibility = parseVisibilitySpecifier(token); if (_options.allowIndexed && token == Token::INDEXED) { isIndexed = true; m_scanner->next(); } - Declaration::Visibility visibility(Declaration::Visibility::DEFAULT); - if (_options.isStateVariable && Token::isVisibilitySpecifier(token)) - visibility = parseVisibilitySpecifier(token); + if (_options.allowEmptyName && m_scanner->getCurrentToken() != Token::IDENTIFIER) + { + identifier = make_shared(""); + nodeFactory.setEndPositionFromNode(type); + } + else + { + nodeFactory.markEndPosition(); + identifier = expectIdentifierToken(); + } nodeFactory.markEndPosition(); - return nodeFactory.createNode(type, expectIdentifierToken(), + return nodeFactory.createNode(type, identifier, visibility, _options.isStateVariable, isIndexed); } @@ -402,6 +413,7 @@ ASTPointer Parser::parseParameterList(bool _allowEmpty, bool _all vector> parameters; VarDeclParserOptions options; options.allowIndexed = _allowIndexed; + options.allowEmptyName = true; expectToken(Token::LPAREN); if (!_allowEmpty || m_scanner->getCurrentToken() != Token::RPAREN) { diff --git a/Parser.h b/Parser.h index 19e0af1aa..5816fec40 100644 --- a/Parser.h +++ b/Parser.h @@ -50,6 +50,7 @@ private: bool allowVar = false; bool isStateVariable = false; bool allowIndexed = false; + bool allowEmptyName = false; }; ///@{