diff options
author | Christian <c@ethdev.com> | 2014-10-14 00:22:15 +0800 |
---|---|---|
committer | Christian <c@ethdev.com> | 2014-10-16 00:40:19 +0800 |
commit | 89b794f1dc15c8688526470b9d68b361dab82be3 (patch) | |
tree | 92db8a29965ee2dd796b22a1508f58b2d199e71e /NameAndTypeResolver.cpp | |
parent | bdac5c7b4b5c23ea4f2cfe4a779da05b4722f1be (diff) | |
download | dexon-solidity-89b794f1dc15c8688526470b9d68b361dab82be3.tar dexon-solidity-89b794f1dc15c8688526470b9d68b361dab82be3.tar.gz dexon-solidity-89b794f1dc15c8688526470b9d68b361dab82be3.tar.bz2 dexon-solidity-89b794f1dc15c8688526470b9d68b361dab82be3.tar.lz dexon-solidity-89b794f1dc15c8688526470b9d68b361dab82be3.tar.xz dexon-solidity-89b794f1dc15c8688526470b9d68b361dab82be3.tar.zst dexon-solidity-89b794f1dc15c8688526470b9d68b361dab82be3.zip |
Type system, not yet complete.
Diffstat (limited to 'NameAndTypeResolver.cpp')
-rw-r--r-- | NameAndTypeResolver.cpp | 103 |
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); } |