diff options
author | John Hodge <tpg@ucc.asn.au> | 2019-05-05 20:12:58 +0800 |
---|---|---|
committer | John Hodge <tpg@ucc.asn.au> | 2019-05-05 20:12:58 +0800 |
commit | 7a5cd835703fdfac0634b975392f915e0230c2a7 (patch) | |
tree | cecda0ef233d853e9058649b49d373a8f0a5f299 | |
parent | 6cc802dfbd44a6f1f76cc5ae76227f1f54cf9f75 (diff) | |
download | mrust-7a5cd835703fdfac0634b975392f915e0230c2a7.tar.gz |
parse/expand/resolve - `macro` macros use their own module as the resolve root
-rw-r--r-- | src/ast/ast.cpp | 3 | ||||
-rw-r--r-- | src/ast/ast.hpp | 1 | ||||
-rw-r--r-- | src/expand/mod.cpp | 3 | ||||
-rw-r--r-- | src/hir/from_ast.cpp | 2 | ||||
-rw-r--r-- | src/ident.cpp | 5 | ||||
-rw-r--r-- | src/include/ident.hpp | 20 | ||||
-rw-r--r-- | src/macro_rules/eval.cpp | 1 | ||||
-rw-r--r-- | src/macro_rules/macro_rules.hpp | 4 | ||||
-rw-r--r-- | src/macro_rules/parse.cpp | 20 | ||||
-rw-r--r-- | src/parse/paths.cpp | 1 | ||||
-rw-r--r-- | src/parse/root.cpp | 43 | ||||
-rw-r--r-- | src/resolve/absolute.cpp | 27 | ||||
-rw-r--r-- | src/resolve/index.cpp | 4 |
13 files changed, 103 insertions, 31 deletions
diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index 9893e87f..03257fc6 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -315,6 +315,9 @@ Item Item::clone() const (MacroInv, TODO(this->span, "Clone on Item::MacroInv"); ), + (Macro, + TODO(this->span, "Clone on Item::Macro"); + ), (Use, return AST::Item(e.clone()); ), diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp index 43a0e027..f6f97fce 100644 --- a/src/ast/ast.hpp +++ b/src/ast/ast.hpp @@ -607,6 +607,7 @@ TAGGED_UNION_EX(Item, (), None, (Impl, Impl), (NegImpl, ImplDef), + (Macro, MacroRulesPtr), (Module, Module), (Crate, struct { ::std::string name; diff --git a/src/expand/mod.cpp b/src/expand/mod.cpp index fd851c89..bc51e1ff 100644 --- a/src/expand/mod.cpp +++ b/src/expand/mod.cpp @@ -1113,6 +1113,9 @@ void Expand_Mod(::AST::Crate& crate, LList<const AST::Module*> modstack, ::AST:: } dat.as_MacroInv() = mv$(mi_owned); } + TU_ARMA(Macro, e) { + mod.add_macro(i.is_pub, i.name, mv$(e)); + } TU_ARMA(Use, e) { // No inner expand. } diff --git a/src/hir/from_ast.cpp b/src/hir/from_ast.cpp index af6bc9cb..2393cadd 100644 --- a/src/hir/from_ast.cpp +++ b/src/hir/from_ast.cpp @@ -1433,6 +1433,8 @@ void _add_mod_val_item(::HIR::Module& mod, ::std::string name, ::HIR::Publicity TU_MATCH(::AST::Item, (item.data), (e), (None, ), + (Macro, + ), (MacroInv, // Valid. //BUG(sp, "Stray macro invocation in " << path); diff --git a/src/ident.cpp b/src/ident.cpp index da029e21..63fe57ed 100644 --- a/src/ident.cpp +++ b/src/ident.cpp @@ -34,7 +34,10 @@ bool Ident::Hygiene::is_visible(const Hygiene& src) const } ::std::ostream& operator<<(::std::ostream& os, const Ident::Hygiene& x) { - os << "{" << x.contexts << "}"; + os << "{" << x.contexts; + if( x.search_module ) + os << " " << x.search_module->ents; + os << "}"; return os; } diff --git a/src/include/ident.hpp b/src/include/ident.hpp index b9a6dec5..ec42c582 100644 --- a/src/include/ident.hpp +++ b/src/include/ident.hpp @@ -8,14 +8,21 @@ #pragma once #include <vector> #include <string> +#include <memory> struct Ident { + struct ModPath + { + //::std::vector<RcString> ents; + ::std::vector<::std::string> ents; + }; class Hygiene { static unsigned g_next_scope; ::std::vector<unsigned int> contexts; + ::std::shared_ptr<ModPath> search_module; Hygiene(unsigned int index): contexts({index}) @@ -32,6 +39,7 @@ struct Ident static Hygiene new_scope_chained(const Hygiene& parent) { Hygiene rv; + rv.search_module = parent.search_module; 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 ); @@ -45,12 +53,22 @@ struct Ident return rv; } + bool has_mod_path() const { + return this->search_module != 0; + } + const ModPath& mod_path() const { + return *this->search_module; + } + void set_mod_path(ModPath p) { + this->search_module.reset( new ModPath(::std::move(p)) ); + } + Hygiene(Hygiene&& x) = default; Hygiene(const Hygiene& x) = default; Hygiene& operator=(Hygiene&& x) = default; Hygiene& operator=(const Hygiene& x) = default; - // Returns true if an ident with hygine `souce` can see an ident with this hygine + // Returns true if an ident with hygine `source` 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; } diff --git a/src/macro_rules/eval.cpp b/src/macro_rules/eval.cpp index 9caff7b8..c40eb810 100644 --- a/src/macro_rules/eval.cpp +++ b/src/macro_rules/eval.cpp @@ -502,6 +502,7 @@ InterpolatedFragment Macro_HandlePatternCap(TokenStream& lex, MacroPatEnt::Type ::std::unique_ptr<TokenStream> Macro_InvokeRules(const char *name, const MacroRules& rules, const Span& sp, TokenTree input, AST::Module& mod) { TRACE_FUNCTION_F("'" << name << "', " << input); + DEBUG("rules.m_hygiene = " << rules.m_hygiene); ParameterMappings bound_tts; unsigned int rule_index = Macro_InvokeRules_MatchPattern(sp, rules, mv$(input), mod, bound_tts); diff --git a/src/macro_rules/macro_rules.hpp b/src/macro_rules/macro_rules.hpp index 02b302d8..9e408fd5 100644 --- a/src/macro_rules/macro_rules.hpp +++ b/src/macro_rules/macro_rules.hpp @@ -181,4 +181,8 @@ public: extern ::std::unique_ptr<TokenStream> Macro_InvokeRules(const char *name, const MacroRules& rules, const Span& sp, TokenTree input, AST::Module& mod); extern MacroRulesPtr Parse_MacroRules(TokenStream& lex); +extern ::std::vector<MacroPatEnt> Parse_MacroRules_Pat(TokenStream& lex, enum eTokenType open, enum eTokenType close, ::std::vector< ::std::string>& names); +extern ::std::vector<MacroExpansionEnt> Parse_MacroRules_Cont(TokenStream& lex, enum eTokenType open, enum eTokenType close, const ::std::vector< ::std::string>& var_names, ::std::map<unsigned int,bool>* var_set_ptr=nullptr); +extern MacroRulesArm Parse_MacroRules_MakeArm(Span pat_sp, ::std::vector<MacroPatEnt> pattern, ::std::vector<MacroExpansionEnt> contents); + #endif // MACROS_HPP_INCLUDED diff --git a/src/macro_rules/parse.cpp b/src/macro_rules/parse.cpp index 98163998..4bd8a577 100644 --- a/src/macro_rules/parse.cpp +++ b/src/macro_rules/parse.cpp @@ -40,6 +40,7 @@ public: int depth = 0; while( GET_TOK(tok, lex) != close || depth > 0 ) { + DEBUG("tok = " << tok); if( tok.type() == open ) { depth ++; @@ -142,7 +143,7 @@ public: TokenStream& lex, enum eTokenType open, enum eTokenType close, const ::std::vector< ::std::string>& var_names, - ::std::map<unsigned int,bool>* var_set_ptr=nullptr + ::std::map<unsigned int,bool>* var_set_ptr/*=nullptr*/ ) { TRACE_FUNCTION; @@ -310,6 +311,15 @@ void enumerate_names(const ::std::vector<MacroPatEnt>& pats, ::std::vector< ::st } } +MacroRulesArm Parse_MacroRules_MakeArm(Span pat_sp, ::std::vector<MacroPatEnt> pattern, ::std::vector<MacroExpansionEnt> contents) +{ + // - Convert the rule into an instruction stream + auto rule_sequence = macro_pattern_to_simple(pat_sp, pattern); + auto arm = MacroRulesArm( mv$(rule_sequence), mv$(contents) ); + enumerate_names(pattern, arm.m_param_names); + return arm; +} + /// Parse an entire macro_rules! block into a format that exec.cpp can use MacroRulesPtr Parse_MacroRules(TokenStream& lex) { @@ -336,13 +346,7 @@ MacroRulesPtr Parse_MacroRules(TokenStream& lex) // Re-parse the patterns into a unified form for(auto& rule : rules) { - // TODO: Transform the pattern into a DFA or similar here (seekable instruction stream?) - - auto rule_sequence = macro_pattern_to_simple(rule.m_pat_span, rule.m_pattern); - MacroRulesArm arm = MacroRulesArm( mv$(rule_sequence), mv$(rule.m_contents) ); - enumerate_names(rule.m_pattern, arm.m_param_names); - - rule_arms.push_back( mv$(arm) ); + rule_arms.push_back( Parse_MacroRules_MakeArm(rule.m_pat_span, mv$(rule.m_pattern), mv$(rule.m_contents)) ); } auto rv = new MacroRules( ); diff --git a/src/parse/paths.cpp b/src/parse/paths.cpp index cb704f85..5c99e049 100644 --- a/src/parse/paths.cpp +++ b/src/parse/paths.cpp @@ -103,6 +103,7 @@ AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generi // TODO: TOK_INTERPOLATED_IDENT? GET_CHECK_TOK(tok, lex, TOK_IDENT); auto hygine = lex.getHygiene(); + DEBUG("hygine = " << hygine); PUTBACK(tok, lex); return AST::Path(AST::Path::TagRelative(), mv$(hygine), Parse_PathNodes(lex, generic_mode)); } diff --git a/src/parse/root.cpp b/src/parse/root.cpp index c055c190..b0c37a21 100644 --- a/src/parse/root.cpp +++ b/src/parse/root.cpp @@ -20,6 +20,7 @@ #include "lex.hpp" // New file lexer #include <parse/interpolated_fragment.hpp> #include <ast/expr.hpp> +#include <macro_rules/macro_rules.hpp> template<typename T> Spanned<T> get_spanned(TokenStream& lex, ::std::function<T()> f) { @@ -1931,31 +1932,31 @@ namespace { GET_TOK(tok, lex); throw ParseError::Unexpected(lex, tok); } + DEBUG("name = " << name); - //::std::vector< ::std::string> names; - //auto arm_pat = Parse_MacroRules_Pat(lex, TOK_PAREN_OPEN, TOK_PAREN_CLOSE, names); - auto args_tt = Parse_TT(lex, false); - if( lex.lookahead(0) != TOK_BRACE_OPEN ) + ::std::vector< ::std::string> names; + auto ps = lex.start_span(); + GET_CHECK_TOK(tok, lex, TOK_PAREN_OPEN); + auto arm_pat = Parse_MacroRules_Pat(lex, TOK_PAREN_OPEN, TOK_PAREN_CLOSE, names); + auto pat_span = lex.end_span(ps); + GET_CHECK_TOK(tok, lex, TOK_BRACE_OPEN); + // TODO: Pass a flag that annotates all idents with the current module? + auto body = Parse_MacroRules_Cont(lex, TOK_BRACE_OPEN, TOK_BRACE_CLOSE, names); + + auto mr = new MacroRules( ); + mr->m_hygiene = lex.getHygiene(); { - GET_TOK(tok, lex); - throw ParseError::Unexpected(lex, tok); + Ident::ModPath mp; + for(const auto& node : mod_path.nodes()) + { + mp.ents.push_back(node.name()); + } + mr->m_hygiene.set_mod_path(::std::move(mp)); } - //auto body = Parse_MacroRules_Cont(lex, TOK_BRACE_OPEN, TOK_BRACE_CLOSE, names); - auto body_tt = Parse_TT(lex, false); - - // TODO: Invoke the macro_rules parsers here - // - Could also do the same level of parsing when `macro_rules! foo {` is seen (i.e. parse macros at parse - // time, instead of during expand). - // - That would simplify some of the expand logic... + mr->m_rules.push_back(Parse_MacroRules_MakeArm(pat_span, ::std::move(arm_pat), ::std::move(body))); - // Lazy option: create a TT - ::std::vector<TokenTree> out; - out.push_back(mv$(args_tt)); - out.push_back(TokenTree( Token(TOK_FATARROW) )); - out.push_back(mv$(body_tt)); - - item_name = ""; - item_data = ::AST::Item( AST::MacroInvocation(lex.end_span(ps), "macro_rules", name, TokenTree({}, mv$(out))) ); + item_name = name; + item_data = ::AST::Item( MacroRulesPtr(mr) ); } else { diff --git a/src/resolve/absolute.cpp b/src/resolve/absolute.cpp index 95e01d18..c2dedfcb 100644 --- a/src/resolve/absolute.cpp +++ b/src/resolve/absolute.cpp @@ -424,6 +424,29 @@ namespace } AST::Path lookup_opt(const ::std::string& name, const Ident::Hygiene& src_context, LookupMode mode) const { DEBUG("name=" << name <<", src_context=" << src_context); + // NOTE: src_context may provide a module to search + if( src_context.has_mod_path() ) + { + DEBUG(src_context.mod_path().ents); + const AST::Module* mod = &m_crate.root_module(); + for(const auto& node : src_context.mod_path().ents) + { + const AST::Module* next = nullptr; + for(const auto& i : mod->items()) + { + if( i.name == node ) { + next = &i.data.as_Module(); + break; + } + } + assert(next); + mod = next; + } + ::AST::Path rv; + if( this->lookup_in_mod(*mod, name, mode, rv) ) { + return rv; + } + } for(auto it = m_name_context.rbegin(); it != m_name_context.rend(); ++ it) { TU_MATCH(Ent, (*it), (e), @@ -2012,6 +2035,7 @@ void Resolve_Absolute_ImplItems(Context& item_context, ::AST::NamedList< ::AST: (ExternBlock, BUG(i.data.span, "Resolve_Absolute_ImplItems - " << i.data.tag_str());), (Impl, BUG(i.data.span, "Resolve_Absolute_ImplItems - " << i.data.tag_str());), (NegImpl, BUG(i.data.span, "Resolve_Absolute_ImplItems - " << i.data.tag_str());), + (Macro, BUG(i.data.span, "Resolve_Absolute_ImplItems - " << i.data.tag_str());), (Use, BUG(i.data.span, "Resolve_Absolute_ImplItems - Use");), (Module, BUG(i.data.span, "Resolve_Absolute_ImplItems - Module");), (Crate , BUG(i.data.span, "Resolve_Absolute_ImplItems - Crate");), @@ -2056,6 +2080,7 @@ void Resolve_Absolute_ImplItems(Context& item_context, ::std::vector< ::AST::Im (Impl , BUG(i.data->span, "Resolve_Absolute_ImplItems - " << i.data->tag_str());), (NegImpl, BUG(i.data->span, "Resolve_Absolute_ImplItems - " << i.data->tag_str());), (ExternBlock, BUG(i.data->span, "Resolve_Absolute_ImplItems - " << i.data->tag_str());), + (Macro , BUG(i.data->span, "Resolve_Absolute_ImplItems - " << i.data->tag_str());), (Use , BUG(i.data->span, "Resolve_Absolute_ImplItems - " << i.data->tag_str());), (Module, BUG(i.data->span, "Resolve_Absolute_ImplItems - " << i.data->tag_str());), (Crate , BUG(i.data->span, "Resolve_Absolute_ImplItems - " << i.data->tag_str());), @@ -2221,6 +2246,8 @@ void Resolve_Absolute_Mod( Context item_context, ::AST::Module& mod ) ), (Use, ), + (Macro, + ), (ExternBlock, for(auto& i2 : e.items()) { diff --git a/src/resolve/index.cpp b/src/resolve/index.cpp index f38219ef..43182faf 100644 --- a/src/resolve/index.cpp +++ b/src/resolve/index.cpp @@ -121,6 +121,10 @@ void Resolve_Index_Module_Base(const AST::Crate& crate, AST::Module& mod) (NegImpl, ), + (Macro, + // TODO: Add to a macro list + ), + (Use, // Skip for now ), |