Allow different entry scope for registerDeclarations.

This commit is contained in:
chriseth 2017-01-31 23:12:40 +01:00
parent e67faa9839
commit b1bb228ab3
3 changed files with 22 additions and 9 deletions

View File

@ -46,12 +46,12 @@ NameAndTypeResolver::NameAndTypeResolver(
m_scopes[nullptr]->registerDeclaration(*declaration); m_scopes[nullptr]->registerDeclaration(*declaration);
} }
bool NameAndTypeResolver::registerDeclarations(ASTNode& _sourceUnit) bool NameAndTypeResolver::registerDeclarations(ASTNode& _sourceUnit, ASTNode const* _currentScope)
{ {
// The helper registers all declarations in m_scopes as a side-effect of its construction. // The helper registers all declarations in m_scopes as a side-effect of its construction.
try try
{ {
DeclarationRegistrationHelper registrar(m_scopes, _sourceUnit, m_errors); DeclarationRegistrationHelper registrar(m_scopes, _sourceUnit, m_errors, _currentScope);
} }
catch (FatalError const&) catch (FatalError const&)
{ {
@ -451,21 +451,22 @@ void NameAndTypeResolver::reportFatalTypeError(Error const& _e)
DeclarationRegistrationHelper::DeclarationRegistrationHelper( DeclarationRegistrationHelper::DeclarationRegistrationHelper(
map<ASTNode const*, shared_ptr<DeclarationContainer>>& _scopes, map<ASTNode const*, shared_ptr<DeclarationContainer>>& _scopes,
ASTNode& _astRoot, ASTNode& _astRoot,
ErrorList& _errors ErrorList& _errors,
ASTNode const* _currentScope
): ):
m_scopes(_scopes), m_scopes(_scopes),
m_currentScope(nullptr), m_currentScope(_currentScope),
m_errors(_errors) m_errors(_errors)
{ {
_astRoot.accept(*this); _astRoot.accept(*this);
solAssert(m_currentScope == nullptr, "Scopes not correctly closed."); solAssert(m_currentScope == _currentScope, "Scopes not correctly closed.");
} }
bool DeclarationRegistrationHelper::visit(SourceUnit& _sourceUnit) bool DeclarationRegistrationHelper::visit(SourceUnit& _sourceUnit)
{ {
if (!m_scopes[&_sourceUnit]) if (!m_scopes[&_sourceUnit])
// By importing, it is possible that the container already exists. // By importing, it is possible that the container already exists.
m_scopes[&_sourceUnit].reset(new DeclarationContainer(nullptr, m_scopes[nullptr].get())); m_scopes[&_sourceUnit].reset(new DeclarationContainer(m_currentScope, m_scopes[m_currentScope].get()));
m_currentScope = &_sourceUnit; m_currentScope = &_sourceUnit;
return true; return true;
} }

View File

@ -49,7 +49,9 @@ public:
); );
/// Registers all declarations found in the AST node, usually a source unit. /// Registers all declarations found in the AST node, usually a source unit.
/// @returns false in case of error. /// @returns false in case of error.
bool registerDeclarations(ASTNode& _sourceUnit); /// @param _currentScope should be nullptr but can be used to inject new declarations into
/// existing scopes, used by the snippets feature.
bool registerDeclarations(ASTNode& _sourceUnit, ASTNode const* _currentScope = nullptr);
/// Applies the effect of import directives. /// Applies the effect of import directives.
bool performImports(SourceUnit& _sourceUnit, std::map<std::string, SourceUnit const*> const& _sourceUnits); bool performImports(SourceUnit& _sourceUnit, std::map<std::string, SourceUnit const*> const& _sourceUnits);
/// Resolves all names and types referenced from the given AST Node. /// Resolves all names and types referenced from the given AST Node.
@ -130,10 +132,15 @@ private:
class DeclarationRegistrationHelper: private ASTVisitor class DeclarationRegistrationHelper: private ASTVisitor
{ {
public: public:
/// Registers declarations in their scopes and creates new scopes as a side-effect
/// of construction.
/// @param _currentScope should be nullptr if we start at SourceUnit, but can be different
/// to inject new declarations into an existing scope, used by snippets.
DeclarationRegistrationHelper( DeclarationRegistrationHelper(
std::map<ASTNode const*, std::shared_ptr<DeclarationContainer>>& _scopes, std::map<ASTNode const*, std::shared_ptr<DeclarationContainer>>& _scopes,
ASTNode& _astRoot, ASTNode& _astRoot,
ErrorList& _errors ErrorList& _errors,
ASTNode const* _currentScope = nullptr
); );
private: private:

View File

@ -427,7 +427,12 @@ bool TypeChecker::visit(StructDefinition const& _struct)
bool TypeChecker::visit(FunctionDefinition const& _function) bool TypeChecker::visit(FunctionDefinition const& _function)
{ {
bool isLibraryFunction = dynamic_cast<ContractDefinition const&>(*_function.scope()).isLibrary(); bool isLibraryFunction = false;
if (
dynamic_cast<ContractDefinition const*>(_function.scope()) &&
dynamic_cast<ContractDefinition const*>(_function.scope())->isLibrary()
)
isLibraryFunction = true;
if (_function.isPayable()) if (_function.isPayable())
{ {
if (isLibraryFunction) if (isLibraryFunction)