From 83c1c2ef2ad5ca242383cab3b862a291124dc2fb Mon Sep 17 00:00:00 2001 From: John Hodge Date: Tue, 24 Mar 2015 07:53:49 +0800 Subject: Wildcard path resolution possibily working --- src/ast/ast.cpp | 51 ++++++++++++++++++++++------ src/ast/ast.hpp | 6 +++- src/ast/path.cpp | 49 +++++++++++++++++++-------- 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 >::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, 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& 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 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) -- cgit v1.2.3