Refactor type system to allow multiple entry points.

This commit is contained in:
chriseth 2017-01-27 23:29:03 +01:00
parent fc8e50f688
commit c87bafd2ed
4 changed files with 27 additions and 15 deletions

View File

@ -44,18 +44,12 @@ NameAndTypeResolver::NameAndTypeResolver(
m_scopes[nullptr]->registerDeclaration(*declaration); m_scopes[nullptr]->registerDeclaration(*declaration);
} }
bool NameAndTypeResolver::registerDeclarations(SourceUnit& _sourceUnit) bool NameAndTypeResolver::registerDeclarations(ASTNode& _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_currentScope = m_scopes[&_sourceUnit].get();
// 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);
_sourceUnit.annotation().exportedSymbols = m_scopes[&_sourceUnit]->declarations();
} }
catch (FatalError const&) catch (FatalError const&)
{ {
@ -458,11 +452,26 @@ DeclarationRegistrationHelper::DeclarationRegistrationHelper(
ErrorList& _errors ErrorList& _errors
): ):
m_scopes(_scopes), m_scopes(_scopes),
m_currentScope(&_astRoot), m_currentScope(nullptr),
m_errors(_errors) m_errors(_errors)
{ {
solAssert(!!m_scopes.at(m_currentScope), "");
_astRoot.accept(*this); _astRoot.accept(*this);
solAssert(m_currentScope == nullptr, "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_currentScope = &_sourceUnit;
return true;
}
void DeclarationRegistrationHelper::endVisit(SourceUnit& _sourceUnit)
{
_sourceUnit.annotation().exportedSymbols = m_scopes[&_sourceUnit]->declarations();
closeCurrentScope();
} }
bool DeclarationRegistrationHelper::visit(ImportDirective& _import) bool DeclarationRegistrationHelper::visit(ImportDirective& _import)
@ -583,12 +592,13 @@ void DeclarationRegistrationHelper::enterNewSubScope(Declaration const& _declara
void DeclarationRegistrationHelper::closeCurrentScope() void DeclarationRegistrationHelper::closeCurrentScope()
{ {
solAssert(m_currentScope, "Closed non-existing scope."); solAssert(m_currentScope && m_scopes.count(m_currentScope), "Closed non-existing scope.");
m_currentScope = m_scopes[m_currentScope]->enclosingNode(); m_currentScope = m_scopes[m_currentScope]->enclosingNode();
} }
void DeclarationRegistrationHelper::registerDeclaration(Declaration& _declaration, bool _opensScope) void DeclarationRegistrationHelper::registerDeclaration(Declaration& _declaration, bool _opensScope)
{ {
solAssert(m_currentScope && m_scopes.count(m_currentScope), "No current scope.");
if (!m_scopes[m_currentScope]->registerDeclaration(_declaration, nullptr, !_declaration.isVisibleInContract())) if (!m_scopes[m_currentScope]->registerDeclaration(_declaration, nullptr, !_declaration.isVisibleInContract()))
{ {
SourceLocation firstDeclarationLocation; SourceLocation firstDeclarationLocation;

View File

@ -43,9 +43,9 @@ class NameAndTypeResolver: private boost::noncopyable
{ {
public: public:
NameAndTypeResolver(std::vector<Declaration const*> const& _globals, ErrorList& _errors); NameAndTypeResolver(std::vector<Declaration const*> const& _globals, ErrorList& _errors);
/// Registers all declarations found in the 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(SourceUnit& _sourceUnit); bool registerDeclarations(ASTNode& _sourceUnit);
/// 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.
@ -133,6 +133,8 @@ public:
); );
private: private:
bool visit(SourceUnit& _sourceUnit) override;
void endVisit(SourceUnit& _sourceUnit) override;
bool visit(ImportDirective& _declaration) override; bool visit(ImportDirective& _declaration) override;
bool visit(ContractDefinition& _contract) override; bool visit(ContractDefinition& _contract) override;
void endVisit(ContractDefinition& _contract) override; void endVisit(ContractDefinition& _contract) override;

View File

@ -32,11 +32,11 @@ using namespace dev;
using namespace dev::solidity; using namespace dev::solidity;
bool TypeChecker::checkTypeRequirements(ContractDefinition const& _contract) bool TypeChecker::checkTypeRequirements(ASTNode const& _contract)
{ {
try try
{ {
visit(_contract); _contract.accept(*this);
} }
catch (FatalError const&) catch (FatalError const&)
{ {

View File

@ -47,7 +47,7 @@ public:
/// Performs type checking on the given contract and all of its sub-nodes. /// Performs type checking on the given contract and all of its sub-nodes.
/// @returns true iff all checks passed. Note even if all checks passed, errors() can still contain warnings /// @returns true iff all checks passed. Note even if all checks passed, errors() can still contain warnings
bool checkTypeRequirements(ContractDefinition const& _contract); bool checkTypeRequirements(ASTNode const& _contract);
/// @returns the type of an expression and asserts that it is present. /// @returns the type of an expression and asserts that it is present.
TypePointer const& type(Expression const& _expression) const; TypePointer const& type(Expression const& _expression) const;