summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn Hodge <tpg@ucc.asn.au>2019-01-01 13:06:13 +0800
committerJohn Hodge <tpg@ucc.asn.au>2019-01-01 13:06:13 +0800
commit95d725d80a76e74549329dfdb74f8147c1b075e7 (patch)
treecddcebd19c54071cea1e36f2531bf584b1e8554c /src
parent47954747236802644fcfdbd378e320fbb69690bc (diff)
downloadmrust-95d725d80a76e74549329dfdb74f8147c1b075e7.tar.gz
Refactor of `use` items to fully-group imports from a single use
Diffstat (limited to 'src')
-rw-r--r--src/ast/ast.cpp23
-rw-r--r--src/ast/ast.hpp32
-rw-r--r--src/ast/dump.cpp23
-rw-r--r--src/expand/mod.cpp2
-rw-r--r--src/expand/std_prelude.cpp4
-rw-r--r--src/parse/root.cpp202
-rw-r--r--src/resolve/index.cpp64
-rw-r--r--src/resolve/use.cpp244
8 files changed, 286 insertions, 308 deletions
diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp
index b439553a..f3a81e80 100644
--- a/src/ast/ast.cpp
+++ b/src/ast/ast.cpp
@@ -241,23 +241,23 @@ bool Impl::has_named_item(const ::std::string& name) const
return os << impl.m_def;
}
-::std::ostream& operator<<(::std::ostream& os, const UseStmt& x)
-{
- os << "Use(" << x.path << ")";
- return os;
-}
-
-
MacroInvocation MacroInvocation::clone() const
{
return MacroInvocation(m_span, m_macro_name, m_ident, m_input.clone());
}
-
-UseStmt UseStmt::clone() const
+UseItem UseItem::clone() const
{
- return UseStmt(sp, AST::Path(path));
+ decltype(this->entries) entries;
+ for(const auto& e : this->entries)
+ {
+ entries.push_back({ e.sp, e.path, e.name });
+ }
+ return UseItem {
+ this->sp,
+ mv$(entries)
+ };
}
void ExternBlock::add_item(Named<Item> named_item)
@@ -296,9 +296,6 @@ void Module::add_item(bool is_pub, ::std::string name, Item it, AttributeList at
void Module::add_ext_crate(bool is_public, ::std::string ext_name, ::std::string imp_name, AttributeList attrs) {
this->add_item( is_public, imp_name, Item::make_Crate({mv$(ext_name)}), mv$(attrs) );
}
-void Module::add_alias(bool is_public, UseStmt us, ::std::string name, AttributeList attrs) {
- this->add_item( is_public, mv$(name), Item(mv$(us)), mv$(attrs) );
-}
void Module::add_macro_invocation(MacroInvocation item) {
this->add_item( false, "", Item( mv$(item) ), ::AST::AttributeList {} );
}
diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp
index 493b397c..8976cfc7 100644
--- a/src/ast/ast.hpp
+++ b/src/ast/ast.hpp
@@ -462,20 +462,18 @@ public:
private:
};
-struct UseStmt
+struct UseItem
{
- Span sp;
- ::AST::Path path;
-
- UseStmt(Span sp, Path p):
- sp(sp),
- path(p)
- {
- }
-
- UseStmt clone() const;
+ Span sp; // Span covering the entire `use foo;`
+ struct Ent {
+ Span sp; // Span covering just the path (final component)
+ ::AST::Path path;
+ ::std::string name; // If "", this is a glob/wildcard use
+ };
+ ::std::vector<Ent> entries;
- friend ::std::ostream& operator<<(::std::ostream& os, const UseStmt& x);
+ UseItem clone() const;
+ //friend ::std::ostream& operator<<(::std::ostream& os, const UseItem& x);
};
class ExternBlock
@@ -549,6 +547,13 @@ public:
};
::std::vector<MacroImport> m_macro_imports;
+ struct Import {
+ bool is_pub;
+ ::std::string name;
+ ::AST::Path path; // If `name` is "", then this is a module/enum to glob
+ };
+ ::std::vector<Import> m_item_imports;
+
public:
Module() {}
Module(::AST::Path path):
@@ -566,7 +571,6 @@ public:
void add_item(Named<Item> item);
void add_item(bool is_pub, ::std::string name, Item it, AttributeList attrs);
void add_ext_crate(bool is_public, ::std::string ext_name, ::std::string imp_name, AttributeList attrs);
- void add_alias(bool is_public, UseStmt path, ::std::string name, AttributeList attrs);
void add_macro_invocation(MacroInvocation item);
void add_macro(bool is_exported, ::std::string name, MacroRulesPtr macro);
@@ -595,7 +599,7 @@ TAGGED_UNION_EX(Item, (), None,
(
(None, struct {} ),
(MacroInv, MacroInvocation),
- (Use, UseStmt),
+ (Use, UseItem),
// Nameless items
(ExternBlock, ExternBlock),
diff --git a/src/ast/dump.cpp b/src/ast/dump.cpp
index f1481abf..94ad6271 100644
--- a/src/ast/dump.cpp
+++ b/src/ast/dump.cpp
@@ -619,17 +619,26 @@ void RustPrinter::handle_module(const AST::Module& mod)
// m_os << "\n";
// need_nl = false;
//}
- if( i_data.path == AST::Path() ) {
+ if( i_data.entries.empty() ) {
continue ;
}
- m_os << indent() << (i.is_pub ? "pub " : "") << "use " << i_data;
- if( i.name == "" )
- {
- m_os << "::*";
+ m_os << indent() << (i.is_pub ? "pub " : "") << "use ";
+ if( i_data.entries.size() > 1 ) {
+ m_os << "{";
}
- else if( i_data.path.nodes().back().name() != i.name )
+ for(const auto& ent : i_data.entries)
{
- m_os << " as " << i.name;
+ if( &ent != &i_data.entries.front() )
+ m_os << ", ";
+ m_os << ent.path;
+ if( ent.name == "" ) {
+ m_os << "::*";
+ }
+ else if( ent.name != ent.path.nodes().back().name() ) {
+ m_os << " as " << ent.name;
+ }
+ else {
+ }
}
m_os << ";\n";
}
diff --git a/src/expand/mod.cpp b/src/expand/mod.cpp
index f63f7ab5..da37dea7 100644
--- a/src/expand/mod.cpp
+++ b/src/expand/mod.cpp
@@ -1051,7 +1051,7 @@ void Expand_Mod(::AST::Crate& crate, LList<const AST::Module*> modstack, ::AST::
if( crate.m_prelude_path != AST::Path() )
{
if( mod.m_insert_prelude && ! mod.is_anon() ) {
- mod.add_alias(false, ::AST::UseStmt(Span(), crate.m_prelude_path), "", {});
+ mod.add_item(false, "", ::AST::UseItem { Span(), ::make_vec1(::AST::UseItem::Ent { Span(), crate.m_prelude_path, "" }) }, {});
}
}
diff --git a/src/expand/std_prelude.cpp b/src/expand/std_prelude.cpp
index d6022959..52c1554c 100644
--- a/src/expand/std_prelude.cpp
+++ b/src/expand/std_prelude.cpp
@@ -65,12 +65,12 @@ public:
void handle(const Span& sp, const AST::Attribute& mi, ::AST::Crate& crate, const AST::Path& path, AST::Module& mod, AST::Item&i) const override {
if( i.is_Use() ) {
- const auto& p = i.as_Use().path;
+ const auto& p = i.as_Use().entries.front().path;
// TODO: Ensure that this statement is a glob (has a name of "")
crate.m_prelude_path = AST::Path(p);
}
else {
- ERROR(sp, E0000, "Invalid use of #[no_prelude] on non-module");
+ ERROR(sp, E0000, "Invalid use of #[prelude_import] on non-module");
}
}
};
diff --git a/src/parse/root.cpp b/src/parse/root.cpp
index 2db03c99..28a49287 100644
--- a/src/parse/root.cpp
+++ b/src/parse/root.cpp
@@ -1322,55 +1322,74 @@ AST::ExternBlock Parse_ExternBlock(TokenStream& lex, ::std::string abi, ::AST::A
return rv;
}
-void Parse_Use_Wildcard(Span sp, AST::Path base_path, ::std::function<void(AST::UseStmt, ::std::string)> fcn)
+/// Parse multiple items from a use "statement"
+void Parse_Use_Inner(TokenStream& lex, ::std::vector<AST::UseItem::Ent>& entries, AST::Path& path)
{
- fcn( AST::UseStmt(mv$(sp), mv$(base_path)), "" ); // HACK! Empty path indicates wilcard import
-}
-void Parse_Use_Set(TokenStream& lex, const ProtoSpan& ps, const AST::Path& base_path, ::std::function<void(AST::UseStmt, ::std::string)> fcn)
-{
- TRACE_FUNCTION;
-
Token tok;
- do {
- AST::Path path;
- ::std::string name;
- if( GET_TOK(tok, lex) == TOK_RWORD_SELF ) {
- path = ::AST::Path(base_path);
- name = base_path[base_path.size()-1].name();
- }
- else if( tok.type() == TOK_BRACE_CLOSE ) {
- break ;
- }
- else {
- path = ::AST::Path(base_path);
- while(1)
- {
- CHECK_TOK(tok, TOK_IDENT);
- path += AST::PathNode(tok.str(), {});
- if( !TARGETVER_1_29 )
- break;
- if( lex.lookahead(0) != TOK_DOUBLE_COLON )
- break;
- GET_CHECK_TOK(tok, lex, TOK_DOUBLE_COLON);
- GET_TOK(tok, lex);
+ do
+ {
+ switch( GET_TOK(tok, lex) )
+ {
+ case TOK_IDENT:
+ path.append( AST::PathNode( mv$(tok.str()), {}) );
+ break;
+ case TOK_BRACE_OPEN:
+ // Can't be an empty list
+ if( LOOK_AHEAD(lex) == TOK_BRACE_CLOSE ) {
+ throw ParseError::Unexpected(lex, tok);
}
- name = mv$(tok.str());
- }
+ // Keep looping until a comma
+ do {
+ if( LOOK_AHEAD(lex) == TOK_BRACE_CLOSE ) {
+ // Trailing comma
+ GET_TOK(tok, lex);
+ break;
+ }
+ // - Handle `self` in braces differently
+ else if( LOOK_AHEAD(lex) == TOK_RWORD_SELF ) {
+ GET_TOK(tok, lex);
+ auto name = path.nodes().back().name();
+ entries.push_back({ lex.point_span(), AST::Path(path), ::std::move(name) });
+ }
+ else {
+ size_t l = path.nodes().size();
- if( GET_TOK(tok, lex) == TOK_RWORD_AS ) {
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- name = mv$(tok.str());
- }
- else {
- PUTBACK(tok, lex);
+ Parse_Use_Inner(lex, entries, path);
+
+ assert(l <= path.nodes().size());
+ path.nodes().resize( l );
+ }
+ } while( GET_TOK(tok, lex) == TOK_COMMA );
+ CHECK_TOK(tok, TOK_BRACE_CLOSE);
+ return;
+ case TOK_STAR:
+ entries.push_back({ lex.point_span(), AST::Path(path), "" });
+ return ;
+ default:
+ throw ParseError::Unexpected(lex, tok);
}
- fcn(AST::UseStmt(lex.end_span(ps), mv$(path)), mv$(name));
- } while( GET_TOK(tok, lex) == TOK_COMMA );
- PUTBACK(tok, lex);
-}
+ } while( GET_TOK(tok, lex) == TOK_DOUBLE_COLON );
+
+ ::std::string name;
-void Parse_Use(TokenStream& lex, ::std::function<void(AST::UseStmt, ::std::string)> fcn)
+ // NOTE: The above loop has to run once, so the last token HAS to have been an ident
+ if( tok.type() == TOK_RWORD_AS )
+ {
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ name = mv$(tok.str());
+ }
+ else
+ {
+ PUTBACK(tok, lex);
+ ASSERT_BUG(lex.point_span(), path.nodes().size() > 0, "`use` with no path");
+ name = path.nodes().back().name();
+ }
+
+ // TODO: Get a span covering the final node.
+ entries.push_back({ lex.point_span(), AST::Path(path), ::std::move(name) });
+}
+::AST::UseItem Parse_Use(TokenStream& lex)
{
TRACE_FUNCTION;
@@ -1379,10 +1398,13 @@ void Parse_Use(TokenStream& lex, ::std::function<void(AST::UseStmt, ::std::strin
::std::vector<AST::PathNode> nodes;
ProtoSpan span_start = lex.start_span();
+ ::std::vector<AST::UseItem::Ent> entries;
+
switch( GET_TOK(tok, lex) )
{
case TOK_RWORD_SELF:
path = AST::Path( AST::Path::TagSelf(), {} ); // relative path
+ GET_CHECK_TOK(tok, lex, TOK_DOUBLE_COLON);
break;
case TOK_RWORD_SUPER: {
unsigned int count = 1;
@@ -1392,11 +1414,11 @@ void Parse_Use(TokenStream& lex, ::std::function<void(AST::UseStmt, ::std::strin
count += 1;
}
path = AST::Path( AST::Path::TagSuper(), count, {} );
+ GET_CHECK_TOK(tok, lex, TOK_DOUBLE_COLON);
break; }
- case TOK_IDENT:
- path.append( AST::PathNode(mv$(tok.str()), {}) );
- break;
case TOK_RWORD_CRATE:
+ // 1.29 absolute path
+ GET_CHECK_TOK(tok, lex, TOK_DOUBLE_COLON);
break;
// Leading :: is allowed and ignored for the $crate feature
case TOK_DOUBLE_COLON:
@@ -1407,66 +1429,24 @@ void Parse_Use(TokenStream& lex, ::std::function<void(AST::UseStmt, ::std::strin
GET_CHECK_TOK(tok, lex, TOK_STRING);
path = ::AST::Path(tok.str(), {});
}
- else {
+ else
+ {
PUTBACK(tok, lex);
}
+ GET_CHECK_TOK(tok, lex, TOK_DOUBLE_COLON);
break;
- case TOK_BRACE_OPEN:
- Parse_Use_Set(lex, span_start, path, fcn);
- GET_CHECK_TOK(tok, lex, TOK_BRACE_CLOSE);
- return;
- case TOK_STAR:
- Parse_Use_Wildcard( lex.end_span(span_start), mv$(path), fcn );
- return;
case TOK_INTERPOLATED_PATH:
path = mv$(tok.frag_path());
+ GET_CHECK_TOK(tok, lex, TOK_DOUBLE_COLON);
break;
default:
- throw ParseError::Unexpected(lex, tok);
- }
- while( GET_TOK(tok, lex) == TOK_DOUBLE_COLON )
- {
- if( GET_TOK(tok, lex) == TOK_IDENT )
- {
- path.append( AST::PathNode( mv$(tok.str()), {}) );
- }
- else
- {
- //path.set_span( lex.end_span(span_start) );
- switch( tok.type() )
- {
- case TOK_BRACE_OPEN:
- Parse_Use_Set(lex, span_start, mv$(path), fcn);
- GET_CHECK_TOK(tok, lex, TOK_BRACE_CLOSE);
- break ;
- case TOK_STAR:
- Parse_Use_Wildcard( lex.end_span(span_start), mv$(path), fcn );
- break ;
- default:
- throw ParseError::Unexpected(lex, tok);
- }
- // early return - This branch is either the end of the use statement, or a syntax error
- return ;
- }
- }
- //path.set_span( lex.end_span(span_start) );
-
- ::std::string name;
- // This should only be allowed if the last token was an ident
- // - Above checks ensure this
- if( tok.type() == TOK_RWORD_AS )
- {
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- name = mv$(tok.str());
- }
- else
- {
PUTBACK(tok, lex);
- ASSERT_BUG(lex.point_span(), path.nodes().size() > 0, "`use` with no path");
- name = path.nodes().back().name();
+ break;
}
- fcn( AST::UseStmt(lex.end_span(span_start), mv$(path)), name);
+ Parse_Use_Inner(lex, entries, path);
+
+ return AST::UseItem { lex.end_span(span_start), mv$(entries) };
}
@@ -1655,16 +1635,7 @@ namespace {
switch( GET_TOK(tok, lex) )
{
case TOK_RWORD_USE:
- // NOTE: The only problem here is with things like `use foo::{a, b, c}` - all others are a single statement.
- // - These are caught by the condition in the closure
- Parse_Use(lex, [&](AST::UseStmt p, std::string s) {
- DEBUG(mod_path << " - use " << p << " as '" << s << "'");
- if( !item_data.is_None() )
- TODO(lex.point_span(), "Encode multi-item use statements as a single Item");
- item_data = ::AST::Item(mv$(p));
- item_name = mv$(s);
- });
- assert( !item_data.is_None() );
+ item_data = Parse_Use(lex);
GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
break;
@@ -2072,26 +2043,7 @@ void Parse_Mod_Item(TokenStream& lex, AST::Module& mod, AST::AttributeList meta_
SET_MODULE(lex, mod);
lex.parse_state().parent_attrs = &meta_items;
- //TRACE_FUNCTION;
- Token tok;
-
- // `use ...`
- // TODO: This doesn't spot `pub(path) use`.
- if( LOOK_AHEAD(lex) == TOK_RWORD_USE || (lex.lookahead(0) == TOK_RWORD_PUB && lex.lookahead(1) == TOK_RWORD_USE) )
- {
- bool is_public = Parse_Publicity(lex);
- GET_CHECK_TOK(tok, lex, TOK_RWORD_USE);
-
- Parse_Use(lex, [&mod,is_public,&meta_items](AST::UseStmt p, std::string s) {
- DEBUG(mod.path() << " - use " << p << " as '" << s << "'");
- mod.add_alias(is_public, mv$(p), s, meta_items.clone());
- });
- GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
- }
- else
- {
- mod.add_item( Parse_Mod_Item_S(lex, mod.m_file_info, mod.path(), mv$(meta_items)) );
- }
+ mod.add_item( Parse_Mod_Item_S(lex, mod.m_file_info, mod.path(), mv$(meta_items)) );
}
void Parse_ModRoot_Items(TokenStream& lex, AST::Module& mod)
diff --git a/src/resolve/index.cpp b/src/resolve/index.cpp
index 48f2d0da..6051b82d 100644
--- a/src/resolve/index.cpp
+++ b/src/resolve/index.cpp
@@ -17,7 +17,7 @@ enum class IndexName
Value,
};
-void Resolve_Index_Module_Wildcard__use_stmt(AST::Crate& crate, AST::Module& dst_mod, const AST::UseStmt& i_data, bool is_pub);
+void Resolve_Index_Module_Wildcard__use_stmt(AST::Crate& crate, AST::Module& dst_mod, const AST::UseItem::Ent& i_data, bool is_pub);
::std::ostream& operator<<(::std::ostream& os, const IndexName& loc)
{
@@ -178,8 +178,8 @@ void Resolve_Index_Module_Base(const AST::Crate& crate, AST::Module& mod)
{
if( ! i.data.is_Use() )
continue ;
- const auto& i_data = i.data.as_Use();
- if( i.name != "" )
+ for(const auto& i_data : i.data.as_Use().entries)
+ if( i_data.name != "" )
{
// TODO: Ensure that the path is canonical?
@@ -190,47 +190,47 @@ void Resolve_Index_Module_Base(const AST::Crate& crate, AST::Module& mod)
// - Types
{TU_MATCH_HDRA( (i_data.path.m_bindings.type), {)
TU_ARMA(Unbound, _e) {
- DEBUG(i.name << " - Not a type/module");
+ DEBUG(i_data.name << " - Not a type/module");
}
TU_ARMA(TypeParameter, e)
BUG(sp, "Import was bound to type parameter");
TU_ARMA(Crate , e)
- _add_item(sp, mod, IndexName::Namespace, i.name, i.is_pub, i_data.path, !allow_collide);
+ _add_item(sp, mod, IndexName::Namespace, i_data.name, i.is_pub, i_data.path, !allow_collide);
TU_ARMA(Module, e)
- _add_item(sp, mod, IndexName::Namespace, i.name, i.is_pub, i_data.path, !allow_collide);
+ _add_item(sp, mod, IndexName::Namespace, i_data.name, i.is_pub, i_data.path, !allow_collide);
TU_ARMA(Enum, e)
- _add_item_type(sp, mod, i.name, i.is_pub, i_data.path, !allow_collide);
+ _add_item_type(sp, mod, i_data.name, i.is_pub, i_data.path, !allow_collide);
TU_ARMA(Union, e)
- _add_item_type(sp, mod, i.name, i.is_pub, i_data.path, !allow_collide);
+ _add_item_type(sp, mod, i_data.name, i.is_pub, i_data.path, !allow_collide);
TU_ARMA(Trait, e)
- _add_item_type(sp, mod, i.name, i.is_pub, i_data.path, !allow_collide);
+ _add_item_type(sp, mod, i_data.name, i.is_pub, i_data.path, !allow_collide);
TU_ARMA(TypeAlias, e)
- _add_item_type(sp, mod, i.name, i.is_pub, i_data.path, !allow_collide);
+ _add_item_type(sp, mod, i_data.name, i.is_pub, i_data.path, !allow_collide);
TU_ARMA(Struct, e)
- _add_item_type(sp, mod, i.name, i.is_pub, i_data.path, !allow_collide);
+ _add_item_type(sp, mod, i_data.name, i.is_pub, i_data.path, !allow_collide);
TU_ARMA(EnumVar, e)
- _add_item_type(sp, mod, i.name, i.is_pub, i_data.path, !allow_collide);
+ _add_item_type(sp, mod, i_data.name, i.is_pub, i_data.path, !allow_collide);
}}
// - Values
{TU_MATCH_HDRA( (i_data.path.m_bindings.value), {)
TU_ARMA(Unbound, _e) {
- DEBUG(i.name << " - Not a value");
+ DEBUG(i_data.name << " - Not a value");
}
TU_ARMA(Variable, e)
BUG(sp, "Import was bound to a variable");
TU_ARMA(Struct, e)
- _add_item_value(sp, mod, i.name, i.is_pub, i_data.path, !allow_collide);
+ _add_item_value(sp, mod, i_data.name, i.is_pub, i_data.path, !allow_collide);
TU_ARMA(EnumVar, e)
- _add_item_value(sp, mod, i.name, i.is_pub, i_data.path, !allow_collide);
+ _add_item_value(sp, mod, i_data.name, i.is_pub, i_data.path, !allow_collide);
TU_ARMA(Static , e)
- _add_item_value(sp, mod, i.name, i.is_pub, i_data.path, !allow_collide);
+ _add_item_value(sp, mod, i_data.name, i.is_pub, i_data.path, !allow_collide);
TU_ARMA(Function, e)
- _add_item_value(sp, mod, i.name, i.is_pub, i_data.path, !allow_collide);
+ _add_item_value(sp, mod, i_data.name, i.is_pub, i_data.path, !allow_collide);
}}
// - Macros
{TU_MATCH_HDRA( (i_data.path.m_bindings.macro), {)
TU_ARMA(Unbound, _e) {
- DEBUG(i.name << " - Not a macro");
+ DEBUG(i_data.name << " - Not a macro");
}
TU_ARMA(MacroRules, e) {
::std::vector<::std::string> path;
@@ -238,7 +238,7 @@ void Resolve_Index_Module_Base(const AST::Crate& crate, AST::Module& mod)
for(const auto& node : i_data.path.m_class.as_Absolute().nodes )
path.push_back( node.name() );
mod.m_macro_imports.push_back({
- i.is_pub, i.name, mv$(path), e.mac
+ i.is_pub, i_data.name, mv$(path), e.mac
});
}
// TODO: Other imports (e.g. derives, which have different naming structures)
@@ -411,16 +411,19 @@ void Resolve_Index_Module_Wildcard__submod(AST::Crate& crate, AST::Module& dst_m
{
if( ! i.data.is_Use() )
continue ;
- if( i.name != "" )
- continue ;
- Resolve_Index_Module_Wildcard__use_stmt(crate, dst_mod, i.data.as_Use(), import_as_pub);
+ for(const auto& e : i.data.as_Use().entries)
+ {
+ if( e.name != "" )
+ continue ;
+ Resolve_Index_Module_Wildcard__use_stmt(crate, dst_mod, e, import_as_pub);
+ }
}
}
stack.erase(&src_mod);
}
-void Resolve_Index_Module_Wildcard__use_stmt(AST::Crate& crate, AST::Module& dst_mod, const AST::UseStmt& i_data, bool is_pub)
+void Resolve_Index_Module_Wildcard__use_stmt(AST::Crate& crate, AST::Module& dst_mod, const AST::UseItem::Ent& i_data, bool is_pub)
{
const auto& sp = i_data.sp;
const auto& b = i_data.path.m_bindings.type;
@@ -443,7 +446,9 @@ void Resolve_Index_Module_Wildcard__use_stmt(AST::Crate& crate, AST::Module& dst
Resolve_Index_Module_Wildcard__submod(crate, dst_mod, *e.module_, is_pub);
}
)
- else TU_IFLET(::AST::PathBinding_Type, b, Enum, e,
+ else if( const auto* ep = b.opt_Enum() )
+ {
+ const auto& e = *ep;
ASSERT_BUG(sp, e.enum_ || e.hir, "Glob import but enum pointer not set - " << i_data.path);
if( e.enum_ )
{
@@ -500,7 +505,7 @@ void Resolve_Index_Module_Wildcard__use_stmt(AST::Crate& crate, AST::Module& dst
}
}
}
- )
+ }
else
{
BUG(sp, "Invalid path binding for glob import: " << b.tag_str() << " - "<<i_data.path);
@@ -522,9 +527,12 @@ void Resolve_Index_Module_Wildcard(AST::Crate& crate, AST::Module& mod)
{
if( ! i.data.is_Use() )
continue ;
- if( i.name != "" )
- continue ;
- Resolve_Index_Module_Wildcard__use_stmt(crate, mod, i.data.as_Use(), i.is_pub);
+ for(const auto& e : i.data.as_Use().entries )
+ {
+ if( e.name != "" )
+ continue ;
+ Resolve_Index_Module_Wildcard__use_stmt(crate, mod, e, i.is_pub);
+ }
}
// Mark this as having all the items it ever will.
diff --git a/src/resolve/use.cpp b/src/resolve/use.cpp
index 203256a4..cde52de1 100644
--- a/src/resolve/use.cpp
+++ b/src/resolve/use.cpp
@@ -113,39 +113,42 @@ void Resolve_Use_Mod(const ::AST::Crate& crate, ::AST::Module& mod, ::AST::Path
auto& use_stmt_data = use_stmt.data.as_Use();
const Span& span = use_stmt_data.sp;
- use_stmt_data.path = Resolve_Use_AbsolutisePath(span, path, mv$(use_stmt_data.path));
- if( !use_stmt_data.path.m_class.is_Absolute() )
- BUG(span, "Use path is not absolute after absolutisation");
-
- // NOTE: Use statements can refer to _three_ different items
- // - types/modules ("type namespace")
- // - values ("value namespace")
- // - macros ("macro namespace")
- // TODO: Have Resolve_Use_GetBinding return the actual path
- use_stmt_data.path.m_bindings = Resolve_Use_GetBinding(span, crate, use_stmt_data.path, parent_modules);
- if( !use_stmt_data.path.m_bindings.has_binding() )
+ for(auto& use_ent : use_stmt_data.entries)
{
- ERROR(span, E0000, "Unable to resolve `use` target " << use_stmt_data.path);
- }
- DEBUG("'" << use_stmt.name << "' = " << use_stmt_data.path);
+ use_ent.path = Resolve_Use_AbsolutisePath(span, path, mv$(use_ent.path));
+ if( !use_ent.path.m_class.is_Absolute() )
+ BUG(span, "Use path is not absolute after absolutisation");
+
+ // NOTE: Use statements can refer to _three_ different items
+ // - types/modules ("type namespace")
+ // - values ("value namespace")
+ // - macros ("macro namespace")
+ // TODO: Have Resolve_Use_GetBinding return the actual path
+ use_ent.path.m_bindings = Resolve_Use_GetBinding(span, crate, use_ent.path, parent_modules);
+ if( !use_ent.path.m_bindings.has_binding() )
+ {
+ ERROR(span, E0000, "Unable to resolve `use` target " << use_ent.path);
+ }
+ DEBUG("'" << use_ent.name << "' = " << use_ent.path);
- // - If doing a glob, ensure the item type is valid
- if( use_stmt.name == "" )
- {
- TU_MATCH_DEF(::AST::PathBinding_Type, (use_stmt_data.path.m_bindings.type), (e),
- (
- ERROR(span, E0000, "Wildcard import of invalid item type - " << use_stmt_data.path);
- ),
- (Enum,
- ),
- (Crate,
- ),
- (Module,
+ // - If doing a glob, ensure the item type is valid
+ if( use_ent.name == "" )
+ {
+ TU_MATCH_DEF(::AST::PathBinding_Type, (use_ent.path.m_bindings.type), (e),
+ (
+ ERROR(span, E0000, "Wildcard import of invalid item type - " << use_ent.path);
+ ),
+ (Enum,
+ ),
+ (Crate,
+ ),
+ (Module,
+ )
)
- )
- }
- else
- {
+ }
+ else
+ {
+ }
}
}
@@ -342,111 +345,116 @@ void Resolve_Use_Mod(const ::AST::Crate& crate, ::AST::Module& mod, ::AST::Path
if( ! imp.data.is_Use() )
continue ;
const auto& imp_data = imp.data.as_Use();
- const Span& sp2 = imp_data.sp;
- if( imp.name == des_item_name ) {
- DEBUG("- Named import " << imp.name << " = " << imp_data);
- if( !imp_data.path.m_bindings.has_binding() ) {
- DEBUG(" > Needs resolve");
- // TODO: Handle possibility of recursion
- //out_path = imp_data.path;
- return Resolve_Use_GetBinding(sp2, crate, Resolve_Use_AbsolutisePath(sp2, mod.path(), imp_data.path), parent_modules);
- }
- else {
- //out_path = imp_data.path;
- return imp_data.path.m_bindings.clone();
- }
- }
- if( imp.is_pub && imp.name == "" ) {
- DEBUG("- Search glob of " << imp_data.path);
- // INEFFICIENT! Resolves and throws away the result (because we can't/shouldn't mutate here)
- ::AST::Path::Bindings bindings_;
- const auto* bindings = &imp_data.path.m_bindings;
- if( bindings->type.is_Unbound() ) {
- DEBUG("Temp resolving wildcard " << imp_data);
- // Handle possibility of recursion
- static ::std::vector<const ::AST::UseStmt*> resolve_stack_ptrs;
- if( ::std::find(resolve_stack_ptrs.begin(), resolve_stack_ptrs.end(), &imp_data) == resolve_stack_ptrs.end() )
- {
- resolve_stack_ptrs.push_back( &imp_data );
- bindings_ = Resolve_Use_GetBinding(sp2, crate, Resolve_Use_AbsolutisePath(sp2, mod.path(), imp_data.path), parent_modules);
- // *waves hand* I'm not evil.
- const_cast< ::AST::Path::Bindings&>( imp_data.path.m_bindings ) = bindings_.clone();
- bindings = &bindings_;
- resolve_stack_ptrs.pop_back();
+ for( const auto& imp_e : imp_data.entries )
+ {
+ const Span& sp2 = imp_e.sp;
+ if( imp_e.name == des_item_name ) {
+ DEBUG("- Named import " << imp_e.name << " = " << imp_e.path);
+ if( !imp_e.path.m_bindings.has_binding() ) {
+ DEBUG(" > Needs resolve");
+ // TODO: Handle possibility of recursion
+ //out_path = imp_e.path;
+ return Resolve_Use_GetBinding(sp2, crate, Resolve_Use_AbsolutisePath(sp2, mod.path(), imp_e.path), parent_modules);
}
else {
- continue ;
+ //out_path = imp_e.path;
+ return imp_e.path.m_bindings.clone();
}
}
- else {
- //out_path = imp_data.path;
- }
- TU_MATCH_HDRA( (bindings->type), {)
- TU_ARMA(Crate, e) {
- assert(e.crate_);
- const ::HIR::Module& hmod = e.crate_->m_hir->m_root_module;
- auto rv = Resolve_Use_GetBinding__ext(sp2, crate, AST::Path("", { AST::PathNode(des_item_name,{}) }), hmod, 0);
- if( rv.has_binding() ) {
- return mv$(rv);
- }
- }
- TU_ARMA(Module, e) {
- if( e.module_ ) {
- // TODO: Prevent infinite recursion?
- auto rv = Resolve_Use_GetBinding_Mod(span, crate, *e.module_, des_item_name, {});
- if( rv.has_binding() ) {
- return mv$(rv);
+ if( imp.is_pub && imp_e.name == "" )
+ {
+ DEBUG("- Search glob of " << imp_e.path);
+ // INEFFICIENT! Resolves and throws away the result (because we can't/shouldn't mutate here)
+ ::AST::Path::Bindings bindings_;
+ const auto* bindings = &imp_e.path.m_bindings;
+ if( bindings->type.is_Unbound() ) {
+ DEBUG("Temp resolving wildcard " << imp_e.path);
+ // Handle possibility of recursion
+ static ::std::vector<const ::AST::UseItem*> resolve_stack_ptrs;
+ if( ::std::find(resolve_stack_ptrs.begin(), resolve_stack_ptrs.end(), &imp_data) == resolve_stack_ptrs.end() )
+ {
+ resolve_stack_ptrs.push_back( &imp_data );
+ bindings_ = Resolve_Use_GetBinding(sp2, crate, Resolve_Use_AbsolutisePath(sp2, mod.path(), imp_e.path), parent_modules);
+ // *waves hand* I'm not evil.
+ const_cast< ::AST::Path::Bindings&>( imp_e.path.m_bindings ) = bindings_.clone();
+ bindings = &bindings_;
+ resolve_stack_ptrs.pop_back();
}
+ else {
+ continue ;
+ }
+ }
+ else {
+ //out_path = imp_e.path;
}
- else if( e.hir ) {
- const ::HIR::Module& hmod = *e.hir;
+
+ TU_MATCH_HDRA( (bindings->type), {)
+ TU_ARMA(Crate, e) {
+ assert(e.crate_);
+ const ::HIR::Module& hmod = e.crate_->m_hir->m_root_module;
auto rv = Resolve_Use_GetBinding__ext(sp2, crate, AST::Path("", { AST::PathNode(des_item_name,{}) }), hmod, 0);
if( rv.has_binding() ) {
return mv$(rv);
}
- }
- else {
- BUG(span, "NULL module for binding on glob of " << imp_data.path);
- }
- }
- TU_ARMA(Enum, e) {
- assert(e.enum_ || e.hir);
- if( e.enum_ ) {
- const auto& enm = *e.enum_;
- unsigned int i = 0;
- for(const auto& var : enm.variants())
- {
- if( var.m_name == des_item_name ) {
- ::AST::Path::Bindings rv;
- if( var.m_data.is_Struct() )
- rv.type = ::AST::PathBinding_Type::make_EnumVar({ &enm, i });
- else
- rv.value = ::AST::PathBinding_Value::make_EnumVar({ &enm, i });
- return rv;
+ }
+ TU_ARMA(Module, e) {
+ if( e.module_ ) {
+ // TODO: Prevent infinite recursion?
+ auto rv = Resolve_Use_GetBinding_Mod(span, crate, *e.module_, des_item_name, {});
+ if( rv.has_binding() ) {
+ return mv$(rv);
}
- i ++;
}
- }
- else {
- const auto& enm = *e.hir;
- auto idx = enm.find_variant(des_item_name);
- if( idx != SIZE_MAX )
- {
- ::AST::Path::Bindings rv;
- if( enm.m_data.is_Data() && enm.m_data.as_Data()[idx].is_struct ) {
- rv.type = ::AST::PathBinding_Type::make_EnumVar({ nullptr, static_cast<unsigned>(idx), &enm });
+ else if( e.hir ) {
+ const ::HIR::Module& hmod = *e.hir;
+ auto rv = Resolve_Use_GetBinding__ext(sp2, crate, AST::Path("", { AST::PathNode(des_item_name,{}) }), hmod, 0);
+ if( rv.has_binding() ) {
+ return mv$(rv);
}
- else {
- rv.value = ::AST::PathBinding_Value::make_EnumVar({ nullptr, static_cast<unsigned>(idx), &enm });
+ }
+ else {
+ BUG(span, "NULL module for binding on glob of " << imp_e.path);
+ }
+ }
+ TU_ARMA(Enum, e) {
+ assert(e.enum_ || e.hir);
+ if( e.enum_ ) {
+ const auto& enm = *e.enum_;
+ unsigned int i = 0;
+ for(const auto& var : enm.variants())
+ {
+ if( var.m_name == des_item_name ) {
+ ::AST::Path::Bindings rv;
+ if( var.m_data.is_Struct() )
+ rv.type = ::AST::PathBinding_Type::make_EnumVar({ &enm, i });
+ else
+ rv.value = ::AST::PathBinding_Value::make_EnumVar({ &enm, i });
+ return rv;
+ }
+ i ++;
+ }
+ }
+ else {
+ const auto& enm = *e.hir;
+ auto idx = enm.find_variant(des_item_name);
+ if( idx != SIZE_MAX )
+ {
+ ::AST::Path::Bindings rv;
+ if( enm.m_data.is_Data() && enm.m_data.as_Data()[idx].is_struct ) {
+ rv.type = ::AST::PathBinding_Type::make_EnumVar({ nullptr, static_cast<unsigned>(idx), &enm });
+ }
+ else {
+ rv.value = ::AST::PathBinding_Value::make_EnumVar({ nullptr, static_cast<unsigned>(idx), &enm });
+ }
+ return rv;
}
- return rv;
}
+ } break;
+ default:
+ BUG(sp2, "Wildcard import expanded to an invalid item class - " << bindings->type.tag_str());
+ break;
}
- } break;
- default:
- BUG(sp2, "Wildcard import expanded to an invalid item class - " << bindings->type.tag_str());
- break;
}
}
}