/* */ #include #include #include #include #include #include "macro_rules.hpp" ::std::map< ::std::string, ::std::unique_ptr > g_decorators; ::std::map< ::std::string, ::std::unique_ptr > g_macros; void Register_Synext_Decorator(::std::string name, ::std::unique_ptr handler) { g_decorators[name] = mv$(handler); } void Register_Synext_Macro(::std::string name, ::std::unique_ptr handler) { g_macros[name] = mv$(handler); } void Expand_Attrs(const ::AST::MetaItems& attrs, AttrStage stage, ::AST::Crate& crate, const ::AST::Path& path, ::AST::Module& mod, ::AST::Item& item) { for( auto& a : attrs.m_items ) { for( auto& d : g_decorators ) { if( d.first == a.name() ) { DEBUG("#[" << d.first << "] " << (int)d.second->stage() << "-" << (int)stage); if( d.second->stage() == stage ) { d.second->handle(a, crate, path, mod, item); } } } } } AST::Expr Expand_Macro(bool is_early, LList modstack, ::AST::Module& mod, ::AST::MacroInvocation& mi, MacroPosition pos) { for( const auto& m : g_macros ) { if( mi.name() == m.first && m.second->expand_early() == is_early ) { auto e = m.second->expand(mi.input_ident(), mi.input_tt(), mod, MacroPosition::Item); mi.clear(); return e; } } // Iterate up the module tree, using the first located macro for(const auto* ll = &modstack; ll; ll = ll->m_prev) { const auto& mac_mod = *ll->m_item; for( const auto& mr : mac_mod.macros() ) { //DEBUG("- " << mr.name); if( mr.name == mi.name() ) { if( mi.input_ident() != "" ) ; // TODO: ERROR - macro_rules! macros can't take an ident auto e = Macro_Invoke(mr.name.c_str(), mr.data, mi.input_tt(), mod, MacroPosition::Item); mi.clear(); return e; } } for( const auto& mri : mac_mod.macro_imports_res() ) { //DEBUG("- " << mri.name); if( mri.name == mi.name() ) { if( mi.input_ident() != "" ) ; // TODO: ERROR - macro_rules! macros can't take an ident auto e = Macro_Invoke(mi.name().c_str(), *mri.data, mi.input_tt(), mod, MacroPosition::Item); mi.clear(); return e; } } } if( ! is_early ) { // Error - Unknown macro name ERROR(mi.span(), E0000, "Unknown macro '" << mi.name() << "'"); } // Leave valid and return an empty expression return AST::Expr(); } void Expand_Mod(bool is_early, ::AST::Crate& crate, LList modstack, ::AST::Path modpath, ::AST::Module& mod) { TRACE_FUNCTION_F("is_early = " << is_early << ", modpath = " << modpath); for( const auto& mi: mod.macro_imports_res() ) DEBUG("- Imports '" << mi.name << "'"); // 1. Macros first //for( auto& mi : mod.macro_invs() ) for(unsigned int i = 0; i < mod.macro_invs().size(); i ++ ) { auto& mi = mod.macro_invs()[i]; DEBUG("> Macro invoke '"< sub_modstack(&modstack, &e.e); Expand_Mod(is_early, crate, sub_modstack, path, e.e); ), (Crate, // Skip, no recursion ), (Struct, // TODO: Struct items ), (Enum, ), (Trait, ), (Type, // TODO: Do type aliases require recursion? ), (Function, // TODO: ), (Static, // TODO: ) ) Expand_Attrs(i.data.attrs, (is_early ? AttrStage::EarlyPost : AttrStage::LatePost), crate, path, mod, i.data); } for( const auto& mi: mod.macro_imports_res() ) DEBUG("- Imports '" << mi.name << "'"); // 3. Post-recurse macros (everything else) } void Expand(::AST::Crate& crate) { // 1. Crate attributes for( auto& a : crate.m_attrs.m_items ) { for( auto& d : g_decorators ) { if( d.first == a.name() && d.second->stage() == AttrStage::EarlyPre ) { d.second->handle(a, crate); } } } // 2. Module attributes for( auto& a : crate.m_attrs.m_items ) { for( auto& d : g_decorators ) { if( d.first == a.name() && d.second->stage() == AttrStage::EarlyPre ) { //d.second->handle(a, crate, ::AST::Path(), crate.m_root_module, crate.m_root_module); } } } // 3. Module tree Expand_Mod(true , crate, LList(nullptr, &crate.m_root_module), ::AST::Path(), crate.m_root_module); Expand_Mod(false, crate, LList(nullptr, &crate.m_root_module), ::AST::Path(), crate.m_root_module); // Post-process #if 0 for( auto& a : crate.m_attrs.m_items ) { for( auto& d : g_decorators ) { if( d.first == a.name() && d.second->expand_before_macros() == false ) { //d.second->handle(a, crate, ::AST::Path(), crate.m_root_module, crate.m_root_module); } } } for( auto& a : crate.m_attrs.m_items ) { for( auto& d : g_decorators ) { if( d.first == a.name() && d.second->expand_before_macros() == false ) { d.second->handle(a, crate); } } } #endif }