diff options
author | John Hodge <tpg@mutabah.net> | 2015-03-24 07:53:49 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2015-03-24 07:53:49 +0800 |
commit | 83c1c2ef2ad5ca242383cab3b862a291124dc2fb (patch) | |
tree | 3ab95bccc658e798c3bc9232d4926108a9029e64 | |
parent | 802c2c5d616d537ed8becea81c2ee6b48ae8f078 (diff) | |
download | mrust-83c1c2ef2ad5ca242383cab3b862a291124dc2fb.tar.gz |
Wildcard path resolution possibily working
-rw-r--r-- | src/ast/ast.cpp | 51 | ||||
-rw-r--r-- | src/ast/ast.hpp | 6 | ||||
-rw-r--r-- | src/ast/path.cpp | 49 | ||||
-rw-r--r-- | src/convert/resolve.cpp | 89 |
4 files changed, 110 insertions, 85 deletions
diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index a695c6f5..2d5fdca2 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -499,7 +499,7 @@ typename ::std::vector<Item<T> >::const_iterator find_named(const ::std::vector< });
}
-Module::ItemRef Module::find_item(const ::std::string& needle) const
+Module::ItemRef Module::find_item(const ::std::string& needle, bool ignore_private_wildcard) const
{
TRACE_FUNCTION_F("needle = " << needle);
// Sub-modules
@@ -581,12 +581,15 @@ Module::ItemRef Module::find_item(const ::std::string& needle) const {
for( const auto& imp : this->imports() )
{
- if( !imp.is_pub )
+ DEBUG("imp: '" << imp.name << "' = " << imp.data);
+ if( !imp.is_pub && ignore_private_wildcard )
{
// not public, ignore
+ DEBUG("Private import, ignore");
}
else if( imp.name == needle )
{
+ DEBUG("Match " << needle);
return ItemRef(imp);
}
else if( imp.name == "" )
@@ -595,21 +598,49 @@ Module::ItemRef Module::find_item(const ::std::string& needle) const //if( &imp.data == this )
// continue ;
//
- //if( !imp.data.is_bound() )
- //{
- // // not yet bound, so run resolution (recursion)
- // DEBUG("Recursively resolving pub wildcard use " << imp.data);
- // //imp.data.resolve(root_crate);
- // throw ParseError::Todo("Path::resolve() wildcard re-export call resolve");
- //}
+ if( !imp.data.is_bound() )
+ {
+ // not yet bound, so run resolution (recursion)
+ DEBUG("Recursively resolving pub wildcard use " << imp.data);
+ //imp.data.resolve(root_crate);
+ throw ParseError::Todo("Path::resolve() wildcard re-export call resolve");
+ }
- throw ParseError::Todo("Path::resolve() wildcard re-export");
+ switch(imp.data.binding_type())
+ {
+ case AST::Path::UNBOUND:
+ throw ParseError::BugCheck("Wildcard import path not bound");
+ // - If it's a module, recurse
+ case AST::Path::MODULE: {
+ auto rv = imp.data.bound_module().find_item(needle);
+ if( rv.type() != Module::ItemRef::ITEM_none )
+ return rv;
+ break; }
+ // - If it's an enum, search for this name and then pass to resolve
+ case AST::Path::ENUM: {
+ auto& vars = imp.data.bound_enum().variants();
+ // Damnit C++ "let it = vars.find(|a| a.name == needle);"
+ auto it = ::std::find_if(vars.begin(), vars.end(),
+ [&needle](const EnumVariant& ev) { return ev.m_name == needle; });
+ if( it != vars.end() ) {
+ DEBUG("Found enum variant " << it->m_name);
+ return ItemRef(imp);
+ //throw ParseError::Todo("Handle lookup_path_in_module for wildcard imports - enum");
+ }
+
+ break; }
+ // - otherwise, error
+ default:
+ DEBUG("ERROR: Import of invalid class : " << imp.data);
+ throw ParseError::Generic("Wildcard import of non-module/enum");
+ }
}
else
{
// Can't match, ignore
}
}
+
}
return Module::ItemRef();
diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp index 60621036..f6834071 100644 --- a/src/ast/ast.hpp +++ b/src/ast/ast.hpp @@ -390,6 +390,10 @@ struct EnumVariant: {
}
+ friend ::std::ostream& operator<<(::std::ostream& os, const EnumVariant& x) {
+ return os << "EnumVariant(" << x.m_name << "(" << x.m_sub_types << ") = " << x.m_value << ")";
+ }
+
SERIALISABLE_PROTOTYPES();
};
@@ -633,7 +637,7 @@ public: _(Item<Path>, Use)
#undef _
};
- ItemRef find_item(const ::std::string& needle) const;
+ ItemRef find_item(const ::std::string& needle, bool ignore_private_wildcard = true) const;
::std::vector<MetaItem>& attrs() { return m_attrs; }
itemlist_fcn_t& functions() { return m_functions; }
diff --git a/src/ast/path.cpp b/src/ast/path.cpp index 3e93e888..6109fa94 100644 --- a/src/ast/path.cpp +++ b/src/ast/path.cpp @@ -72,9 +72,11 @@ void Path::resolve(const Crate& root_crate) unsigned int slice_from = 0; // Used when rewriting the path to be relative to its crate root + ::std::vector<const Module*> mod_stack; const Module* mod = &root_crate.get_root_module(m_crate); for(unsigned int i = 0; i < m_nodes.size(); i ++ ) { + mod_stack.push_back(mod); const bool is_last = (i+1 == m_nodes.size()); const bool is_sec_last = (i+2 == m_nodes.size()); const PathNode& node = m_nodes[i]; @@ -105,9 +107,21 @@ void Path::resolve(const Crate& root_crate) { // Not found case AST::Module::ItemRef::ITEM_none: - // TODO: If parent node is anon, backtrack and try again + // If parent node is anon, backtrack and try again + // TODO: I feel like this shouldn't be done here, instead perform this when absolutising (now that find_item is reusable) + if( i > 0 && m_nodes[i-1].name()[0] == '#' && m_nodes[i-1].name().size() > 1 ) + { + i --; + mod_stack.pop_back(); + mod = mod_stack.back(); + mod_stack.pop_back(); + m_nodes.erase(m_nodes.begin()+i); + i --; + DEBUG("Failed to locate item in nested, look upwards - " << *this); + + continue ; + } throw ParseError::Generic("Unable to find component '" + node.name() + "'"); - break; // Sub-module case AST::Module::ItemRef::ITEM_Module: @@ -226,22 +240,29 @@ void Path::resolve(const Crate& root_crate) } break; } - // + // Re-export case AST::Module::ItemRef::ITEM_Use: { const auto& imp = item.unwrap_Use(); - // replace nodes 0:i with the source path - DEBUG("Re-exported path " << imp.data); - AST::Path newpath = imp.data; - for( unsigned int j = i+1; j < m_nodes.size(); j ++ ) + if( imp.name == "" ) { - newpath.m_nodes.push_back( m_nodes[j] ); + throw ParseError::Todo("Path::resolve - wildcard import"); + } + else + { + // replace nodes 0:i with the source path + DEBUG("Re-exported path " << imp.data); + AST::Path newpath = imp.data; + for( unsigned int j = i+1; j < m_nodes.size(); j ++ ) + { + newpath.m_nodes.push_back( m_nodes[j] ); + } + DEBUG("- newpath = " << newpath); + // TODO: This should check for recursion somehow + newpath.resolve(root_crate); + + *this = newpath; + DEBUG("Alias resolved, *this = " << *this); } - DEBUG("- newpath = " << newpath); - // TODO: This should check for recursion somehow - newpath.resolve(root_crate); - - *this = newpath; - DEBUG("Alias resolved, *this = " << *this); break; } } diff --git a/src/convert/resolve.cpp b/src/convert/resolve.cpp index 2de4ae44..fada5150 100644 --- a/src/convert/resolve.cpp +++ b/src/convert/resolve.cpp @@ -190,16 +190,38 @@ void CPathResolver::end_scope() // > Search module-level definitions
bool lookup_path_in_module(const AST::Crate& crate, const AST::Module& module, const AST::Path& mod_path, AST::Path& path)
{
- for( const auto& item_mod : module.submods() )
+ auto item = module.find_item(path[0].name(), false);
+ switch(item.type())
{
- if( item_mod.first.name() == path[0].name() ) {
- // Check name down?
- // Add current module path
- path = mod_path + path;
+ case AST::Module::ItemRef::ITEM_none:
+ return false;
+ case AST::Module::ItemRef::ITEM_Use: {
+ const auto& imp = item.unwrap_Use();
+ if( imp.name == "" )
+ {
+ // Wildcard path, prefix entirely with the path
+ path = imp.data + path;
+ return true;
+ }
+ else
+ {
+ path = AST::Path::add_tailing(imp.data, path);
path.resolve( crate );
return true;
}
+ break; }
+ case AST::Module::ItemRef::ITEM_Module:
+ // Check name down?
+ // Add current module path
+ path = mod_path + path;
+ path.resolve( crate );
+ return true;
+ default:
+ path = mod_path + path;
+ path.resolve( crate );
+ return true;
}
+ #if 0
for( const auto& import : module.imports() )
{
const ::std::string& bind_name = import.name;
@@ -231,60 +253,7 @@ bool lookup_path_in_module(const AST::Crate& crate, const AST::Module& module, c return true;
}
}
-
- // Types
- for( const auto& item : module.structs() )
- {
- if( item.name == path[0].name() ) {
- path = mod_path + path;
- path.resolve( crate );
- return true;
- }
- }
- for( const auto& item : module.enums() )
- {
- if( item.name == path[0].name() ) {
- path = mod_path + path;
- path.resolve( crate );
- return true;
- }
- }
- for( const auto& item : module.traits() )
- {
- if( item.name == path[0].name() ) {
- path = mod_path + path;
- path.resolve( crate );
- return true;
- }
- }
- for( const auto& item : module.type_aliases() )
- {
- if( item.name == path[0].name() ) {
- path = mod_path + path;
- path.resolve( crate );
- return true;
- }
- }
-
- // Values / Functions
- for( const auto& item_fcn : module.functions() )
- {
- if( item_fcn.name == path[0].name() ) {
- path = mod_path + path;
- path.resolve( crate );
- return true;
- }
- }
- for( const auto& item : module.statics() )
- {
- if( item.name == path[0].name() ) {
- path = mod_path + path;
- path.resolve( crate );
- return true;
- }
- }
-
- return false;
+ #endif
}
void CPathResolver::handle_path(AST::Path& path, CASTIterator::PathMode mode)
{
@@ -373,7 +342,7 @@ void CPathResolver::handle_path(AST::Path& path, CASTIterator::PathMode mode) DEBUG("no matches found for path = " << path);
assert( path.is_relative() );
if( mode != MODE_BIND )
- throw ParseError::Generic("Name resolution failed");
+ throw ParseError::Generic("CPathResolver::handle_path - Name resolution failed");
}
}
void CPathResolver::handle_type(TypeRef& type)
|