diff options
| -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              ), | 
