diff options
-rw-r--r-- | src/ident.cpp | 15 | ||||
-rw-r--r-- | src/include/ident.hpp | 19 | ||||
-rw-r--r-- | src/macro_rules/eval.cpp | 8 | ||||
-rw-r--r-- | src/macro_rules/macro_rules.hpp | 2 | ||||
-rw-r--r-- | src/macro_rules/parse.cpp | 3 |
5 files changed, 34 insertions, 13 deletions
diff --git a/src/ident.cpp b/src/ident.cpp index 8543d6fa..45c96f2e 100644 --- a/src/ident.cpp +++ b/src/ident.cpp @@ -15,8 +15,17 @@ unsigned int Ident::Hygiene::g_next_scope = 0; bool Ident::Hygiene::is_visible(const Hygiene& src) const { // HACK: Disable hygiene for now - return true; - //return this->scope_index == src.scope_index; + //return true; + + if( this->contexts.size() == 0 ) { + return src.contexts.size() == 0; + } + + auto des = this->contexts.back(); + for(const auto& c : src.contexts) + if( des == c ) + return true; + return false; } ::std::ostream& operator<<(::std::ostream& os, const Ident& x) { @@ -25,7 +34,7 @@ bool Ident::Hygiene::is_visible(const Hygiene& src) const } ::std::ostream& operator<<(::std::ostream& os, const Ident::Hygiene& x) { - os << "{" << x.scope_index << "}"; + os << "{" << x.contexts << "}"; return os; } diff --git a/src/include/ident.hpp b/src/include/ident.hpp index cff918ca..1122a68b 100644 --- a/src/include/ident.hpp +++ b/src/include/ident.hpp @@ -14,20 +14,29 @@ struct Ident class Hygiene { static unsigned g_next_scope; - unsigned int scope_index; + + ::std::vector<unsigned int> contexts; Hygiene(unsigned int index): - scope_index(index) + contexts({index}) {} public: Hygiene(): - scope_index(0) + contexts({}) {} static Hygiene new_scope() { return Hygiene(++g_next_scope); } + static Hygiene new_scope_chained(const Hygiene& parent) + { + Hygiene rv; + rv.contexts.reserve( parent.contexts.size() + 1 ); + rv.contexts.insert( rv.contexts.begin(), parent.contexts.begin(), parent.contexts.end() ); + rv.contexts.push_back( ++g_next_scope ); + return rv; + } Hygiene(Hygiene&& x) = default; Hygiene(const Hygiene& x) = default; @@ -36,8 +45,8 @@ struct Ident // Returns true if an ident with hygine `souce` can see an ident with this hygine bool is_visible(const Hygiene& source) const; - bool operator==(const Hygiene& x) const { return scope_index == x.scope_index; } - bool operator!=(const Hygiene& x) const { return scope_index != x.scope_index; } + //bool operator==(const Hygiene& x) const { return scope_index == x.scope_index; } + //bool operator!=(const Hygiene& x) const { return scope_index != x.scope_index; } friend ::std::ostream& operator<<(::std::ostream& os, const Hygiene& v); }; diff --git a/src/macro_rules/eval.cpp b/src/macro_rules/eval.cpp index 3a55f500..5f2ac6b0 100644 --- a/src/macro_rules/eval.cpp +++ b/src/macro_rules/eval.cpp @@ -571,12 +571,12 @@ class MacroExpander: public: MacroExpander(const MacroExpander& x) = delete; - MacroExpander(const ::std::string& macro_name, const ::std::vector<MacroExpansionEnt>& contents, ParameterMappings mappings, ::std::string crate_name): + MacroExpander(const ::std::string& macro_name, const Ident::Hygiene& parent_hygiene, const ::std::vector<MacroExpansionEnt>& contents, ParameterMappings mappings, ::std::string crate_name): m_macro_filename( FMT("Macro:" << macro_name) ), m_crate_name( mv$(crate_name) ), m_mappings( mv$(mappings) ), m_state( contents, m_mappings ), - m_hygiene( Ident::Hygiene::new_scope() ) + m_hygiene( Ident::Hygiene::new_scope_chained(parent_hygiene) ) { } @@ -708,7 +708,7 @@ void Macro_HandlePatternCap(TokenStream& lex, unsigned int index, MacroPatEnt::T ; else CHECK_TOK(tok, TOK_IDENT); - bound_tts.insert( index, iterations, InterpolatedFragment( TokenTree(tok) ) ); + bound_tts.insert( index, iterations, InterpolatedFragment( TokenTree(lex.getHygiene(), tok) ) ); break; } } @@ -786,7 +786,7 @@ bool Macro_HandlePattern(TokenStream& lex, const MacroPatEnt& pat, ::std::vector // Run through the expansion counting the number of times each fragment is used Macro_InvokeRules_CountSubstUses(bound_tts, rule.m_contents); - TokenStream* ret_ptr = new MacroExpander(name, rule.m_contents, mv$(bound_tts), rules.m_source_crate); + TokenStream* ret_ptr = new MacroExpander(name, rules.m_hygiene, rule.m_contents, mv$(bound_tts), rules.m_source_crate); return ::std::unique_ptr<TokenStream>( ret_ptr ); } diff --git a/src/macro_rules/macro_rules.hpp b/src/macro_rules/macro_rules.hpp index 30e3e45b..337a4707 100644 --- a/src/macro_rules/macro_rules.hpp +++ b/src/macro_rules/macro_rules.hpp @@ -142,6 +142,8 @@ public: /// - Populated on deserialise if not already set
::std::string m_source_crate;
+ Ident::Hygiene m_hygiene;
+
/// Expansion rules
::std::vector<MacroRulesArm> m_rules;
diff --git a/src/macro_rules/parse.cpp b/src/macro_rules/parse.cpp index c7a6ef89..4da91a90 100644 --- a/src/macro_rules/parse.cpp +++ b/src/macro_rules/parse.cpp @@ -473,7 +473,8 @@ MacroRulesPtr Parse_MacroRules(TokenStream& lex) rule_arms.push_back( mv$(arm) ); } - auto rv = new MacroRules(); + auto rv = new MacroRules( ); + rv->m_hygiene = lex.getHygiene(); rv->m_rules = mv$(rule_arms); return MacroRulesPtr(rv); |