aboutsummaryrefslogtreecommitdiffstats
path: root/NameAndTypeResolver.cpp
diff options
context:
space:
mode:
authorChristian <c@ethdev.com>2014-10-13 21:07:21 +0800
committerChristian <c@ethdev.com>2014-10-13 23:02:21 +0800
commit4f791179640fdcfbbd62c4c7a2a5273081b7b742 (patch)
tree7c7576b991884befde24473b5f6370b8afa83b2f /NameAndTypeResolver.cpp
parent98bdd7429974521946a1aa3bffa038fc515f745c (diff)
downloaddexon-solidity-4f791179640fdcfbbd62c4c7a2a5273081b7b742.tar.gz
dexon-solidity-4f791179640fdcfbbd62c4c7a2a5273081b7b742.tar.zst
dexon-solidity-4f791179640fdcfbbd62c4c7a2a5273081b7b742.zip
Name resolution.
Diffstat (limited to 'NameAndTypeResolver.cpp')
-rw-r--r--NameAndTypeResolver.cpp142
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();
+}
+
+} }