From a9f50a04705603e696dbcd6bb0f5f5ded4fde759 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 28 Jan 2024 17:57:34 +0800 Subject: [PATCH] Expand - Refactor to run in two (or more) passes to handle macro definition quirks No idea if this is the correct way (could have been that libstd wanted `macro_use` to cause a sorting change, or early expansion), but it works --- Notes/UpgradeQuirks.txt | 18 + src/ast/ast.cpp | 2 +- src/ast/macro.hpp | 4 + src/expand/codegen.cpp | 2 +- src/expand/macro_rules.cpp | 76 +++- src/expand/mod.cpp | 705 ++++++++++++++++++------------- src/expand/std_prelude.cpp | 2 +- src/include/synext_decorator.hpp | 1 + 8 files changed, 499 insertions(+), 311 deletions(-) diff --git a/Notes/UpgradeQuirks.txt b/Notes/UpgradeQuirks.txt index 38bc18fc4..113c6cf53 100644 --- a/Notes/UpgradeQuirks.txt +++ b/Notes/UpgradeQuirks.txt @@ -48,3 +48,21 @@ - Generic values raised to statics - U128 literals required - An annoying-to-debug excessive memset caused by a bad float to u64 cast + + + +=== 1.74 === +- if-let chains +- `if let` in match guards +- Closure captures +- `FnPtr` trait +- unsized locals +- `const` blocks +- `macro_rules` "operators" +- `Box::new` now recurses with a `#[rustc_box]`-annotated expression. + - WHY? WHY is Box::new so funky. INTRINSICS EXIST FOR A REASON! +- `Drop for Box` is FINALLY a normal impl! +- `type Foo = impl Trait` +- `libstd` has a reference to `thread_local!` (well, `thread_local_inner!`) that is used before the `mod sys` that defines `thread_local_inner!`) + - To solve this, need to loop on expand until nothing expands + - That took ages to code. \ No newline at end of file diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index a37fc4ce1..4faf00707 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -49,7 +49,7 @@ const Attribute* AttributeList::get(const char *name) const return &i; } } - return 0; + return nullptr; } ::std::ostream& operator<<(::std::ostream& os, const AttributeList& x) { diff --git a/src/ast/macro.hpp b/src/ast/macro.hpp index add714d2c..2c4e8dedd 100644 --- a/src/ast/macro.hpp +++ b/src/ast/macro.hpp @@ -22,6 +22,7 @@ class MacroInvocation AST::Path m_macro_path; RcString m_ident; TokenTree m_input; + bool m_is_expanded = false; public: MacroInvocation(MacroInvocation&&) = default; MacroInvocation& operator=(MacroInvocation&&) = default; @@ -51,6 +52,9 @@ class MacroInvocation const Span& span() const { return m_span; } const AST::Path& path() const { return m_macro_path; } + bool is_expanded() const { return m_is_expanded; } + void set_expanded() { m_is_expanded = true; } + const RcString& input_ident() const { return m_ident; } const TokenTree& input_tt() const { return m_input; } TokenTree& input_tt() { return m_input; } diff --git a/src/expand/codegen.cpp b/src/expand/codegen.cpp index 914962cac..6ebda18a1 100644 --- a/src/expand/codegen.cpp +++ b/src/expand/codegen.cpp @@ -89,7 +89,7 @@ class CHandler_Cold: void handle(const AST::Attribute& mi, AST::Function& fcn) const override { TTStream lex(mi.span(), ParseState(), mi.data()); lex.getTokenCheck(TOK_EOF); - ASSERT_BUG(mi.span(), !fcn.m_markings.is_cold, "Duplicate #[cold] attributes"); + //ASSERT_BUG(mi.span(), !fcn.m_markings.is_cold, "Duplicate #[cold] attributes"); fcn.m_markings.is_cold = true; } }; diff --git a/src/expand/macro_rules.cpp b/src/expand/macro_rules.cpp index a44493e10..0c751de52 100644 --- a/src/expand/macro_rules.cpp +++ b/src/expand/macro_rules.cpp @@ -41,6 +41,7 @@ class CMacroUseHandler: public ExpandDecorator { AttrStage stage() const override { return AttrStage::Post; } + bool run_during_iter() const override { return true; } void handle(const Span& sp, const AST::Attribute& mi, ::AST::Crate& crate, const AST::AbsolutePath& path, AST::Module& mod, slice attrs, AST::Item& i) const override { @@ -70,6 +71,26 @@ class CMacroUseHandler: } }; + auto exists = [&mod](const RcString& name, const MacroRef& mr)->bool { + for( const auto& imp : mod.macro_imports_res() ) { + if( imp.name != name ) + continue; + if( imp.data.tag() != mr.tag() ) + continue ; + bool rv; + TU_MATCH_HDRA( (imp.data, mr), {) + TU_ARMA(None, a,b) { rv = true; } + TU_ARMA(MacroRules, a,b) { rv = (a == b); } + TU_ARMA(BuiltinProcMacro, a,b) { rv = (a == b); } + TU_ARMA(ExternalProcMacro, a,b) { rv = (a == b); } + } + if(rv) { + return true; + } + } + return false; + }; + if(i.is_None()) { // Just ignore } @@ -117,24 +138,33 @@ class CMacroUseHandler: } } + MacroRef mr; TU_MATCH_HDRA( (e->ent), { ) - TU_ARMA(Import, imp) { - assert(false); - } - TU_ARMA(MacroRules, mac_ptr) { - DEBUG("Imported " << name << "!"); + TU_ARMA(Import, imp) { throw "Unexpected"; } + TU_ARMA(MacroRules, mac_ptr) { mr = &*mac_ptr; } + TU_ARMA(ProcMacro, p) { mr = &p; } + } + if(!exists(name, mr)) + { + mod.add_macro_import( sp, name, std::move(mr) ); + + TU_MATCH_HDRA( (e->ent), { ) + TU_ARMA(Import, imp) { + throw "Unexpected"; + } + TU_ARMA(MacroRules, mac_ptr) { + DEBUG("Imported " << name << "!"); - auto mi = AST::Module::MacroImport{ false, name, make_vec2(ec_item->name, name), &*mac_ptr }; - mod.m_macro_imports.push_back(mv$(mi)); + auto mi = AST::Module::MacroImport{ false, name, make_vec2(ec_item->name, name), &*mac_ptr }; + mod.m_macro_imports.push_back(mv$(mi)); + } + TU_ARMA(ProcMacro, p) { + DEBUG("Imported " << name << "! (proc macro)"); - mod.add_macro_import( sp, name, &*mac_ptr ); - } - TU_ARMA(ProcMacro, p) { - DEBUG("Imported " << name << "! (proc macro)"); - auto mi = AST::Module::MacroImport{ false, p.path.m_components.back(), p.path.m_components, nullptr }; - mi.path.insert(mi.path.begin(), p.path.m_crate_name); - mod.m_macro_imports.push_back(mv$(mi)); - mod.add_macro_import( sp, name, &p ); + auto mi = AST::Module::MacroImport{ false, p.path.m_components.back(), p.path.m_components, nullptr }; + mi.path.insert(mi.path.begin(), p.path.m_crate_name); + mod.m_macro_imports.push_back(mv$(mi)); + } } } } @@ -144,21 +174,25 @@ class CMacroUseHandler: const auto& submod = *submod_p; for( const auto& mr : submod.macros() ) { - if( !filter_valid(mr.name) ) - { + if( !filter_valid(mr.name) ) { continue; } DEBUG("Imported " << mr.name); - mod.add_macro_import( sp, mr.name, &*mr.data ); + if( !exists(mr.name, &*mr.data) ) + { + mod.add_macro_import( sp, mr.name, &*mr.data ); + } } for( const auto& mri : submod.macro_imports_res() ) { - if( !filter_valid(mri.name) ) - { + if( !filter_valid(mri.name) ) { continue; } DEBUG("Imported " << mri.name << " (propagate)"); - mod.add_macro_import( sp, mri.name, mri.data.clone() ); + if( !exists(mri.name, mri.data) ) + { + mod.add_macro_import( sp, mri.name, mri.data.clone() ); + } } } else { diff --git a/src/expand/mod.cpp b/src/expand/mod.cpp index af10af69b..513c148a1 100644 --- a/src/expand/mod.cpp +++ b/src/expand/mod.cpp @@ -27,12 +27,36 @@ MacroDef* g_macros_list = nullptr; ::std::map< RcString, ::std::unique_ptr > g_decorators; ::std::map< RcString, ::std::unique_ptr > g_macros; -void Expand_Attrs(const ::AST::AttributeList& attrs, AttrStage stage, ::std::function f); -void Expand_Mod(::AST::Crate& crate, LList modstack, ::AST::AbsolutePath modpath, ::AST::Module& mod, unsigned int first_item = 0); -void Expand_Expr(::AST::Crate& crate, LList modstack, ::AST::ExprNodeP& node); -void Expand_Expr(::AST::Crate& crate, LList modstack, AST::Expr& node); -void Expand_Expr(::AST::Crate& crate, LList modstack, ::std::shared_ptr& node); -void Expand_Path(::AST::Crate& crate, LList modstack, ::AST::Module& mod, ::AST::Path& p); +enum class ExpandMode { + FirstPass, + Iterate, + Final, +}; + +struct ExpandState { + ::AST::Crate& crate; + LList modstack; + ExpandMode mode; + mutable bool change; + mutable bool has_missing; + ExpandState(::AST::Crate& crate, LList modstack, ExpandMode mode) + : crate(crate) + , modstack(modstack) + , mode(mode) + , change(false) + , has_missing(false) + { + DEBUG("" << this); + } + explicit ExpandState(const ExpandState&) = default; +}; + +void Expand_Attrs(const ExpandState& es, const ::AST::AttributeList& attrs, AttrStage stage, ::std::function f); +void Expand_Mod(const ExpandState& es, ::AST::AbsolutePath modpath, ::AST::Module& mod, unsigned int first_item = 0); +void Expand_Expr(const ExpandState& es, ::AST::ExprNodeP& node); +void Expand_Expr(const ExpandState& es, AST::Expr& node); +void Expand_Expr(const ExpandState& es, ::std::shared_ptr& node); +void Expand_Path(const ExpandState& es, ::AST::Module& mod, ::AST::Path& p); void Register_Synext_Decorator(::std::string name, ::std::unique_ptr handler) { g_decorators.insert(::std::make_pair( RcString::new_interned(name), mv$(handler) )); @@ -84,18 +108,38 @@ ExpandProcMacro* Expand_FindProcMacro(const RcString& name) return it->second.get(); } -void Expand_Attr(const Span& sp, const ::AST::Attribute& a, AttrStage stage, ::std::function f) +void Expand_Attr(const ExpandState& es, const Span& sp, const ::AST::Attribute& a, AttrStage stage, ::std::function f) { bool found = false; for( auto& d : g_decorators ) { if( a.name() == d.first ) { - DEBUG("#[" << d.first << "] " << (int)d.second->stage() << "-" << (int)stage); - if( d.second->stage() == stage ) { + found = true; + if( d.second->stage() != stage ) { + DEBUG("#[" << d.first << "] s=" << (int)d.second->stage() << " != " << (int)stage); + } + else { + if( !d.second->run_during_iter() ) { + switch(es.mode) { + case ExpandMode::FirstPass: + if( stage != AttrStage::Pre ) { + DEBUG("#[" << d.first << "] m=" << (int)es.mode); + continue ; + } + break; + case ExpandMode::Iterate: + continue ; + case ExpandMode::Final: + if( stage != AttrStage::Post ) { + DEBUG("#[" << d.first << "] m=" << (int)es.mode); + continue ; + } + break; + } + } + DEBUG("#[" << d.first << "]"); f(sp, *d.second, a); - // TODO: Early return? // TODO: Annotate the attribute as having been handled } - found = true; } } if( !found ) { @@ -104,11 +148,11 @@ void Expand_Attr(const Span& sp, const ::AST::Attribute& a, AttrStage stage, :: //WARNING(sp, W0000, "Unknown attribute #[" << a.name() << "]"); } } -void Expand_Attrs(const ::AST::AttributeList& attrs, AttrStage stage, ::std::function f) +void Expand_Attrs(const ExpandState& es, const ::AST::AttributeList& attrs, AttrStage stage, ::std::function f) { for( auto& a : attrs.m_items ) { - Expand_Attr(a.span(), a, stage, f); + Expand_Attr(es, a.span(), a, stage, f); } } void Expand_Attrs_CfgAttr(AST::AttributeList& attrs) @@ -126,43 +170,43 @@ void Expand_Attrs_CfgAttr(AST::AttributeList& attrs) } } } -void Expand_Attrs(const ::AST::AttributeList& attrs, AttrStage stage, ::AST::Crate& crate, const ::AST::AbsolutePath& path, ::AST::Module& mod, ::AST::Item& item) +void Expand_Attrs(const ExpandState& es, const ::AST::AttributeList& attrs, AttrStage stage, const ::AST::AbsolutePath& path, ::AST::Module& mod, ::AST::Item& item) { - Expand_Attrs(attrs, stage, [&](const auto& sp, const auto& d, const auto& a){ + Expand_Attrs(es, attrs, stage, [&](const Span& sp, const auto& d, const auto& a){ if(!item.is_None()) { // TODO: Pass attributes _after_ this attribute - d.handle(sp, a, crate, path, mod, slice(&a, &attrs.m_items.back() - &a + 1), item); + d.handle(sp, a, es.crate, path, mod, slice(&a, &attrs.m_items.back() - &a + 1), item); } }); } -void Expand_Attrs(const ::AST::AttributeList& attrs, AttrStage stage, ::AST::Crate& crate, const ::AST::AbsolutePath& path, ::AST::Trait& trait, ::AST::Item& item) +void Expand_Attrs(const ExpandState& es, const ::AST::AttributeList& attrs, AttrStage stage, const ::AST::AbsolutePath& path, ::AST::Trait& trait, ::AST::Item& item) { - Expand_Attrs(attrs, stage, [&](const auto& sp, const auto& d, const auto& a){ + Expand_Attrs(es, attrs, stage, [&](const Span& sp, const auto& d, const auto& a){ if(!item.is_None()) { // TODO: Pass attributes _after_ this attribute - d.handle(sp, a, crate, path, trait, slice(&a, &attrs.m_items.back() - &a + 1), item); + d.handle(sp, a, es.crate, path, trait, slice(&a, &attrs.m_items.back() - &a + 1), item); } }); } -void Expand_Attrs(const ::AST::AttributeList& attrs, AttrStage stage, ::AST::Crate& crate, ::AST::Impl& impl, const RcString& name, ::AST::Item& item) +void Expand_Attrs(const ExpandState& es, const ::AST::AttributeList& attrs, AttrStage stage, ::AST::Impl& impl, const RcString& name, ::AST::Item& item) { - Expand_Attrs(attrs, stage, [&](const auto& sp, const auto& d, const auto& a){ + Expand_Attrs(es, attrs, stage, [&](const Span& sp, const auto& d, const auto& a){ if(!item.is_None()) { // TODO: Pass attributes _after_ this attribute - d.handle(sp, a, crate, impl, name, slice(&a, &attrs.m_items.back() - &a + 1), item); + d.handle(sp, a, es.crate, impl, name, slice(&a, &attrs.m_items.back() - &a + 1), item); } }); } -void Expand_Attrs(const ::AST::AttributeList& attrs, AttrStage stage, ::AST::Crate& crate, ::AST::Module& mod, ::AST::ImplDef& impl) +void Expand_Attrs(const ExpandState& es, const ::AST::AttributeList& attrs, AttrStage stage, ::AST::Module& mod, ::AST::ImplDef& impl) { - Expand_Attrs(attrs, stage, [&](const auto& sp, const auto& d, const auto& a){ d.handle(sp, a, crate, mod, impl); }); + Expand_Attrs(es, attrs, stage, [&](const Span& sp, const auto& d, const auto& a){ d.handle(sp, a, es.crate, mod, impl); }); } -bool Expand_Attrs_CfgOnly(AST::AttributeList& attrs) +bool Expand_Attrs_CfgOnly(const ExpandState& es, AST::AttributeList& attrs) { bool remove = false; Expand_Attrs_CfgAttr(attrs); - Expand_Attrs(attrs, AttrStage::Pre, [&](const Span& sp, const ExpandDecorator& d, const AST::Attribute& a) { + Expand_Attrs(es, attrs, AttrStage::Pre, [&](const Span& sp, const ExpandDecorator& d, const AST::Attribute& a) { if( a.name() == "cfg" ) { if( !check_cfg(sp, a) ) { remove = true; @@ -257,9 +301,7 @@ ::std::unique_ptr Expand_Macro_Inner( Span mi_span, const AST::Path& path, const RcString& input_ident, TokenTree& input_tt ) { - if( !path.is_valid() ) { - return ::std::unique_ptr(); - } + ASSERT_BUG(mi_span, path.is_valid(), "Macro invocation with invalid path"); TRACE_FUNCTION_F("Searching for macro " << path); @@ -270,53 +312,64 @@ ::std::unique_ptr Expand_Macro_Inner( // TODO: If `mr_ptr` is tagged with #[rustc_builtin_macro], look for a matching entry in `g_macros` } + ::std::unique_ptr rv; TU_MATCH_HDRA( (mac), {) TU_ARMA(None, e) { - ERROR(mi_span, E0000, "Unknown macro " << path); + DEBUG("Unknown macro " << path); + return ::std::unique_ptr(); } TU_ARMA(ExternalProcMacro, proc_mac) { ::std::vector mac_path; mac_path.push_back(proc_mac->path.m_crate_name); mac_path.insert(mac_path.end(), proc_mac->path.m_components.begin(), proc_mac->path.m_components.end()); - return ProcMacro_Invoke(mi_span, crate, mac_path, input_tt); + rv = ProcMacro_Invoke(mi_span, crate, mac_path, input_tt); } TU_ARMA(BuiltinProcMacro, proc_mac) { ASSERT_BUG(mi_span, proc_mac, "null BuiltinProcMacro? " << path); - auto e = input_ident == "" + rv = input_ident == "" ? proc_mac->expand(mi_span, crate, input_tt, mod) : proc_mac->expand_ident(mi_span, crate, input_ident, input_tt, mod) ; - return e; } TU_ARMA(MacroRules, mr_ptr) { if( input_ident != "" ) ERROR(mi_span, E0000, "macro_rules! macros can't take an ident"); DEBUG("Invoking macro_rules " << path << " " << mr_ptr); - auto e = Macro_InvokeRules(path.is_trivial() ? path.as_trivial().c_str() : FMT(path).c_str(), *mr_ptr, mi_span, mv$(input_tt), crate, mod); + rv = Macro_InvokeRules(path.is_trivial() ? path.as_trivial().c_str() : FMT(path).c_str(), *mr_ptr, mi_span, mv$(input_tt), crate, mod); input_tt = TokenTree(); - return e; } } - throw ""; + ASSERT_BUG(mi_span, rv, "Macro invocation returned null tokentree"); + return rv; } ::std::unique_ptr Expand_Macro( - const ::AST::Crate& crate, LList modstack, ::AST::Module& mod, - Span mi_span, const AST::Path& name, const RcString& input_ident, TokenTree& input_tt + const ExpandState& es, ::AST::Module& mod, + Span mi_span, const AST::Path& path, const RcString& input_ident, TokenTree& input_tt ) { - auto rv = Expand_Macro_Inner(crate, modstack, mod, mi_span, name, input_ident, input_tt); - assert(rv); - rv->parse_state().crate = &crate; - rv->parse_state().module = &mod; + if( es.mode == ExpandMode::Final ) { + ERROR(mi_span, E0000, "Unknown macro " << path); + } + auto rv = Expand_Macro_Inner(es.crate, es.modstack, mod, mi_span, path, input_ident, input_tt); + if( rv ) { + es.change = true; + DEBUG("Change flagged"); + rv->parse_state().crate = &es.crate; + rv->parse_state().module = &mod; + } + else { + DEBUG("Missing, waiting until another pass"); + es.has_missing = true; + } return rv; } -::std::unique_ptr Expand_Macro(const ::AST::Crate& crate, LList modstack, ::AST::Module& mod, ::AST::MacroInvocation& mi) +::std::unique_ptr Expand_Macro(const ExpandState& es, ::AST::Module& mod, ::AST::MacroInvocation& mi) { - return Expand_Macro(crate, modstack, mod, mi.span(), mi.path(), mi.input_ident(), mi.input_tt()); + return Expand_Macro(es, mod, mi.span(), mi.path(), mi.input_ident(), mi.input_tt()); } -void Expand_Pattern(::AST::Crate& crate, LList modstack, ::AST::Module& mod, ::AST::Pattern& pat, bool is_refutable) +void Expand_Pattern(const ExpandState& es, ::AST::Module& mod, ::AST::Pattern& pat, bool is_refutable) { TU_MATCH_HDRA( (pat.data()), {) TU_ARMA(MaybeBind, e) { @@ -324,30 +377,30 @@ void Expand_Pattern(::AST::Crate& crate, LList modstack, ::A TU_ARMA(Macro, e) { const auto span = e.inv->span(); - auto tt = Expand_Macro(crate, modstack, mod, *e.inv); - if( ! tt ) { - ERROR(span, E0000, "Macro in pattern didn't expand to anything"); - } - auto& lex = *tt; - auto newpat = Parse_Pattern(lex); - if( LOOK_AHEAD(lex) != TOK_EOF ) { - ERROR(span, E0000, "Trailing tokens in macro expansion"); - } + auto tt = Expand_Macro(es, mod, *e.inv); + if( tt ) + { + auto& lex = *tt; + auto newpat = Parse_Pattern(lex); + if( LOOK_AHEAD(lex) != TOK_EOF ) { + ERROR(span, E0000, "Trailing tokens in macro expansion"); + } - for(auto& b : pat.bindings()) { - newpat.bindings().push_back( std::move(b) ); - } + for(auto& b : pat.bindings()) { + newpat.bindings().push_back( std::move(b) ); + } - pat = mv$(newpat); - Expand_Pattern(crate, modstack, mod, pat, is_refutable); + pat = mv$(newpat); + Expand_Pattern(es, mod, pat, is_refutable); + } } TU_ARMA(Any, e) { } TU_ARMA(Box, e) { - Expand_Pattern(crate, modstack, mod, *e.sub, is_refutable); + Expand_Pattern(es, mod, *e.sub, is_refutable); } TU_ARMA(Ref, e) { - Expand_Pattern(crate, modstack, mod, *e.sub, is_refutable); + Expand_Pattern(es, mod, *e.sub, is_refutable); } TU_ARMA(Value, e) { //Expand_Expr(crate, modstack, e.start); @@ -359,46 +412,46 @@ void Expand_Pattern(::AST::Crate& crate, LList modstack, ::A } TU_ARMA(Tuple, e) { for(auto& sp : e.start) - Expand_Pattern(crate, modstack, mod, sp, is_refutable); + Expand_Pattern(es, mod, sp, is_refutable); for(auto& sp : e.end) - Expand_Pattern(crate, modstack, mod, sp, is_refutable); + Expand_Pattern(es, mod, sp, is_refutable); } TU_ARMA(StructTuple, e) { for(auto& sp : e.tup_pat.start) - Expand_Pattern(crate, modstack, mod, sp, is_refutable); + Expand_Pattern(es, mod, sp, is_refutable); for(auto& sp : e.tup_pat.end) - Expand_Pattern(crate, modstack, mod, sp, is_refutable); + Expand_Pattern(es, mod, sp, is_refutable); } TU_ARMA(Struct, e) { for(auto& subpat : e.sub_patterns) { - if( !Expand_Attrs_CfgOnly(subpat.attrs) ) { + if( !Expand_Attrs_CfgOnly(es, subpat.attrs) ) { subpat.name = RcString(); continue ; } - Expand_Pattern(crate, modstack, mod, subpat.pat, is_refutable); + Expand_Pattern(es, mod, subpat.pat, is_refutable); } auto new_end = std::remove_if(e.sub_patterns.begin(), e.sub_patterns.end(), [&](const auto& e){ return e.name == ""; }); e.sub_patterns.erase(new_end, e.sub_patterns.end()); } TU_ARMA(Slice, e) { for(auto& sp : e.sub_pats) - Expand_Pattern(crate, modstack, mod, sp, is_refutable); + Expand_Pattern(es, mod, sp, is_refutable); } TU_ARMA(SplitSlice, e) { for(auto& sp : e.leading) - Expand_Pattern(crate, modstack, mod, sp, is_refutable); + Expand_Pattern(es, mod, sp, is_refutable); for(auto& sp : e.trailing) - Expand_Pattern(crate, modstack, mod, sp, is_refutable); + Expand_Pattern(es, mod, sp, is_refutable); } TU_ARMA(Or, e) { for(auto& sp : e) - Expand_Pattern(crate, modstack, mod, sp, is_refutable); + Expand_Pattern(es, mod, sp, is_refutable); } } } -void Expand_Type(::AST::Crate& crate, LList modstack, ::AST::Module& mod, ::TypeRef& ty) +void Expand_Type(const ExpandState& es, ::AST::Module& mod, ::TypeRef& ty) { TU_MATCH_HDRA( (ty.m_data), {) TU_ARMA(None, e) { @@ -410,65 +463,66 @@ void Expand_Type(::AST::Crate& crate, LList modstack, ::AST: TU_ARMA(Bang, e) { } TU_ARMA(Macro, e) { - auto tt = Expand_Macro(crate, modstack, mod, *e.inv); - if(!tt) - ERROR(e.inv->span(), E0000, "Macro invocation didn't yeild any data"); - auto new_ty = Parse_Type(*tt); - if( tt->lookahead(0) != TOK_EOF ) - ERROR(e.inv->span(), E0000, "Extra tokens after parsed type"); - ty = mv$(new_ty); + auto tt = Expand_Macro(es, mod, *e.inv); + if(tt) + { + auto new_ty = Parse_Type(*tt); + if( tt->lookahead(0) != TOK_EOF ) + ERROR(e.inv->span(), E0000, "Extra tokens after parsed type"); + ty = mv$(new_ty); - Expand_Type(crate, modstack, mod, ty); + Expand_Type(es, mod, ty); + } } TU_ARMA(Primitive, e) { } TU_ARMA(Function, e) { Type_Function& tf = e.info; - Expand_Type(crate, modstack, mod, *tf.m_rettype); + Expand_Type(es, mod, *tf.m_rettype); for(auto& st : tf.m_arg_types) - Expand_Type(crate, modstack, mod, st); + Expand_Type(es, mod, st); } TU_ARMA(Tuple, e) { for(auto& st : e.inner_types) - Expand_Type(crate, modstack, mod, st); + Expand_Type(es, mod, st); } TU_ARMA(Borrow, e) { - Expand_Type(crate, modstack, mod, *e.inner); + Expand_Type(es, mod, *e.inner); } TU_ARMA(Pointer, e) { - Expand_Type(crate, modstack, mod, *e.inner); + Expand_Type(es, mod, *e.inner); } TU_ARMA(Array, e) { - Expand_Type(crate, modstack, mod, *e.inner); + Expand_Type(es, mod, *e.inner); if( e.size ) { - Expand_Expr(crate, modstack, e.size); + Expand_Expr(es, e.size); } } TU_ARMA(Slice, e) { - Expand_Type(crate, modstack, mod, *e.inner); + Expand_Type(es, mod, *e.inner); } TU_ARMA(Generic, e) { } TU_ARMA(Path, e) { - Expand_Path(crate, modstack, mod, *e); + Expand_Path(es, mod, *e); } TU_ARMA(TraitObject, e) { for(auto& p : e.traits) { // TODO: p.hrbs? Not needed until types are in those - Expand_Path(crate, modstack, mod, *p.path); + Expand_Path(es, mod, *p.path); } } TU_ARMA(ErasedType, e) { for(auto& p : e.traits) { // TODO: p.hrbs? - Expand_Path(crate, modstack, mod, *p.path); + Expand_Path(es, mod, *p.path); } } } } -void Expand_PathParams(::AST::Crate& crate, LList modstack, ::AST::Module& mod, ::AST::PathParams& params) +void Expand_PathParams(const ExpandState& es, ::AST::Module& mod, ::AST::PathParams& params) { for(auto& e : params.m_entries) { @@ -478,26 +532,26 @@ void Expand_PathParams(::AST::Crate& crate, LList modstack, TU_ARMA(Lifetime, _) { } TU_ARMA(Type, typ) { - Expand_Type(crate, modstack, mod, typ); + Expand_Type(es, mod, typ); } TU_ARMA(Value, node) { - Expand_Expr(crate, modstack, node); + Expand_Expr(es, node); } TU_ARMA(AssociatedTyEqual, aty) { - Expand_Type(crate, modstack, mod, aty.second); + Expand_Type(es, mod, aty.second); } TU_ARMA(AssociatedTyBound, aty) { - Expand_Path(crate, modstack, mod, aty.second); + Expand_Path(es, mod, aty.second); } } } } -void Expand_Path(::AST::Crate& crate, LList modstack, ::AST::Module& mod, ::AST::Path& p) +void Expand_Path(const ExpandState& es, ::AST::Module& mod, ::AST::Path& p) { auto expand_nodes = [&](::std::vector<::AST::PathNode>& nodes) { for(auto& node : nodes) { - Expand_PathParams(crate, modstack, mod, node.args()); + Expand_PathParams(es, mod, node.args()); } }; @@ -519,9 +573,9 @@ void Expand_Path(::AST::Crate& crate, LList modstack, ::AST: expand_nodes(pe.nodes); } TU_ARMA(UFCS, pe) { - Expand_Type(crate, modstack, mod, *pe.type); + Expand_Type(es, mod, *pe.type); if( pe.trait ) { - Expand_Path(crate, modstack, mod, *pe.trait); + Expand_Path(es, mod, *pe.trait); } expand_nodes(pe.nodes); } @@ -532,7 +586,8 @@ struct CExpandExpr: public ::AST::NodeVisitor { ::AST::Crate& crate; - LList modstack; + const ExpandState& parent_expand_state; + ExpandState expand_state; ::AST::ExprNodeP replacement; // Stack of `try { ... }` blocks (the string is the loop label for the desugaring) @@ -541,14 +596,30 @@ struct CExpandExpr: AST::ExprNode_Block* current_block = nullptr; - CExpandExpr(::AST::Crate& crate, LList ms): - crate(crate), - modstack(ms) + CExpandExpr(const ExpandState& es) + : crate(es.crate) + , parent_expand_state(es) + , expand_state(es) { } + ~CExpandExpr() + { + if( expand_state.change ) { + if( ! parent_expand_state.change ) { + DEBUG("Propagate change"); + } + parent_expand_state.change = true; + } + if( expand_state.has_missing ) { + if( ! parent_expand_state.has_missing ) { + DEBUG("Propagate has missing (to " << &parent_expand_state << ")"); + } + parent_expand_state.has_missing = true; + } + } ::AST::Module& cur_mod() { - return *const_cast< ::AST::Module*>(modstack.m_item); + return *const_cast< ::AST::Module*>(expand_state.modstack.m_item); } void visit(::AST::ExprNodeP& cnode) { @@ -556,7 +627,7 @@ struct CExpandExpr: { auto attrs = mv$(cnode->attrs()); Expand_Attrs_CfgAttr(attrs); - Expand_Attrs(attrs, AttrStage::Pre, [&](const auto& sp, const ExpandDecorator& d, const auto& a){ d.handle(sp, a, this->crate, cnode); }); + Expand_Attrs(expand_state, attrs, AttrStage::Pre, [&](const Span& sp, const ExpandDecorator& d, const auto& a){ d.handle(sp, a, this->crate, cnode); }); if(cnode.get()) cnode->attrs() = mv$(attrs); } @@ -575,7 +646,7 @@ struct CExpandExpr: } if(cnode.get()) - Expand_Attrs(cnode->attrs(), AttrStage::Post, [&](const auto& sp, const auto& d, const auto& a){ d.handle(sp, a, this->crate, cnode); }); + Expand_Attrs(expand_state, cnode->attrs(), AttrStage::Post, [&](const Span& sp, const auto& d, const auto& a){ d.handle(sp, a, this->crate, cnode); }); assert( ! this->replacement ); } void visit_nodelete(const ::AST::ExprNode& parent, ::AST::ExprNodeP& cnode) { @@ -609,10 +680,11 @@ struct CExpandExpr: ::AST::ExprNodeP rv; auto& mod = this->cur_mod(); - auto ttl = Expand_Macro( crate, modstack, mod, node.span(), node.m_path, node.m_ident, node.m_tokens ); + auto ttl = Expand_Macro( expand_state, mod, node.span(), node.m_path, node.m_ident, node.m_tokens ); if( !ttl.get() ) { // No expansion + DEBUG("Deferred"); } else { @@ -652,6 +724,7 @@ struct CExpandExpr: } } } + node.m_path = AST::Path(); } if( !nodes_out && !rv ) @@ -659,7 +732,6 @@ struct CExpandExpr: ERROR(node.span(), E0000, "Macro didn't expand to anything"); } - node.m_path = AST::Path(); return mv$(rv); } @@ -688,15 +760,15 @@ struct CExpandExpr: void visit(::AST::ExprNode_Block& node) override { unsigned int mod_item_count = 0; - auto prev_modstack = this->modstack; + auto prev_modstack = this->expand_state.modstack; if( node.m_local_mod ) { - this->modstack = LList(&prev_modstack, node.m_local_mod.get()); + this->expand_state.modstack = LList(&prev_modstack, node.m_local_mod.get()); } // TODO: macro_rules! invocations within the expression list influence this. // > Solution: Defer creation of the local module until during expand. if( node.m_local_mod ) { - Expand_Mod(crate, modstack, node.m_local_mod->path(), *node.m_local_mod); + Expand_Mod(this->expand_state, node.m_local_mod->path(), *node.m_local_mod); mod_item_count = node.m_local_mod->m_items.size(); } @@ -711,7 +783,7 @@ struct CExpandExpr: { auto attrs = std::move( (*it)->attrs() ); Expand_Attrs_CfgAttr( attrs ); - Expand_Attrs(attrs, AttrStage::Pre, [&](const auto& sp, const auto& d, const auto& a){ d.handle(sp, a, this->crate, *it); }); + Expand_Attrs(expand_state, attrs, AttrStage::Pre, [&](const Span& sp, const auto& d, const auto& a){ d.handle(sp, a, this->crate, *it); }); if( !it->get() ) { it = node.m_nodes.erase( it ); continue ; @@ -723,9 +795,15 @@ struct CExpandExpr: ::std::vector< ::AST::ExprNodeP> new_nodes; this->visit_macro(*node_mac, &new_nodes); - it = node.m_nodes.erase(it); - it = node.m_nodes.insert(it, ::std::make_move_iterator(new_nodes.begin()), ::std::make_move_iterator(new_nodes.end())); - // NOTE: Doesn't advance the iterator above, we want to re-visit the new node + if(node_mac->m_path.is_valid()) { + DEBUG("Deferred macro"); + ++ it; + } + else { + it = node.m_nodes.erase(it); + it = node.m_nodes.insert(it, ::std::make_move_iterator(new_nodes.begin()), ::std::make_move_iterator(new_nodes.end())); + // NOTE: Doesn't advance the iterator above, we want to re-visit the new node + } } else { @@ -743,10 +821,10 @@ struct CExpandExpr: // HACK! Run Expand_Mod twice on local modules. if( node.m_local_mod ) { - Expand_Mod(crate, modstack, node.m_local_mod->path(), *node.m_local_mod, mod_item_count); + Expand_Mod(this->expand_state, node.m_local_mod->path(), *node.m_local_mod, mod_item_count); } - this->modstack = mv$(prev_modstack); + this->expand_state.modstack = mv$(prev_modstack); } void visit(::AST::ExprNode_Try& node) override { // Desugar into @@ -791,7 +869,7 @@ struct CExpandExpr: this->visit_nodelete(node, e); } TU_ARMA(Sym, e) { - Expand_Path(crate, modstack, this->cur_mod(), e); + Expand_Path(this->expand_state, this->cur_mod(), e); } TU_ARMA(RegSingle, e) { this->visit_nodelete(node, e.val); @@ -807,8 +885,8 @@ struct CExpandExpr: this->visit_nodelete(node, node.m_value); } void visit(::AST::ExprNode_LetBinding& node) override { - Expand_Type(crate, modstack, this->cur_mod(), node.m_type); - Expand_Pattern(crate, modstack, this->cur_mod(), node.m_pat, false); + Expand_Type(this->expand_state, this->cur_mod(), node.m_type); + Expand_Pattern(this->expand_state, this->cur_mod(), node.m_pat, false); this->visit_nodelete(node, node.m_value); this->visit_nodelete(node, node.m_else); } @@ -936,11 +1014,11 @@ struct CExpandExpr: } } void visit(::AST::ExprNode_CallPath& node) override { - Expand_Path(crate, modstack, this->cur_mod(), node.m_path); + Expand_Path(this->expand_state, this->cur_mod(), node.m_path); this->visit_vector(node.m_args); } void visit(::AST::ExprNode_CallMethod& node) override { - Expand_PathParams(crate, modstack, this->cur_mod(), node.m_method.args()); + Expand_PathParams(this->expand_state, this->cur_mod(), node.m_method.args()); this->visit_nodelete(node, node.m_val); this->visit_vector(node.m_args); } @@ -951,7 +1029,7 @@ struct CExpandExpr: void visit(::AST::ExprNode_Loop& node) override { this->visit_nodelete(node, node.m_cond); this->visit_nodelete(node, node.m_code); - Expand_Pattern(crate, modstack, this->cur_mod(), node.m_pattern, false); + Expand_Pattern(this->expand_state, this->cur_mod(), node.m_pattern, false); if(node.m_type == ::AST::ExprNode_Loop::FOR) { auto core_crate = crate.m_ext_cratename_core; @@ -1046,7 +1124,7 @@ struct CExpandExpr: void visit(::AST::ExprNode_WhileLet& node) override { for(auto& cond : node.m_conditions) { if( cond.opt_pat ) { - Expand_Pattern(crate, modstack, this->cur_mod(), *cond.opt_pat, true); + Expand_Pattern(this->expand_state, this->cur_mod(), *cond.opt_pat, true); } this->visit_nodelete(node, cond.value); } @@ -1076,11 +1154,11 @@ struct CExpandExpr: for(auto& arm : node.m_arms) { Expand_Attrs_CfgAttr( arm.m_attrs ); - Expand_Attrs(arm.m_attrs, AttrStage::Pre , [&](const auto& sp, const auto& d, const auto& a){ d.handle(sp, a, crate, arm); }); + Expand_Attrs(expand_state, arm.m_attrs, AttrStage::Pre , [&](const Span& sp, const auto& d, const auto& a){ d.handle(sp, a, crate, arm); }); if( arm.m_patterns.size() == 0 ) continue ; for(auto& pat : arm.m_patterns) { - Expand_Pattern(crate, modstack, this->cur_mod(), pat, true); + Expand_Pattern(this->expand_state, this->cur_mod(), pat, true); } TU_MATCH_HDRA( (arm.m_cond), { ) TU_ARMA(None, e) {} @@ -1089,14 +1167,14 @@ struct CExpandExpr: } TU_ARMA(Pattern, e) { for(auto& pat : e.patterns) { - Expand_Pattern(crate, modstack, this->cur_mod(), pat, true); + Expand_Pattern(this->expand_state, this->cur_mod(), pat, true); } this->visit_nodelete(node, e.val); } } this->visit_nodelete(node, arm.m_code); - Expand_Attrs(arm.m_attrs, AttrStage::Post, [&](const auto& sp, const auto& d, const auto& a){ d.handle(sp, a, crate, arm); }); + Expand_Attrs(expand_state, arm.m_attrs, AttrStage::Post, [&](const Span& sp, const auto& d, const auto& a){ d.handle(sp, a, crate, arm); }); } // Prune deleted arms for(auto it = node.m_arms.begin(); it != node.m_arms.end(); ) { @@ -1114,7 +1192,7 @@ struct CExpandExpr: void visit(::AST::ExprNode_IfLet& node) override { for(auto& cond : node.m_conditions) { if( cond.opt_pat ) { - Expand_Pattern(crate, modstack, this->cur_mod(), *cond.opt_pat, true); + Expand_Pattern(this->expand_state, this->cur_mod(), *cond.opt_pat, true); } this->visit_nodelete(node, cond.value); } @@ -1163,10 +1241,10 @@ struct CExpandExpr: void visit(::AST::ExprNode_ByteString& node) override { } void visit(::AST::ExprNode_Closure& node) override { for(auto& arg : node.m_args) { - Expand_Pattern(crate, modstack, this->cur_mod(), arg.first, false); - Expand_Type(crate, modstack, this->cur_mod(), arg.second); + Expand_Pattern(this->expand_state, this->cur_mod(), arg.first, false); + Expand_Type(this->expand_state, this->cur_mod(), arg.second); } - Expand_Type(crate, modstack, this->cur_mod(), node.m_return); + Expand_Type(this->expand_state, this->cur_mod(), node.m_return); this->visit_nodelete(node, node.m_code); } void visit(::AST::ExprNode_StructLiteral& node) override { @@ -1174,11 +1252,11 @@ struct CExpandExpr: for(auto& val : node.m_values) { Expand_Attrs_CfgAttr(val.attrs); - Expand_Attrs(val.attrs, AttrStage::Pre , [&](const auto& sp, const auto& d, const auto& a){ d.handle(sp, a, crate, val); }); + Expand_Attrs(expand_state, val.attrs, AttrStage::Pre , [&](const Span& sp, const auto& d, const auto& a){ d.handle(sp, a, crate, val); }); if( !val.value ) continue ; this->visit_nodelete(node, val.value); - Expand_Attrs(val.attrs, AttrStage::Post, [&](const auto& sp, const auto& d, const auto& a){ d.handle(sp, a, crate, val); }); + Expand_Attrs(expand_state, val.attrs, AttrStage::Post, [&](const Span& sp, const auto& d, const auto& a){ d.handle(sp, a, crate, val); }); } for(auto it = node.m_values.begin(); it != node.m_values.end(); ) { @@ -1196,7 +1274,7 @@ struct CExpandExpr: this->visit_vector(node.m_values); } void visit(::AST::ExprNode_NamedValue& node) override { - Expand_Path(crate, modstack, this->cur_mod(), node.m_path); + Expand_Path(this->expand_state, this->cur_mod(), node.m_path); } void visit(::AST::ExprNode_Field& node) override { this->visit_nodelete(node, node.m_obj); @@ -1210,11 +1288,11 @@ struct CExpandExpr: } void visit(::AST::ExprNode_Cast& node) override { this->visit_nodelete(node, node.m_value); - Expand_Type(crate, modstack, this->cur_mod(), node.m_type); + Expand_Type(this->expand_state, this->cur_mod(), node.m_type); } void visit(::AST::ExprNode_TypeAnnotation& node) override { this->visit_nodelete(node, node.m_value); - Expand_Type(crate, modstack, this->cur_mod(), node.m_type); + Expand_Type(this->expand_state, this->cur_mod(), node.m_type); } void visit(::AST::ExprNode_BinOp& node) override { this->visit_nodelete(node, node.m_left); @@ -1397,32 +1475,32 @@ struct CExpandExpr: } }; -void Expand_Expr(::AST::Crate& crate, LList modstack, ::AST::ExprNodeP& node) +void Expand_Expr(const ExpandState& es, ::AST::ExprNodeP& node) { TRACE_FUNCTION_F("unique_ptr"); - auto visitor = CExpandExpr(crate, modstack); + CExpandExpr visitor { es }; visitor.visit(node); } -void Expand_Expr(::AST::Crate& crate, LList modstack, ::std::shared_ptr& node) +void Expand_Expr(const ExpandState& es, ::std::shared_ptr& node) { TRACE_FUNCTION_F("shared_ptr"); - auto visitor = CExpandExpr(crate, modstack); + CExpandExpr visitor { es }; node->visit(visitor); if( visitor.replacement ) { node.reset( visitor.replacement.release() ); } } -void Expand_Expr(::AST::Crate& crate, LList modstack, AST::Expr& node) +void Expand_Expr(const ExpandState& es, AST::Expr& node) { TRACE_FUNCTION_F("AST::Expr"); - auto visitor = CExpandExpr(crate, modstack); + CExpandExpr visitor { es }; node.visit_nodes(visitor); if( visitor.replacement ) { node = AST::Expr( mv$(visitor.replacement) ); } } -void Expand_GenericParams(::AST::Crate& crate, LList modstack, ::AST::Module& mod, ::AST::GenericParams& params) +void Expand_GenericParams(const ExpandState& es, ::AST::Module& mod, ::AST::GenericParams& params) { for(auto& param_def : params.m_params) { @@ -1433,10 +1511,10 @@ void Expand_GenericParams(::AST::Crate& crate, LList modstac TU_ARMA(Lifetime, e) { } TU_ARMA(Type, ty_def) { - Expand_Type(crate, modstack, mod, ty_def.get_default()); + Expand_Type(es, mod, ty_def.get_default()); } TU_ARMA(Value, val_def) { - Expand_Type(crate, modstack, mod, val_def.type()); + Expand_Type(es, mod, val_def.type()); } } } @@ -1448,23 +1526,23 @@ void Expand_GenericParams(::AST::Crate& crate, LList modstac (Lifetime, ), (TypeLifetime, - Expand_Type(crate, modstack, mod, be.type); + Expand_Type(es, mod, be.type); ), (IsTrait, - Expand_Type(crate, modstack, mod, be.type); - Expand_Path(crate, modstack, mod, be.trait); + Expand_Type(es, mod, be.type); + Expand_Path(es, mod, be.trait); ), (MaybeTrait, - Expand_Type(crate, modstack, mod, be.type); - Expand_Path(crate, modstack, mod, be.trait); + Expand_Type(es, mod, be.type); + Expand_Path(es, mod, be.trait); ), (NotTrait, - Expand_Type(crate, modstack, mod, be.type); - Expand_Path(crate, modstack, mod, be.trait); + Expand_Type(es, mod, be.type); + Expand_Path(es, mod, be.trait); ), (Equality, - Expand_Type(crate, modstack, mod, be.type); - Expand_Type(crate, modstack, mod, be.replacement); + Expand_Type(es, mod, be.type); + Expand_Type(es, mod, be.replacement); ) ) } @@ -1472,7 +1550,10 @@ void Expand_GenericParams(::AST::Crate& crate, LList modstac void Expand_BareExpr(const ::AST::Crate& crate, const AST::Module& mod, ::AST::ExprNodeP& node) { - Expand_Expr(const_cast< ::AST::Crate&>(crate), LList(nullptr, &mod), node); + ExpandState es { const_cast(crate), LList(nullptr, &mod), ExpandMode::FirstPass }; + Expand_Expr(es, node); + es.mode = ExpandMode::Final; + //Expand_Expr(es, node); } ::AST::ExprNodeP Expand_ParseAndExpand_ExprVal(const ::AST::Crate& crate, const AST::Module& mod, TokenStream& lex) { @@ -1483,39 +1564,39 @@ ::AST::ExprNodeP Expand_ParseAndExpand_ExprVal(const ::AST::Crate& crate, const return n; } -void Expand_Function(::AST::Crate& crate, LList modstack, AST::Module& mod, AST::Function& e) +void Expand_Function(const ExpandState& es, AST::Module& mod, AST::Function& e) { for(size_t i = 0; i < e.args().size(); i ++) { auto& arg = e.args()[i]; - if( !Expand_Attrs_CfgOnly(arg.attrs) ) { + if( !Expand_Attrs_CfgOnly(es, arg.attrs) ) { e.args().erase(e.args().begin() + i); i --; continue ; } - Expand_Pattern(crate, modstack, mod, arg.pat, false); - Expand_Type(crate, modstack, mod, arg.ty); - Expand_Attrs(arg.attrs, AttrStage::Post, [&](const Span& sp, const ExpandDecorator& d, const AST::Attribute& a) { + Expand_Pattern(es, mod, arg.pat, false); + Expand_Type(es, mod, arg.ty); + Expand_Attrs(es, arg.attrs, AttrStage::Post, [&](const Span& sp, const ExpandDecorator& d, const AST::Attribute& a) { TODO(sp, "attributes on function arguments - " << a); }); } - Expand_Type(crate, modstack, mod, e.rettype()); - Expand_Expr(crate, modstack, e.code()); + Expand_Type(es, mod, e.rettype()); + Expand_Expr(es, e.code()); } -void Expand_Impl(::AST::Crate& crate, LList modstack, ::AST::Path modpath, ::AST::Module& mod, ::AST::Impl& impl) +void Expand_Impl(const ExpandState& es, ::AST::Path modpath, ::AST::Module& mod, ::AST::Impl& impl) { TRACE_FUNCTION_F(impl.def()); Expand_Attrs_CfgAttr(impl.def().attrs()); - Expand_Attrs(impl.def().attrs(), AttrStage::Pre, crate, mod, impl.def()); + Expand_Attrs(es, impl.def().attrs(), AttrStage::Pre, mod, impl.def()); if( impl.def().type().is_wildcard() ) { DEBUG("Deleted"); return ; } - Expand_GenericParams(crate, modstack, mod, impl.def().params()); + Expand_GenericParams(es, mod, impl.def().params()); - Expand_Type(crate, modstack, mod, impl.def().type()); - Expand_Path(crate, modstack, mod, impl.def().trait().ent); + Expand_Type(es, mod, impl.def().type()); + Expand_Path(es, mod, impl.def().trait().ent); DEBUG("> Items"); for( unsigned int idx = 0; idx < impl.items().size(); idx ++ ) @@ -1530,7 +1611,7 @@ void Expand_Impl(::AST::Crate& crate, LList modstack, ::AST: auto attrs = mv$(i.attrs); Expand_Attrs_CfgAttr(attrs); - Expand_Attrs(attrs, AttrStage::Pre, crate, impl, i.name, *i.data); + Expand_Attrs(es, attrs, AttrStage::Pre, impl, i.name, *i.data); TU_MATCH_HDRA( (*i.data), {) default: @@ -1544,9 +1625,10 @@ void Expand_Impl(::AST::Crate& crate, LList modstack, ::AST: // Move out of the module to avoid invalidation if a new macro invocation is added auto mi_owned = mv$(e); - auto ttl = Expand_Macro(crate, modstack, mod, mi_owned); + auto ttl = Expand_Macro(es, mod, mi_owned); + ASSERT_BUG(mi_owned.span(), ttl, "TODO: Unexpanded macro?"); - if( ttl.get() ) + if( ttl ) { // Re-parse tt while( ttl->lookahead(0) != TOK_EOF ) @@ -1554,89 +1636,96 @@ void Expand_Impl(::AST::Crate& crate, LList modstack, ::AST: Parse_Impl_Item(*ttl, impl); } // - Any new macro invocations ends up at the end of the list and handled + + *impl.items()[idx].data = AST::Item::make_None({}); + } + else { + // Move back in (using the index, as the old pointr may be invalid) + impl.items()[idx].data->as_MacroInv() = mv$(mi_owned); } - // Move back in (using the index, as the old pointr may be invalid) - impl.items()[idx].data->as_MacroInv() = mv$(mi_owned); } } TU_ARMA(Function, e) { TRACE_FUNCTION_F("fn " << i.name); - Expand_Function(crate, modstack, mod, e); + Expand_Function(es, mod, e); } TU_ARMA(Static, e) { TRACE_FUNCTION_F("static " << i.name); - Expand_Expr(crate, modstack, e.value()); - Expand_Type(crate, modstack, mod, e.type()); + Expand_Expr(es, e.value()); + Expand_Type(es, mod, e.type()); } TU_ARMA(Type, e) { TRACE_FUNCTION_F("type " << i.name); - Expand_Type(crate, modstack, mod, e.type()); + Expand_Type(es, mod, e.type()); } } // Run post-expansion decorators and restore attributes { auto& i = impl.items()[idx]; - Expand_Attrs(attrs, AttrStage::Post, crate, impl, i.name, *i.data); + Expand_Attrs(es, attrs, AttrStage::Post, impl, i.name, *i.data); // TODO: How would this be populated? It got moved out? if( i.attrs.m_items.size() == 0 ) i.attrs = mv$(attrs); } } - Expand_Attrs(impl.def().attrs(), AttrStage::Post, crate, mod, impl.def()); + Expand_Attrs(es, impl.def().attrs(), AttrStage::Post, mod, impl.def()); } -void Expand_ImplDef(::AST::Crate& crate, LList modstack, ::AST::Path modpath, ::AST::Module& mod, ::AST::ImplDef& impl_def) +void Expand_ImplDef(const ExpandState& es, ::AST::Path modpath, ::AST::Module& mod, ::AST::ImplDef& impl_def) { Expand_Attrs_CfgAttr(impl_def.attrs()); - Expand_Attrs(impl_def.attrs(), AttrStage::Pre, crate, mod, impl_def); + Expand_Attrs(es, impl_def.attrs(), AttrStage::Pre, mod, impl_def); if( impl_def.type().is_wildcard() ) { DEBUG("Deleted"); return ; } - Expand_GenericParams(crate, modstack, mod, impl_def.params()); + Expand_GenericParams(es, mod, impl_def.params()); - Expand_Type(crate, modstack, mod, impl_def.type()); - //Expand_Type(crate, modstack, mod, impl_def.trait()); + Expand_Type(es, mod, impl_def.type()); + //Expand_Type(es, mod, impl_def.trait()); - Expand_Attrs(impl_def.attrs(), AttrStage::Post, crate, mod, impl_def); + Expand_Attrs(es, impl_def.attrs(), AttrStage::Post, mod, impl_def); } //void Expand_Function( -void Expand_Mod(::AST::Crate& crate, LList modstack, ::AST::AbsolutePath modpath, ::AST::Module& mod, unsigned int first_item) +void Expand_Mod(const ExpandState& es, ::AST::AbsolutePath modpath, ::AST::Module& mod, unsigned int first_item) { TRACE_FUNCTION_F("modpath = " << modpath << ", first_item=" << first_item); // TODO: Pre-parse all macro_rules invocations into items? - for( const auto& mi: mod.macro_imports_res() ) - DEBUG("- Imports '" << mi.name << "'"); - // Import all macros from parent module. - if( first_item == 0 ) + if( es.mode == ExpandMode::FirstPass ) { for( const auto& mi: mod.macro_imports_res() ) DEBUG("- Imports '" << mi.name << "'"); - if( modstack.m_prev ) + // Import all macros from parent module. + if( first_item == 0 ) { - for(const auto& mac : modstack.m_prev->m_item->m_macro_imports) + for( const auto& mi: mod.macro_imports_res() ) + DEBUG("- Imports '" << mi.name << "'"); + if( es.modstack.m_prev ) { - mod.m_macro_imports.push_back(mac); + for(const auto& mac : es.modstack.m_prev->m_item->m_macro_imports) + { + mod.m_macro_imports.push_back(mac); + } } + for( const auto& mi: mod.m_macro_imports ) + DEBUG("- Imports '" << mi.path << "'"); } - for( const auto& mi: mod.m_macro_imports ) - DEBUG("- Imports '" << mi.path << "'"); - } - // Insert prelude if: Enabled for this module, present for the crate, and this module is not an anon - if( crate.m_prelude_path != AST::Path() ) - { - if( mod.m_insert_prelude && ! mod.is_anon() ) { - DEBUG("> Adding custom prelude " << crate.m_prelude_path); - mod.add_item(Span(), false, "", ::AST::UseItem { Span(), ::make_vec1(::AST::UseItem::Ent { Span(), crate.m_prelude_path, "" }) }, {}); - } - else { - DEBUG("> Not inserting custom prelude (anon or disabled)"); + // Insert prelude if: Enabled for this module, present for the crate, and this module is not an anon + if( es.crate.m_prelude_path != AST::Path() ) + { + if( mod.m_insert_prelude && ! mod.is_anon() ) { + DEBUG("> Adding custom prelude " << es.crate.m_prelude_path); + mod.add_item(Span(), false, "", ::AST::UseItem { Span(), ::make_vec1(::AST::UseItem::Ent { Span(), es.crate.m_prelude_path, "" }) }, {}); + } + else { + DEBUG("> Not inserting custom prelude (anon or disabled)"); + } } } @@ -1668,17 +1757,23 @@ void Expand_Mod(::AST::Crate& crate, LList modstack, ::AST:: } auto attrs = mv$(i.attrs); - Expand_Attrs_CfgAttr(attrs); - Expand_Attrs(attrs, AttrStage::Pre, crate, path, mod, i.data); + if( es.mode == ExpandMode::FirstPass ) + { + Expand_Attrs_CfgAttr(attrs); + Expand_Attrs(es, attrs, AttrStage::Pre, path, mod, i.data); + } // Do modules without moving the definition (so the module path is always valid) if( i.data.is_Module() ) { auto& e = i.data.as_Module(); - LList sub_modstack(&modstack, &e); - Expand_Mod(crate, sub_modstack, path, e); - Expand_Attrs(attrs, AttrStage::Post, crate, path, mod, i.data); - i.attrs = mv$(attrs); + LList sub_modstack(&es.modstack, &e); + ExpandState es_inner(es.crate, sub_modstack, es.mode); + Expand_Mod(es_inner, path, e, 0); + Expand_Attrs(es, attrs, AttrStage::Post, path, mod, i.data); + es.change |= es_inner.change; + es.has_missing |= es_inner.has_missing; + i.attrs = std::move(attrs); continue ; } @@ -1696,35 +1791,43 @@ void Expand_Mod(::AST::Crate& crate, LList modstack, ::AST:: } auto mi_owned = mv$(e); - TRACE_FUNCTION_F("Macro invoke " << mi_owned.path()); + if( !mi_owned.is_expanded() ) + { + TRACE_FUNCTION_F("Macro invoke " << mi_owned.path()); - auto ttl = Expand_Macro(crate, modstack, mod, mi_owned); - assert( mi_owned.path().is_valid() ); + auto ttl = Expand_Macro(es, mod, mi_owned); + if( ttl ) + { + Expand_Attrs(es, attrs, AttrStage::Post, path, mod, dat); - if( ttl.get() ) - { - // Re-parse tt - // TODO: All new items should be placed just after this? - assert(ttl.get()); - DEBUG("-- Parsing as mod items"); - // Move the item list out - auto old_items = std::move(mod.m_items); - // Parse module items - Parse_ModRoot_Items(*ttl, mod); - auto new_item_count = mod.m_items.size(); - // Then insert the newly created items - old_items.insert(old_items.begin() + idx + 1, std::make_move_iterator(mod.m_items.begin()), std::make_move_iterator(mod.m_items.end())); - // and move the (updated) item list back in - mod.m_items = std::move(old_items); - - auto next_non_macro_item = idx + 1 + new_item_count; - macro_recursion_stack.push_back(next_non_macro_item == mod.m_items.size() ? nullptr : &*mod.m_items[next_non_macro_item]); + // Re-parse tt + // TODO: All new items should be placed just after this? + DEBUG("-- Parsing as mod items"); + // Move the item list out + auto old_items = std::move(mod.m_items); + // Parse module items + Parse_ModRoot_Items(*ttl, mod); + auto new_item_count = mod.m_items.size(); + // Then insert the newly created items + old_items.insert(old_items.begin() + idx + 1, std::make_move_iterator(mod.m_items.begin()), std::make_move_iterator(mod.m_items.end())); + // and move the (updated) item list back in + mod.m_items = std::move(old_items); + + auto next_non_macro_item = idx + 1 + new_item_count; + macro_recursion_stack.push_back(next_non_macro_item == mod.m_items.size() ? nullptr : &*mod.m_items[next_non_macro_item]); + + mi_owned.set_expanded(); + } + else { + DEBUG("Deferred macro"); + } } dat.as_MacroInv() = mv$(mi_owned); } TU_ARMA(Macro, e) { ASSERT_BUG(i.span, e, "Null macro - " << i.name); mod.add_macro(i.is_pub, i.name, mv$(e)); + dat = AST::Item::make_None({}); } TU_ARMA(Use, e) { // Determine if the `use` refers to a macro, and import into the current scope @@ -1735,7 +1838,7 @@ void Expand_Mod(::AST::Crate& crate, LList modstack, ::AST:: { DEBUG("Use " << ue.path); - auto m = Resolve_Lookup_Macro(ue.sp, crate, mod.path(), ue.path, /*out_path=*/nullptr); + auto m = Resolve_Lookup_Macro(ue.sp, es.crate, mod.path(), ue.path, /*out_path=*/nullptr); TU_MATCH_HDRA( (m), { ) TU_ARMA(None, e) { // Not found? Ignore. @@ -1767,13 +1870,13 @@ void Expand_Mod(::AST::Crate& crate, LList modstack, ::AST:: } } TU_ARMA(Impl, e) { - Expand_Impl(crate, modstack, modpath, mod, e); + Expand_Impl(es, modpath, mod, e); if( e.def().type().is_wildcard() ) { dat = AST::Item(); } } TU_ARMA(NegImpl, e) { - Expand_ImplDef(crate, modstack, modpath, mod, e); + Expand_ImplDef(es, modpath, mod, e); if( e.type().is_wildcard() ) { dat = AST::Item(); } @@ -1785,9 +1888,9 @@ void Expand_Mod(::AST::Crate& crate, LList modstack, ::AST:: if( e.name != "" ) { // Can't recurse into an `extern crate` - if(crate.m_extern_crates.count(e.name) == 0) + if(es.crate.m_extern_crates.count(e.name) == 0) { - e.name = crate.load_extern_crate( i.span, e.name ); + e.name = es.crate.load_extern_crate( i.span, e.name ); } // Crates imported in root are added to the implicit list if( modpath.nodes.empty() ) @@ -1804,7 +1907,7 @@ void Expand_Mod(::AST::Crate& crate, LList modstack, ::AST:: } TU_ARMA(Struct, e) { - Expand_GenericParams(crate, modstack, mod, e.params()); + Expand_GenericParams(es, mod, e.params()); TU_MATCH_HDRA( (e.m_data), {) TU_ARMA(Unit, sd) { } @@ -1812,9 +1915,9 @@ void Expand_Mod(::AST::Crate& crate, LList modstack, ::AST:: for(auto it = sd.ents.begin(); it != sd.ents.end(); ) { auto& si = *it; Expand_Attrs_CfgAttr(si.m_attrs); - Expand_Attrs(si.m_attrs, AttrStage::Pre, [&](const auto& sp, const auto& d, const auto& a){ d.handle(sp, a, crate, si); }); - Expand_Type(crate, modstack, mod, si.m_type); - Expand_Attrs(si.m_attrs, AttrStage::Post, [&](const auto& sp, const auto& d, const auto& a){ d.handle(sp, a, crate, si); }); + Expand_Attrs(es, si.m_attrs, AttrStage::Pre, [&](const Span& sp, const auto& d, const auto& a){ d.handle(sp, a, es.crate, si); }); + Expand_Type(es, mod, si.m_type); + Expand_Attrs(es, si.m_attrs, AttrStage::Post, [&](const Span& sp, const auto& d, const auto& a){ d.handle(sp, a, es.crate, si); }); if( si.m_name == "" ) it = sd.ents.erase(it); @@ -1826,9 +1929,9 @@ void Expand_Mod(::AST::Crate& crate, LList modstack, ::AST:: for(auto it = sd.ents.begin(); it != sd.ents.end(); ) { auto& si = *it; Expand_Attrs_CfgAttr(si.m_attrs); - Expand_Attrs(si.m_attrs, AttrStage::Pre, [&](const auto& sp, const auto& d, const auto& a){ d.handle(sp, a, crate, si); }); - Expand_Type(crate, modstack, mod, si.m_type); - Expand_Attrs(si.m_attrs, AttrStage::Post, [&](const auto& sp, const auto& d, const auto& a){ d.handle(sp, a, crate, si); }); + Expand_Attrs(es, si.m_attrs, AttrStage::Pre, [&](const Span& sp, const auto& d, const auto& a){ d.handle(sp, a, es.crate, si); }); + Expand_Type(es, mod, si.m_type); + Expand_Attrs(es, si.m_attrs, AttrStage::Post, [&](const Span& sp, const auto& d, const auto& a){ d.handle(sp, a, es.crate, si); }); if( ! si.m_type.is_valid() ) it = sd.ents.erase(it); @@ -1839,35 +1942,35 @@ void Expand_Mod(::AST::Crate& crate, LList modstack, ::AST:: } } TU_ARMA(Enum, e) { - Expand_GenericParams(crate, modstack, mod, e.params()); + Expand_GenericParams(es, mod, e.params()); for(auto& var : e.variants()) { Expand_Attrs_CfgAttr(var.m_attrs); - Expand_Attrs(var.m_attrs, AttrStage::Pre, [&](const auto& sp, const auto& d, const auto& a){ d.handle(sp, a, crate, var); }); - TU_MATCH(::AST::EnumVariantData, (var.m_data), (e), - (Value, - Expand_Expr(crate, modstack, e.m_value); - ), - (Tuple, + Expand_Attrs(es, var.m_attrs, AttrStage::Pre, [&](const Span& sp, const auto& d, const auto& a){ d.handle(sp, a, es.crate, var); }); + TU_MATCH_HDRA( (var.m_data), {) + TU_ARMA(Value, e) { + Expand_Expr(es, e.m_value); + } + TU_ARMA(Tuple, e) { for(auto& ty : e.m_sub_types) { - Expand_Type(crate, modstack, mod, ty); + Expand_Type(es, mod, ty); + } } - ), - (Struct, + TU_ARMA(Struct, e) { for(auto it = e.m_fields.begin(); it != e.m_fields.end(); ) { auto& si = *it; Expand_Attrs_CfgAttr(si.m_attrs); - Expand_Attrs(si.m_attrs, AttrStage::Pre, [&](const auto& sp, const auto& d, const auto& a){ d.handle(sp, a, crate, si); }); - Expand_Type(crate, modstack, mod, si.m_type); - Expand_Attrs(si.m_attrs, AttrStage::Post, [&](const auto& sp, const auto& d, const auto& a){ d.handle(sp, a, crate, si); }); + Expand_Attrs(es, si.m_attrs, AttrStage::Pre, [&](const Span& sp, const auto& d, const auto& a){ d.handle(sp, a, es.crate, si); }); + Expand_Type(es, mod, si.m_type); + Expand_Attrs(es, si.m_attrs, AttrStage::Post, [&](const Span& sp, const auto& d, const auto& a){ d.handle(sp, a, es.crate, si); }); if( si.m_name == "" ) it = e.m_fields.erase(it); else ++it; } - ) - ) - Expand_Attrs(var.m_attrs, AttrStage::Post, [&](const auto& sp, const auto& d, const auto& a){ d.handle(sp, a, crate, var); }); + } + } + Expand_Attrs(es, var.m_attrs, AttrStage::Post, [&](const Span& sp, const auto& d, const auto& a){ d.handle(sp, a, es.crate, var); }); } // Handle cfg on variants (kinda hacky) for(auto it = e.variants().begin(); it != e.variants().end(); ) { @@ -1880,14 +1983,14 @@ void Expand_Mod(::AST::Crate& crate, LList modstack, ::AST:: } } TU_ARMA(Union, e) { - Expand_GenericParams(crate, modstack, mod, e.m_params); + Expand_GenericParams(es, mod, e.m_params); for(auto it = e.m_variants.begin(); it != e.m_variants.end(); ) { auto& si = *it; Expand_Attrs_CfgAttr(si.m_attrs); - Expand_Attrs(si.m_attrs, AttrStage::Pre, [&](const auto& sp, const auto& d, const auto& a){ d.handle(sp, a, crate, si); }); - Expand_Type(crate, modstack, mod, si.m_type); - Expand_Attrs(si.m_attrs, AttrStage::Post, [&](const auto& sp, const auto& d, const auto& a){ d.handle(sp, a, crate, si); }); + Expand_Attrs(es, si.m_attrs, AttrStage::Pre, [&](const Span& sp, const auto& d, const auto& a){ d.handle(sp, a, es.crate, si); }); + Expand_Type(es, mod, si.m_type); + Expand_Attrs(es, si.m_attrs, AttrStage::Post, [&](const Span& sp, const auto& d, const auto& a){ d.handle(sp, a, es.crate, si); }); if( si.m_name == "" ) it = e.m_variants.erase(it); @@ -1896,9 +1999,9 @@ void Expand_Mod(::AST::Crate& crate, LList modstack, ::AST:: } } TU_ARMA(Trait, e) { - Expand_GenericParams(crate, modstack, mod, e.params()); + Expand_GenericParams(es, mod, e.params()); for(auto& p : e.supertraits()) - Expand_Path(crate, modstack, mod, *p.ent.path); + Expand_Path(es, mod, *p.ent.path); auto& trait_items = e.items(); for(size_t idx = 0; idx < trait_items.size(); idx ++) { @@ -1907,7 +2010,7 @@ void Expand_Mod(::AST::Crate& crate, LList modstack, ::AST:: auto attrs = mv$(ti.attrs); auto ti_path = path + ti.name; Expand_Attrs_CfgAttr(attrs); - Expand_Attrs(attrs, AttrStage::Pre, crate, ti_path, e, ti.data); + Expand_Attrs(es, attrs, AttrStage::Pre, ti_path, e, ti.data); TU_MATCH_HDRA( (ti.data), {) default: @@ -1920,7 +2023,8 @@ void Expand_Mod(::AST::Crate& crate, LList modstack, ::AST:: // Move out of the module to avoid invalidation if a new macro invocation is added auto mi_owned = mv$(e); - auto ttl = Expand_Macro(crate, modstack, mod, mi_owned); + auto ttl = Expand_Macro(es, mod, mi_owned); + ASSERT_BUG(mi_owned.span(), ttl, "TODO: Unexpanded macro"); if( ttl.get() ) { @@ -1933,49 +2037,53 @@ void Expand_Mod(::AST::Crate& crate, LList modstack, ::AST:: insert_pos ++; } // - Any new macro invocations ends up at the end of the list and handled + trait_items[idx].data = AST::Item::make_None({}); + } + else + { + // Move back in (using the index, as the old pointer may be invalid) + trait_items[idx].data.as_MacroInv() = mv$(mi_owned); } - // Move back in (using the index, as the old pointer may be invalid) - trait_items[idx].data.as_MacroInv() = mv$(mi_owned); } } TU_ARMA(Function, e) { - Expand_Function(crate, modstack, mod, e); + Expand_Function(es, mod, e); } TU_ARMA(Static, e) { - Expand_Expr(crate, modstack, e.value()); - Expand_Type(crate, modstack, mod, e.type()); + Expand_Expr(es, e.value()); + Expand_Type(es, mod, e.type()); } TU_ARMA(Type, e) { - Expand_Type(crate, modstack, mod, e.type()); + Expand_Type(es, mod, e.type()); } } { auto& ti = trait_items[idx]; - Expand_Attrs(attrs, AttrStage::Post, crate, ti_path, e, ti.data); + Expand_Attrs(es, attrs, AttrStage::Post, ti_path, e, ti.data); if( ti.attrs.m_items.size() == 0 ) ti.attrs = mv$(attrs); } } } TU_ARMA(Type, e) { - Expand_Type(crate, modstack, mod, e.type()); + Expand_Type(es, mod, e.type()); } TU_ARMA(Function, e) { - Expand_Function(crate, modstack, mod, e); + Expand_Function(es, mod, e); } TU_ARMA(Static, e) { - Expand_Expr(crate, modstack, e.value()); - Expand_Type(crate, modstack, mod, e.type()); + Expand_Expr(es, e.value()); + Expand_Type(es, mod, e.type()); } TU_ARMA(TraitAlias, e) { for(auto& p : e.traits) - Expand_Path(crate, modstack, mod, *p.ent.path); + Expand_Path(es, mod, *p.ent.path); } } - Expand_Attrs(attrs, AttrStage::Post, crate, path, mod, dat); + Expand_Attrs(es, attrs, AttrStage::Post, path, mod, dat); { @@ -2104,7 +2212,9 @@ void Expand_Mod_Early(::AST::Crate& crate, ::AST::Module& mod, std::vectordata = AST::Item::make_None({}); + } + else + { } mod.m_items[idx]->data.as_MacroInv() = mv$(mi_owned); } @@ -2142,12 +2256,12 @@ void Expand(::AST::Crate& crate) DEBUG("Macro: " << e.first); } - auto modstack = LList(nullptr, &crate.m_root_module); + ExpandState es { crate, LList(nullptr, &crate.m_root_module), ExpandMode::FirstPass }; // 1. Crate attributes Expand_Attrs_CfgAttr(crate.m_attrs); - Expand_Attrs(crate.m_attrs, AttrStage::Pre, [&](const auto& sp, const auto& d, const auto& a){ d.handle(sp, a, crate); }); + Expand_Attrs(es, crate.m_attrs, AttrStage::Pre, [&](const Span& sp, const auto& d, const auto& a){ d.handle(sp, a, crate); }); // TODO: Crate name and type @@ -2210,9 +2324,26 @@ void Expand(::AST::Crate& crate) } // 3. Module tree - Expand_Mod(crate, modstack, ::AST::AbsolutePath(), crate.m_root_module); + // Loop until no more expansions happen + // - Combine this with allowing macros to fail to expand, to be caught with a final pass + Expand_Mod(es, ::AST::AbsolutePath(), crate.m_root_module); + DEBUG("(first) es.change = " << es.change << ", es.has_missing=" << es.has_missing << " (" << &es << ")"); + if( es.has_missing ) + { + for(size_t n_iters = 0; n_iters < 5 && es.change && es.has_missing; n_iters ++) + { + es.mode = ExpandMode::Iterate; + es.change = false; + es.has_missing = false; + Expand_Mod(es, ::AST::AbsolutePath(), crate.m_root_module); + DEBUG("?(Iter) es.change = " << es.change << ", es.has_missing=" << es.has_missing); + } + ASSERT_BUG(Span(), !es.has_missing, "Expand too too many attempts"); + } + es.mode = ExpandMode::Final; + Expand_Mod(es, ::AST::AbsolutePath(), crate.m_root_module); - //Expand_Attrs(crate.m_attrs, AttrStage::Post, [&](const auto& sp, const auto& d, const auto& a){ d.handle(sp, a, crate); }); + //Expand_Attrs(es, crate.m_attrs, AttrStage::Post, [&](const Span& sp, const auto& d, const auto& a){ d.handle(sp, a, crate); }); // Post-process Expand_Mod_IndexAnon(crate, crate.m_root_module); diff --git a/src/expand/std_prelude.cpp b/src/expand/std_prelude.cpp index 9776f9a8b..cdf8d85f2 100644 --- a/src/expand/std_prelude.cpp +++ b/src/expand/std_prelude.cpp @@ -62,7 +62,7 @@ class Decorator_PreludeImport: public ExpandDecorator { public: - AttrStage stage() const override { return AttrStage::Post; } + AttrStage stage() const override { return AttrStage::Pre; } void handle(const Span& sp, const AST::Attribute& mi, ::AST::Crate& crate, const AST::AbsolutePath& path, AST::Module& mod, slice attrs, AST::Item&i) const override { if( const auto* e = i.opt_Use() ) { diff --git a/src/include/synext_decorator.hpp b/src/include/synext_decorator.hpp index e1bd7de27..4a7e2b732 100644 --- a/src/include/synext_decorator.hpp +++ b/src/include/synext_decorator.hpp @@ -49,6 +49,7 @@ class ExpandDecorator public: virtual ~ExpandDecorator() = default; virtual AttrStage stage() const = 0; + virtual bool run_during_iter() const { return false; } virtual void handle(const Span& sp, const AST::Attribute& mi, AST::Crate& crate) const { unexpected(sp, mi, "crate"); } virtual void handle(const Span& sp, const AST::Attribute& mi, AST::Crate& crate, const AST::AbsolutePath& path, AST::Module& mod, slice attrs, AST::Item&i) const { unexpected(sp, mi, "item"); }