From b51454692716f07e56f2f2a0f1ba5f4efe4bba8a Mon Sep 17 00:00:00 2001 From: Christian Date: Mon, 1 Dec 2014 15:22:45 +0100 Subject: [PATCH] Save the scope for every declaration. --- libsolidity/AST.h | 7 ++++++- .../{Scope.cpp => DeclarationContainer.cpp} | 10 +++++----- .../{Scope.h => DeclarationContainer.h} | 10 ++++++---- libsolidity/NameAndTypeResolver.cpp | 19 +++++++++---------- libsolidity/NameAndTypeResolver.h | 14 +++++++------- 5 files changed, 33 insertions(+), 27 deletions(-) rename libsolidity/{Scope.cpp => DeclarationContainer.cpp} (78%) rename libsolidity/{Scope.h => DeclarationContainer.h} (77%) diff --git a/libsolidity/AST.h b/libsolidity/AST.h index 81a12ad1a..68b5c8b80 100644 --- a/libsolidity/AST.h +++ b/libsolidity/AST.h @@ -88,11 +88,16 @@ public: Declaration(Location const& _location, ASTPointer const& _name): ASTNode(_location), m_name(_name) {} - /// Returns the declared name. + /// @returns the declared name. ASTString const& getName() const { return *m_name; } + /// @returns the scope this declaration resides in. Can be nullptr if it is the global scope. + /// Available only after name and type resolution step. + Declaration* getScope() const { return m_scope; } + void setScope(Declaration* const& _scope) { m_scope = _scope; } private: ASTPointer m_name; + Declaration* m_scope; }; /** diff --git a/libsolidity/Scope.cpp b/libsolidity/DeclarationContainer.cpp similarity index 78% rename from libsolidity/Scope.cpp rename to libsolidity/DeclarationContainer.cpp index 540c41204..6ea9c28c5 100644 --- a/libsolidity/Scope.cpp +++ b/libsolidity/DeclarationContainer.cpp @@ -20,7 +20,7 @@ * Scope - object that holds declaration of names. */ -#include +#include #include namespace dev @@ -28,7 +28,7 @@ namespace dev namespace solidity { -bool Scope::registerDeclaration(Declaration& _declaration) +bool DeclarationContainer::registerDeclaration(Declaration& _declaration) { if (m_declarations.find(_declaration.getName()) != m_declarations.end()) return false; @@ -36,13 +36,13 @@ bool Scope::registerDeclaration(Declaration& _declaration) return true; } -Declaration* Scope::resolveName(ASTString const& _name, bool _recursive) const +Declaration* DeclarationContainer::resolveName(ASTString const& _name, bool _recursive) const { auto result = m_declarations.find(_name); if (result != m_declarations.end()) return result->second; - if (_recursive && m_enclosingScope) - return m_enclosingScope->resolveName(_name, true); + if (_recursive && m_enclosingContainer) + return m_enclosingContainer->resolveName(_name, true); return nullptr; } diff --git a/libsolidity/Scope.h b/libsolidity/DeclarationContainer.h similarity index 77% rename from libsolidity/Scope.h rename to libsolidity/DeclarationContainer.h index 637c2d5ce..db6812890 100644 --- a/libsolidity/Scope.h +++ b/libsolidity/DeclarationContainer.h @@ -36,18 +36,20 @@ namespace solidity * Container that stores mappings betwee names and declarations. It also contains a link to the * enclosing scope. */ -class Scope +class DeclarationContainer { public: - explicit Scope(Scope* _enclosingScope = nullptr): m_enclosingScope(_enclosingScope) {} + explicit DeclarationContainer(Declaration* _enclosingDeclaration = nullptr, DeclarationContainer* _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. bool registerDeclaration(Declaration& _declaration); Declaration* resolveName(ASTString const& _name, bool _recursive = false) const; - Scope* getEnclosingScope() const { return m_enclosingScope; } + Declaration* getEnclosingDeclaration() const { return m_enclosingDeclaration; } private: - Scope* m_enclosingScope; + Declaration* m_enclosingDeclaration; + DeclarationContainer* m_enclosingContainer; std::map m_declarations; }; diff --git a/libsolidity/NameAndTypeResolver.cpp b/libsolidity/NameAndTypeResolver.cpp index 225f2a78a..d473348b8 100644 --- a/libsolidity/NameAndTypeResolver.cpp +++ b/libsolidity/NameAndTypeResolver.cpp @@ -78,9 +78,9 @@ Declaration* NameAndTypeResolver::getNameFromCurrentScope(ASTString const& _name return m_currentScope->resolveName(_name, _recursive); } -DeclarationRegistrationHelper::DeclarationRegistrationHelper(map& _scopes, +DeclarationRegistrationHelper::DeclarationRegistrationHelper(map& _scopes, ASTNode& _astRoot): - m_scopes(_scopes), m_currentScope(&m_scopes[nullptr]) + m_scopes(_scopes), m_currentScope(nullptr) { _astRoot.accept(*this); } @@ -135,31 +135,30 @@ bool DeclarationRegistrationHelper::visit(VariableDeclaration& _declaration) return true; } -void DeclarationRegistrationHelper::enterNewSubScope(ASTNode& _node) +void DeclarationRegistrationHelper::enterNewSubScope(Declaration& _declaration) { - map::iterator iter; + map::iterator iter; bool newlyAdded; - tie(iter, newlyAdded) = m_scopes.emplace(&_node, Scope(m_currentScope)); + tie(iter, newlyAdded) = m_scopes.emplace(&_declaration, DeclarationContainer(m_currentScope, &m_scopes[m_currentScope])); if (asserts(newlyAdded)) BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unable to add new scope.")); - m_currentScope = &iter->second; + m_currentScope = &_declaration; } void DeclarationRegistrationHelper::closeCurrentScope() { if (asserts(m_currentScope)) BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Closed non-existing scope.")); - m_currentScope = m_currentScope->getEnclosingScope(); + m_currentScope = m_scopes[m_currentScope].getEnclosingDeclaration(); } void DeclarationRegistrationHelper::registerDeclaration(Declaration& _declaration, bool _opensScope) { - if (asserts(m_currentScope)) - BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Declaration registered without scope.")); - if (!m_currentScope->registerDeclaration(_declaration)) + if (!m_scopes[m_currentScope].registerDeclaration(_declaration)) BOOST_THROW_EXCEPTION(DeclarationError() << errinfo_sourceLocation(_declaration.getLocation()) << errinfo_comment("Identifier already declared.")); //@todo the exception should also contain the location of the first declaration + _declaration.setScope(m_currentScope); if (_opensScope) enterNewSubScope(_declaration); } diff --git a/libsolidity/NameAndTypeResolver.h b/libsolidity/NameAndTypeResolver.h index 64f3c89db..797eca605 100644 --- a/libsolidity/NameAndTypeResolver.h +++ b/libsolidity/NameAndTypeResolver.h @@ -25,7 +25,7 @@ #include #include -#include +#include #include namespace dev @@ -61,9 +61,9 @@ private: /// Maps nodes declaring a scope to scopes, i.e. ContractDefinition and FunctionDeclaration, /// where nullptr denotes the global scope. Note that structs are not scope since they do /// not contain code. - std::map m_scopes; + std::map m_scopes; - Scope* m_currentScope; + DeclarationContainer* m_currentScope; }; /** @@ -73,7 +73,7 @@ private: class DeclarationRegistrationHelper: private ASTVisitor { public: - DeclarationRegistrationHelper(std::map& _scopes, ASTNode& _astRoot); + DeclarationRegistrationHelper(std::map& _scopes, ASTNode& _astRoot); private: bool visit(ContractDefinition& _contract); @@ -85,12 +85,12 @@ private: void endVisit(VariableDefinition& _variableDefinition); bool visit(VariableDeclaration& _declaration); - void enterNewSubScope(ASTNode& _node); + void enterNewSubScope(Declaration& _declaration); void closeCurrentScope(); void registerDeclaration(Declaration& _declaration, bool _opensScope); - std::map& m_scopes; - Scope* m_currentScope; + std::map& m_scopes; + Declaration* m_currentScope; FunctionDefinition* m_currentFunction; };