summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ast/ast.hpp4
-rw-r--r--src/expand/macro_rules.cpp50
-rw-r--r--src/expand/macro_rules.hpp15
-rw-r--r--src/expand/mod.cpp85
-rw-r--r--src/macros.cpp28
-rw-r--r--src/macros.hpp1
-rw-r--r--src/parse/common.hpp1
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);