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);
}
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.
try
{
DeclarationRegistrationHelper registrar(m_scopes, _sourceUnit, m_errors);
DeclarationRegistrationHelper registrar(m_scopes, _sourceUnit, m_errors, _currentScope);
}
catch (FatalError const&)
{
@ -451,21 +451,22 @@ void NameAndTypeResolver::reportFatalTypeError(Error const& _e)
DeclarationRegistrationHelper::DeclarationRegistrationHelper(
map<ASTNode const*, shared_ptr<DeclarationContainer>>& _scopes,
ASTNode& _astRoot,
ErrorList& _errors
ErrorList& _errors,
ASTNode const* _currentScope
):
m_scopes(_scopes),
m_currentScope(nullptr),
m_currentScope(_currentScope),
m_errors(_errors)
{
_astRoot.accept(*this);
solAssert(m_currentScope == nullptr, "Scopes not correctly closed.");
solAssert(m_currentScope == _currentScope, "Scopes not correctly closed.");
}
bool DeclarationRegistrationHelper::visit(SourceUnit& _sourceUnit)
{
if (!m_scopes[&_sourceUnit])
// 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;
return true;
}

View File

@ -49,7 +49,9 @@ public:
);
/// Registers all declarations found in the AST node, usually a source unit.
/// @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.
bool performImports(SourceUnit& _sourceUnit, std::map<std::string, SourceUnit const*> const& _sourceUnits);
/// Resolves all names and types referenced from the given AST Node.
@ -130,10 +132,15 @@ private:
class DeclarationRegistrationHelper: private ASTVisitor
{
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(
std::map<ASTNode const*, std::shared_ptr<DeclarationContainer>>& _scopes,
ASTNode& _astRoot,
ErrorList& _errors
ErrorList& _errors,
ASTNode const* _currentScope = nullptr
);
private:

View File

@ -427,7 +427,12 @@ bool TypeChecker::visit(StructDefinition const& _struct)
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 (isLibraryFunction)