summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2015-03-24 07:53:49 +0800
committerJohn Hodge <tpg@mutabah.net>2015-03-24 07:53:49 +0800
commit83c1c2ef2ad5ca242383cab3b862a291124dc2fb (patch)
tree3ab95bccc658e798c3bc9232d4926108a9029e64
parent802c2c5d616d537ed8becea81c2ee6b48ae8f078 (diff)
downloadmrust-83c1c2ef2ad5ca242383cab3b862a291124dc2fb.tar.gz
Wildcard path resolution possibily working
-rw-r--r--src/ast/ast.cpp51
-rw-r--r--src/ast/ast.hpp6
-rw-r--r--src/ast/path.cpp49
-rw-r--r--src/convert/resolve.cpp89
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)