diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ast/ast.hpp | 4 | ||||
-rw-r--r-- | src/expand/macro_rules.cpp | 50 | ||||
-rw-r--r-- | src/expand/macro_rules.hpp | 15 | ||||
-rw-r--r-- | src/expand/mod.cpp | 85 | ||||
-rw-r--r-- | src/macros.cpp | 28 | ||||
-rw-r--r-- | src/macros.hpp | 1 | ||||
-rw-r--r-- | src/parse/common.hpp | 1 |
7 files changed, 152 insertions, 32 deletions
diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp index ea518eab..93652a9a 100644 --- a/src/ast/ast.hpp +++ b/src/ast/ast.hpp @@ -431,7 +431,9 @@ public: void add_macro(bool is_exported, ::std::string name, MacroRules macro) {
m_macros.push_back( Named<MacroRules>( move(name), move(macro), is_exported ) );
}
- void add_macro_import(const Crate& crate, ::std::string mod, ::std::string name);
+ void add_macro_import(::std::string name, const MacroRules& mr) {
+ m_macro_import_res.push_back( NamedNS<const MacroRules*>( mv$(name), &mr, false ) );
+ }
void add_macro_invocation(MacroInvocation item) {
m_macro_invocations.push_back( mv$(item) );
}
diff --git a/src/expand/macro_rules.cpp b/src/expand/macro_rules.cpp index d860aaa3..4ef39c01 100644 --- a/src/expand/macro_rules.cpp +++ b/src/expand/macro_rules.cpp @@ -3,6 +3,7 @@ #include "../ast/expr.hpp" #include "../ast/ast.hpp" #include "../parse/common.hpp" +#include "macro_rules.hpp" class CMacroRulesExpander: public ExpandProcMacro @@ -18,11 +19,60 @@ class CMacroRulesExpander: TTStream lex(tt); auto mac = Parse_MacroRules(lex); // TODO: Place into current module using `ident` as the name + mod.add_macro( false, ident, mac ); return AST::Expr(); } }; +class CMacroUseHandler: + public ExpandDecorator +{ + AttrStage stage() const override { return AttrStage::EarlyPost; } + + void handle(const AST::MetaItem& mi, AST::Crate& crate, const AST::Path& path, AST::Module& mod, AST::Item& i) const override + { + if( !i.is_Module() ) + throw ::std::runtime_error("ERROR: Use of #[macro_use] on non-module"); + + const auto& submod = i.as_Module().e; + + if( mi.has_sub_items() ) + { + } + else + { + for( const auto& mr : submod.macros() ) + { + mod.add_macro_import( mr.name, mr.data ); + } + } + + throw ::std::runtime_error("TODO: #[macro_use]"); + } + +}; + +AST::Expr Macro_Invoke(const char* name, const MacroRules& rules, const TokenTree& tt, AST::Module& mod, MacroPosition position) +{ + auto out_tt = Macro_InvokeRules(name, rules, tt); + TokenStream& lex = *out_tt; + // TODO: Expand out_tt + switch(position) + { + case MacroPosition::Item: { + LList<AST::Module*> l(nullptr, &mod); + Parse_ModRoot_Items(lex, mod, l, false, "-"); + return AST::Expr(); + } + default: + throw ::std::runtime_error("TODO: Macro in non-item position"); + //case MacroPosition::Stmt: { + // break; } + } +} + STATIC_MACRO("macro_rules", CMacroRulesExpander); +STATIC_DECORATOR("macro_use", CMacroUseHandler); diff --git a/src/expand/macro_rules.hpp b/src/expand/macro_rules.hpp new file mode 100644 index 00000000..81e9b18a --- /dev/null +++ b/src/expand/macro_rules.hpp @@ -0,0 +1,15 @@ +/** + * Binding header for the macro_rules syntax extension + */ +#pragma once + +#include <synext.hpp> +#include "../macros.hpp" + +namespace AST { + class Expr; + class Module; +} +class TokenTree; + +extern AST::Expr Macro_Invoke(const char* name, const MacroRules& rules, const TokenTree& tt, AST::Module& mod, MacroPosition position); diff --git a/src/expand/mod.cpp b/src/expand/mod.cpp index 368360bd..cb7667f8 100644 --- a/src/expand/mod.cpp +++ b/src/expand/mod.cpp @@ -5,6 +5,7 @@ #include <main_bindings.hpp> #include <synext.hpp> #include <map> +#include "macro_rules.hpp" ::std::map< ::std::string, ::std::unique_ptr<ExpandDecorator> > g_decorators; ::std::map< ::std::string, ::std::unique_ptr<ExpandProcMacro> > g_macros; @@ -21,41 +22,93 @@ void Expand_Attrs(const ::AST::MetaItems& attrs, AttrStage stage, ::AST::Crate& for( auto& a : attrs.m_items ) { for( auto& d : g_decorators ) { - if( d.first == a.name() && d.second->stage() == stage ) { - d.second->handle(a, crate, path, mod, item); + if( d.first == a.name() ) { + DEBUG("#[" << d.first << "]"); + if( d.second->stage() == stage ) { + d.second->handle(a, crate, path, mod, item); + } } } } } +AST::Expr Expand_Macro(bool is_early, ::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; + } + } + + + for( const auto& mr : mod.macros() ) + { + 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 : mod.macro_imports_res() ) + { + 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 ) { + // TODO: Error - Unknown macro name + throw ::std::runtime_error( FMT("Unknown macro '" << mi.name() << "'") ); + } + + // Leave valid and return an empty expression + return AST::Expr(); +} + void Expand_Mod(bool is_early, ::AST::Crate& crate, ::AST::Path modpath, ::AST::Module& mod) { TRACE_FUNCTION_F("is_early = " << is_early << ", modpath = " << modpath); // 1. Macros first - for( auto& mi : mod.macro_invs() ) + //for( auto& mi : mod.macro_invs() ) + for(unsigned int i = 0; i < mod.macro_invs().size(); i ++ ) { - if( mi.name() == "" ) - continue ; - for( auto& m : g_macros ) { - if( mi.name() == m.first && m.second->expand_early() == is_early ) { - m.second->expand(mi.input_ident(), mi.input_tt(), mod, MacroPosition::Item); - - mi.clear(); - break; + auto& mi = mod.macro_invs()[i]; + if( mi.name() != "" ) + { + // Move out of the module to avoid invalidation if a new macro invocation is added + auto mi_owned = mv$(mi); + + auto rv = Expand_Macro(is_early, mod, mi_owned, MacroPosition::Item); + if( rv.is_valid() ) + ; // TODO: ERROR - macro yeilded an expression in item position + + if( mi_owned.name() != "" ) + { + mod.macro_invs()[i] = mv$(mi_owned); } } - - if( ! is_early && mi.name() != "" ) { - // TODO: Error - Unknown macro name - throw ::std::runtime_error( FMT("Unknown macro '" << mi.name() << "'") ); - } } // 2. General items DEBUG("Items"); for( auto& i : mod.items() ) { + DEBUG("- " << i.name); ::AST::Path path = modpath + i.name; Expand_Attrs(i.data.attrs, (is_early ? AttrStage::EarlyPre : AttrStage::LatePre), crate, path, mod, i.data); diff --git a/src/macros.cpp b/src/macros.cpp index d7d30f4e..5a45156e 100644 --- a/src/macros.cpp +++ b/src/macros.cpp @@ -108,7 +108,6 @@ class MacroExpander: public:
private:
- const TokenStream& m_olex;
const ::std::string m_crate_name;
const ::std::vector<MacroRuleEnt>& m_root_contents;
const ParameterMappings m_mappings;
@@ -131,7 +130,6 @@ private: public:
MacroExpander(const MacroExpander& x):
- m_olex(x.m_olex),
m_crate_name(x.m_crate_name),
m_root_contents(x.m_root_contents),
m_mappings(x.m_mappings),
@@ -140,8 +138,7 @@ public: {
prep_counts();
}
- MacroExpander(const TokenStream& olex, const ::std::vector<MacroRuleEnt>& contents, ParameterMappings mappings, ::std::string crate_name):
- m_olex(olex),
+ MacroExpander(const ::std::vector<MacroRuleEnt>& contents, ParameterMappings mappings, ::std::string crate_name):
m_crate_name(crate_name),
m_root_contents(contents),
m_mappings(mappings),
@@ -354,7 +351,7 @@ bool Macro_HandlePattern(TTStream& lex, const MacroPatEnt& pat, unsigned int lay return true;
}
-::std::unique_ptr<TokenStream> Macro_InvokeInt(const TokenStream& olex, const char *name, const MacroRules& rules, TokenTree input)
+::std::unique_ptr<TokenStream> Macro_InvokeRules(const char *name, const MacroRules& rules, TokenTree input)
{
TRACE_FUNCTION;
@@ -396,7 +393,7 @@ bool Macro_HandlePattern(TTStream& lex, const MacroPatEnt& pat, unsigned int lay }
DEBUG("TODO: Obtain crate name correctly");
- TokenStream* ret_ptr = new MacroExpander(olex, rule.m_contents, bound_tts, "");
+ TokenStream* ret_ptr = new MacroExpander(rule.m_contents, bound_tts, "");
// HACK! Disable nested macro expansion
//ret_ptr->parse_state().no_expand_macros = true;
@@ -409,9 +406,10 @@ bool Macro_HandlePattern(TTStream& lex, const MacroPatEnt& pat, unsigned int lay i ++;
}
DEBUG("");
- throw ParseError::Todo(olex, "Error when macro fails to match");
+ throw ParseError::Todo(/*source_span, */"Error when macro fails to match");
}
+#if 0
::std::unique_ptr<TokenStream> Macro_Invoke(const TokenStream& olex, const ::std::string& name, TokenTree input)
{
DEBUG("Invoke " << name << " from " << olex.getPosition());
@@ -445,7 +443,7 @@ bool Macro_HandlePattern(TTStream& lex, const MacroPatEnt& pat, unsigned int lay t_macro_regs::iterator macro_reg = g_macro_registrations.find(name);
if( macro_reg != g_macro_registrations.end() )
{
- return Macro_InvokeInt(olex, macro_reg->first.c_str(), macro_reg->second, input);
+ return Macro_InvokeRules(olex.getPosition(), macro_reg->first.c_str(), macro_reg->second, input);
}
// Search import list
@@ -459,7 +457,7 @@ bool Macro_HandlePattern(TTStream& lex, const MacroPatEnt& pat, unsigned int lay DEBUG("- [local] " << m.name);
if( m.name == name )
{
- return Macro_InvokeInt(olex, m.name.c_str(), m.data, input);
+ return Macro_InvokeRules(olex.getPosition(), m.name.c_str(), m.data, input);
}
}
@@ -468,18 +466,18 @@ bool Macro_HandlePattern(TTStream& lex, const MacroPatEnt& pat, unsigned int lay DEBUG("- [imp]" << mi.name);
if( mi.name == name )
{
- return Macro_InvokeInt(olex, mi.name.c_str(), *mi.data, input);
+ return Macro_InvokeRules(olex.getPosition(), mi.name.c_str(), *mi.data, input);
}
}
}
throw ParseError::Generic(olex, FMT("Macro '" << name << "' was not found") );
}
+#endif
Position MacroExpander::getPosition() const
{
- DEBUG("olex.getPosition() = " << m_olex.getPosition());
return Position(FMT("Macro:" << ""), 0, m_offsets[0].read_pos);
}
Token MacroExpander::realGetToken()
@@ -722,10 +720,10 @@ void Macro_Invoke_Concat_Once(::std::string& s, TokenStream& lex, enum eTokenTyp {
// Special case, expand both concat! and stringify! internally
// TODO: Invoke
- auto tt = Parse_TT(lex, false);
- auto slex = Macro_Invoke(lex, tok.str(), tt);
- Macro_Invoke_Concat_Once(s, (*slex), exp);
- GET_CHECK_TOK(tok, (*slex), TOK_EOF);
+ //auto tt = Parse_TT(lex, false);
+ //auto slex = Macro_Invoke(lex, tok.str(), tt);
+ //Macro_Invoke_Concat_Once(s, (*slex), exp);
+ //GET_CHECK_TOK(tok, (*slex), TOK_EOF);
}
else if( tok.type() == exp )
{
diff --git a/src/macros.hpp b/src/macros.hpp index d7efec1a..14b4add2 100644 --- a/src/macros.hpp +++ b/src/macros.hpp @@ -149,6 +149,7 @@ typedef ::std::vector<MacroRule> MacroRules; extern const LList<AST::Module*>* Macro_GetModule();
extern void Macro_SetModule(const LList<AST::Module*>& mod);
+extern ::std::unique_ptr<TokenStream> Macro_InvokeRules(const char *name, const MacroRules& rules, TokenTree input);
extern ::std::unique_ptr<TokenStream> Macro_Invoke(const TokenStream& lex, const ::std::string& name, TokenTree input);
#endif // MACROS_HPP_INCLUDED
diff --git a/src/parse/common.hpp b/src/parse/common.hpp index def67ef4..4b6ceb54 100644 --- a/src/parse/common.hpp +++ b/src/parse/common.hpp @@ -52,6 +52,7 @@ extern MacroRules Parse_MacroRules(TokenStream& lex); extern void Parse_ExternCrate(TokenStream& lex, AST::Module& mod, AST::MetaItems meta_items);
extern void Parse_Mod_Item(TokenStream& lex, LList<AST::Module*>& modstack, bool file_controls_dir, const ::std::string& file_path, AST::Module& mod, bool is_public, AST::MetaItems meta_items);
+extern void Parse_ModRoot_Items(TokenStream& lex, AST::Module& mod, LList<AST::Module*>& modstack, bool file_controls_dir, const ::std::string& path);
extern AST::Function Parse_FunctionDef(TokenStream& lex, ::std::string abi, AST::MetaItems attrs, bool allow_self, bool can_be_prototype);
|