aboutsummaryrefslogtreecommitdiffstats
path: root/NameAndTypeResolver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'NameAndTypeResolver.cpp')
-rw-r--r--NameAndTypeResolver.cpp103
1 files changed, 70 insertions, 33 deletions
diff --git a/NameAndTypeResolver.cpp b/NameAndTypeResolver.cpp
index c3932ca9..33b550eb 100644
--- a/NameAndTypeResolver.cpp
+++ b/NameAndTypeResolver.cpp
@@ -31,10 +31,10 @@ namespace solidity {
class NameAndTypeResolver::ScopeHelper {
public:
- ScopeHelper(NameAndTypeResolver& _resolver, ASTString const& _name, ASTNode& _declaration)
+ ScopeHelper(NameAndTypeResolver& _resolver, Declaration& _declaration)
: m_resolver(_resolver)
{
- m_resolver.registerName(_name, _declaration);
+ m_resolver.registerDeclaration(_declaration);
m_resolver.enterNewSubScope(_declaration);
}
~ScopeHelper()
@@ -60,16 +60,15 @@ void NameAndTypeResolver::resolveNamesAndTypes(ContractDefinition& _contract)
void NameAndTypeResolver::handleContract(ContractDefinition& _contract)
{
- ScopeHelper scopeHelper(*this, _contract.getName(), _contract);
+ ScopeHelper scopeHelper(*this, _contract);
+
+ // @todo structs (definition and usage)
for (ptr<VariableDeclaration> const& variable : _contract.getStateVariables())
- registerName(variable->getName(), *variable);
- // @todo structs
+ registerVariableDeclarationAndResolveType(*variable);
for (ptr<FunctionDefinition> const& function : _contract.getDefinedFunctions())
handleFunction(*function);
-
- // @todo resolve names used in mappings
}
void NameAndTypeResolver::reset()
@@ -81,30 +80,20 @@ void NameAndTypeResolver::reset()
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());
-}
+ ScopeHelper scopeHelper(*this, _function);
-void NameAndTypeResolver::handleFunctionBody(Block& _functionBody)
-{
- registerVariablesInFunction(_functionBody);
- resolveReferencesInFunction(_functionBody);
+ registerVariablesInFunction(_function);
+ resolveReferencesInFunction(*_function.getReturnParameterList(), _function.getBody());
+ _function.getBody().checkTypeRequirements();
}
-void NameAndTypeResolver::registerVariablesInFunction(Block& _functionBody)
+void NameAndTypeResolver::registerVariablesInFunction(FunctionDefinition& _function)
{
class VariableDeclarationFinder : public ASTVisitor {
public:
VariableDeclarationFinder(NameAndTypeResolver& _resolver) : m_resolver(_resolver) {}
virtual bool visit(VariableDeclaration& _variable) override {
- m_resolver.registerName(_variable.getName(), _variable);
+ m_resolver.registerVariableDeclarationAndResolveType(_variable);
return false;
}
private:
@@ -112,37 +101,85 @@ void NameAndTypeResolver::registerVariablesInFunction(Block& _functionBody)
};
VariableDeclarationFinder declarationFinder(*this);
- _functionBody.accept(declarationFinder);
+ _function.accept(declarationFinder);
}
-void NameAndTypeResolver::resolveReferencesInFunction(Block& _functionBody)
+void NameAndTypeResolver::resolveReferencesInFunction(ParameterList& _returnParameters,
+ Block& _functionBody)
{
class ReferencesResolver : public ASTVisitor {
public:
- ReferencesResolver(NameAndTypeResolver& _resolver) : m_resolver(_resolver) {}
+ ReferencesResolver(NameAndTypeResolver& _resolver,
+ ParameterList& _returnParameters)
+ : m_resolver(_resolver), m_returnParameters(_returnParameters) {}
virtual bool visit(Identifier& _identifier) override {
- ASTNode* node = m_resolver.getNameFromCurrentScope(_identifier.getName());
- if (node == nullptr)
+ Declaration* declaration = m_resolver.getNameFromCurrentScope(_identifier.getName());
+ if (declaration == nullptr)
throw std::exception(); // @todo
- _identifier.setReferencedObject(*node);
+ _identifier.setReferencedDeclaration(*declaration);
return false;
}
+ virtual bool visit(Return& _return) override {
+ _return.setFunctionReturnParameters(m_returnParameters);
+ return true;
+ }
private:
NameAndTypeResolver& m_resolver;
+ ParameterList& m_returnParameters;
};
- ReferencesResolver referencesResolver(*this);
+ ReferencesResolver referencesResolver(*this, _returnParameters);
_functionBody.accept(referencesResolver);
}
+void NameAndTypeResolver::registerVariableDeclarationAndResolveType(VariableDeclaration& _variable)
+{
+ registerDeclaration(_variable);
+ TypeName* typeName = _variable.getTypeName();
+ if (typeName == nullptr) // unknown type, to be resolved by first assignment
+ return;
+
+ // walk the AST to resolve user defined type references
+ // (walking is necessory because of mappings)
+ // @todo this could probably also be done at an earlier stage where we anyway
+ // walk the AST
+
+ class UserDefinedTypeNameResolver : public ASTVisitor {
+ public:
+ UserDefinedTypeNameResolver(NameAndTypeResolver& _resolver)
+ : m_resolver(_resolver) {}
+ virtual bool visit(UserDefinedTypeName& _typeName) override {
+ Declaration* declaration = m_resolver.getNameFromCurrentScope(_typeName.getName());
+ if (declaration == nullptr)
+ throw std::exception(); // @todo
+ StructDefinition* referencedStruct = dynamic_cast<StructDefinition*>(declaration);
+ if (referencedStruct == nullptr)
+ throw std::exception(); // @todo we only allow structs as user defined types (later also contracts)
+ _typeName.setReferencedStruct(*referencedStruct);
+ return false;
+ }
+ virtual bool visit(Mapping&) override {
+ // @todo
+ return true;
+ }
+ private:
+ NameAndTypeResolver& m_resolver;
+ };
+
+ UserDefinedTypeNameResolver resolver(*this);
+ _variable.accept(resolver);
+
+ _variable.setType(typeName->toType());
+}
+
-void NameAndTypeResolver::registerName(ASTString const& _name, ASTNode& _declaration)
+void NameAndTypeResolver::registerDeclaration(Declaration& _declaration)
{
- if (!m_currentScope->registerName(_name, _declaration))
+ if (!m_currentScope->registerDeclaration(_declaration))
throw std::exception(); // @todo
}
-ASTNode* NameAndTypeResolver::getNameFromCurrentScope(ASTString const& _name, bool _recursive)
+Declaration* NameAndTypeResolver::getNameFromCurrentScope(ASTString const& _name, bool _recursive)
{
return m_currentScope->resolveName(_name, _recursive);
}