diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ast/ast.cpp | 23 | ||||
-rw-r--r-- | src/ast/ast.hpp | 32 | ||||
-rw-r--r-- | src/ast/dump.cpp | 23 | ||||
-rw-r--r-- | src/expand/mod.cpp | 2 | ||||
-rw-r--r-- | src/expand/std_prelude.cpp | 4 | ||||
-rw-r--r-- | src/parse/root.cpp | 202 | ||||
-rw-r--r-- | src/resolve/index.cpp | 64 | ||||
-rw-r--r-- | src/resolve/use.cpp | 244 |
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; } } } |