diff options
author | Christian <c@ethdev.com> | 2014-10-13 21:07:21 +0800 |
---|---|---|
committer | Christian <c@ethdev.com> | 2014-10-13 23:02:21 +0800 |
commit | 4f791179640fdcfbbd62c4c7a2a5273081b7b742 (patch) | |
tree | 7c7576b991884befde24473b5f6370b8afa83b2f /NameAndTypeResolver.cpp | |
parent | 98bdd7429974521946a1aa3bffa038fc515f745c (diff) | |
download | dexon-solidity-4f791179640fdcfbbd62c4c7a2a5273081b7b742.tar.gz dexon-solidity-4f791179640fdcfbbd62c4c7a2a5273081b7b742.tar.zst dexon-solidity-4f791179640fdcfbbd62c4c7a2a5273081b7b742.zip |
Name resolution.
Diffstat (limited to 'NameAndTypeResolver.cpp')
-rw-r--r-- | NameAndTypeResolver.cpp | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/NameAndTypeResolver.cpp b/NameAndTypeResolver.cpp new file mode 100644 index 00000000..c4f0612b --- /dev/null +++ b/NameAndTypeResolver.cpp @@ -0,0 +1,142 @@ +#include <libsolidity/NameAndTypeResolver.h> + +#include <libsolidity/AST.h> +#include <boost/assert.hpp> + +namespace dev { +namespace solidity { + + +class NameAndTypeResolver::ScopeHelper { +public: + ScopeHelper(NameAndTypeResolver& _resolver, ASTString const& _name, ASTNode& _declaration) + : m_resolver(_resolver) + { + m_resolver.registerName(_name, _declaration); + m_resolver.enterNewSubScope(_declaration); + } + ~ScopeHelper() + { + m_resolver.closeCurrentScope(); + } + +private: + NameAndTypeResolver& m_resolver; +}; + + +NameAndTypeResolver::NameAndTypeResolver() +{ +} + +void NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract) +{ + reset(); + + handleContract(_contract); +} + +void NameAndTypeResolver::handleContract(ContractDefinition& _contract) +{ + ScopeHelper scopeHelper(*this, _contract.getName(), _contract); + + for (ptr<VariableDeclaration> const& variable : _contract.getStateVariables()) + registerName(variable->getName(), *variable); + // @todo structs + + for (ptr<FunctionDefinition> const& function : _contract.getDefinedFunctions()) + handleFunction(*function); + + // @todo resolve names used in mappings +} + +void NameAndTypeResolver::reset() +{ + m_scopes.clear(); + m_globalScope = Scope(); + m_currentScope = &m_globalScope; +} + +void NameAndTypeResolver::handleFunction(FunctionDefinition& _function) +{ + ScopeHelper scopeHelper(*this, _function.getName(), _function); + + // @todo resolve names used in mappings + for (ptr<VariableDeclaration> const& variable : _function.getParameters()) + registerName(variable->getName(), *variable); + if (_function.hasReturnParameters()) + for (ptr<VariableDeclaration> const& variable : _function.getReturnParameters()) + registerName(variable->getName(), *variable); + handleFunctionBody(_function.getBody()); +} + +void NameAndTypeResolver::handleFunctionBody(Block& _functionBody) +{ + registerVariablesInFunction(_functionBody); + resolveReferencesInFunction(_functionBody); +} + +void NameAndTypeResolver::registerVariablesInFunction(Block& _functionBody) +{ + class VariableDeclarationFinder : public ASTVisitor { + public: + VariableDeclarationFinder(NameAndTypeResolver& _resolver) : m_resolver(_resolver) {} + virtual bool visit(VariableDeclaration& _variable) override { + m_resolver.registerName(_variable.getName(), _variable); + return false; + } + private: + NameAndTypeResolver& m_resolver; + }; + + VariableDeclarationFinder declarationFinder(*this); + _functionBody.accept(declarationFinder); +} + +void NameAndTypeResolver::resolveReferencesInFunction(Block& _functionBody) +{ + class ReferencesResolver : public ASTVisitor { + public: + ReferencesResolver(NameAndTypeResolver& _resolver) : m_resolver(_resolver) {} + virtual bool visit(Identifier& _identifier) override { + ASTNode* node = m_resolver.getNameFromCurrentScope(_identifier.getName()); + if (node == nullptr) + throw std::exception(); // @todo + _identifier.setReferencedObject(*node); + return false; + } + private: + NameAndTypeResolver& m_resolver; + }; + + ReferencesResolver referencesResolver(*this); + _functionBody.accept(referencesResolver); +} + + +void NameAndTypeResolver::registerName(ASTString const& _name, ASTNode& _declaration) +{ + if (!m_currentScope->registerName(_name, _declaration)) + throw std::exception(); // @todo +} + +ASTNode* NameAndTypeResolver::getNameFromCurrentScope(ASTString const& _name, bool _recursive) +{ + return m_currentScope->resolveName(_name, _recursive); +} + +void NameAndTypeResolver::enterNewSubScope(ASTNode& _node) +{ + decltype(m_scopes)::iterator iter; + bool newlyAdded; + std::tie(iter, newlyAdded) = m_scopes.emplace(&_node, Scope(m_currentScope)); + BOOST_ASSERT(newlyAdded); + m_currentScope = &iter->second; +} + +void NameAndTypeResolver::closeCurrentScope() +{ + m_currentScope = m_currentScope->getOuterScope(); +} + +} } |