diff options
| -rw-r--r-- | Makefile | 1 | ||||
| -rw-r--r-- | rust-nightly-date | 2 | ||||
| -rw-r--r-- | src/ast/ast.hpp | 5 | ||||
| -rw-r--r-- | src/ast/attrs.hpp | 1 | ||||
| -rw-r--r-- | src/ast/path.hpp | 4 | ||||
| -rw-r--r-- | src/expand/assert.cpp | 89 | ||||
| -rw-r--r-- | src/expand/file_line.cpp | 9 | ||||
| -rw-r--r-- | src/expand/lang_item.cpp | 15 | ||||
| -rw-r--r-- | src/expand/mod.cpp | 19 | ||||
| -rw-r--r-- | src/hir/from_ast.cpp | 6 | ||||
| -rw-r--r-- | src/include/main_bindings.hpp | 1 | ||||
| -rw-r--r-- | src/macro_rules/eval.cpp | 4 | ||||
| -rw-r--r-- | src/macro_rules/parse.cpp | 14 | ||||
| -rw-r--r-- | src/main.cpp | 2 | ||||
| -rw-r--r-- | src/parse/eTokenType.enum.h | 1 | ||||
| -rw-r--r-- | src/parse/expr.cpp | 9 | ||||
| -rw-r--r-- | src/parse/lex.cpp | 8 | ||||
| -rw-r--r-- | src/parse/pattern.cpp | 5 | ||||
| -rw-r--r-- | src/parse/root.cpp | 73 | ||||
| -rw-r--r-- | src/parse/token.cpp | 11 | ||||
| -rw-r--r-- | src/parse/tokenstream.hpp | 2 | 
21 files changed, 251 insertions, 30 deletions
| @@ -89,6 +89,7 @@ OBJ +=  expand/env.o  OBJ +=  expand/test.o  OBJ +=  expand/rustc_diagnostics.o  OBJ +=  expand/proc_macro.o +OBJ +=  expand/assert.o  OBJ += expand/test_harness.o  OBJ += macro_rules/mod.o macro_rules/eval.o macro_rules/parse.o  OBJ += resolve/use.o resolve/index.o resolve/absolute.o diff --git a/rust-nightly-date b/rust-nightly-date index 69416130..1242c4a4 100644 --- a/rust-nightly-date +++ b/rust-nightly-date @@ -1 +1 @@ -2017-07-14 +2018-07-09 diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp index 0a43cc71..19f0c66b 100644 --- a/src/ast/ast.hpp +++ b/src/ast/ast.hpp @@ -8,6 +8,9 @@  #ifndef AST_HPP_INCLUDED  #define AST_HPP_INCLUDED +#define TARGETVER_1_19  true +#define TARGETVER_1_29  true +  #include <string>  #include <vector>  #include <stdexcept> @@ -44,6 +47,8 @@ enum eItemType  {      ITEM_TRAIT,      ITEM_STRUCT, +    ITEM_ENUM, +    ITEM_UNION,      ITEM_FN,      ITEM_STATIC,  }; diff --git a/src/ast/attrs.hpp b/src/ast/attrs.hpp index 1926e96a..860e75ee 100644 --- a/src/ast/attrs.hpp +++ b/src/ast/attrs.hpp @@ -77,6 +77,7 @@ class Attribute      ::std::string   m_name;      AttributeData   m_data;      mutable bool    m_is_used; +    // TODO: Parse as a TT then expand?  public:      Attribute(Span sp, ::std::string name):          m_span(::std::move(sp)), diff --git a/src/ast/path.hpp b/src/ast/path.hpp index c2d13d73..2693a070 100644 --- a/src/ast/path.hpp +++ b/src/ast/path.hpp @@ -271,6 +271,10 @@ public:          return Path(*this) += x;      }      Path& operator+=(const Path& x); +    Path& operator+=(PathNode pn) { +        this->nodes().push_back( mv$(pn) ); +        return *this; +    }      void append(PathNode node) {          assert( !m_class.is_Invalid() ); diff --git a/src/expand/assert.cpp b/src/expand/assert.cpp new file mode 100644 index 00000000..1c057935 --- /dev/null +++ b/src/expand/assert.cpp @@ -0,0 +1,89 @@ +/* + * MRustC - Rust Compiler + * - By John Hodge (Mutabah/thePowersGang) + * + * expand/assert.cpp + * - assert! built-in macro (1.29) + */ +#include <synext_macro.hpp> +#include <synext.hpp>   // for Expand_BareExpr +#include <parse/interpolated_fragment.hpp> +#include "../parse/ttstream.hpp" +#include "../parse/common.hpp" +#include "../parse/parseerror.hpp" + +class CExpander_assert: +    public ExpandProcMacro +{ +    ::std::unique_ptr<TokenStream> expand(const Span& sp, const ::AST::Crate& crate, const ::std::string& ident, const TokenTree& tt, AST::Module& mod) override +    { +        Token   tok; + +        auto lex = TTStream(sp, tt); +        lex.parse_state().module = &mod; +        if( ident != "" ) +            ERROR(sp, E0000, "format_args! doesn't take an ident"); + +        // assertion condition +        auto n = Parse_Expr0(lex); +        ASSERT_BUG(sp, n, "No expression returned"); + +        ::std::vector<TokenTree> toks; + +        toks.push_back( Token(TOK_RWORD_IF) ); + +        GET_TOK(tok, lex); +        if( tok == TOK_COMMA ) +        { +            toks.push_back( Token(InterpolatedFragment(InterpolatedFragment::EXPR, n.release())) ); +            toks.push_back( Token(TOK_BRACE_OPEN) ); +            // User-provided message +            toks.push_back( Token(TOK_IDENT, "panic") ); +            toks.push_back( Token(TOK_EXCLAM) ); +            toks.push_back( Token(TOK_PAREN_OPEN) ); +            while(lex.lookahead(0) != TOK_EOF ) +            { +                toks.push_back( Token(InterpolatedFragment(InterpolatedFragment::EXPR, Parse_Expr0(lex).release())) ); +                if( lex.lookahead(0) != TOK_COMMA ) +                    break; +                GET_CHECK_TOK(tok, lex, TOK_COMMA); +                toks.push_back( Token(TOK_COMMA) ); +            } +            GET_CHECK_TOK(tok, lex, TOK_EOF); +            toks.push_back( Token(TOK_PAREN_CLOSE) ); +        } +        else if( tok == TOK_EOF ) +        { +            ::std::stringstream ss; +            ss << "assertion failed: "; +            n->print(ss); + +            toks.push_back( Token(InterpolatedFragment(InterpolatedFragment::EXPR, n.release())) ); + +            toks.push_back( Token(TOK_BRACE_OPEN) ); +            // Auto-generated message +            toks.push_back( Token(TOK_IDENT, "panic") ); +            toks.push_back( Token(TOK_EXCLAM) ); +            toks.push_back( Token(TOK_PAREN_OPEN) ); +            toks.push_back( Token(TOK_STRING, ss.str()) ); +            toks.push_back( Token(TOK_PAREN_CLOSE) ); +        } +        else +        { +            throw ParseError::Unexpected(lex, tok, {TOK_COMMA, TOK_EOF}); +        } + +        toks.push_back( Token(TOK_BRACE_CLOSE) ); + +        return box$( TTStreamO(sp, TokenTree(Ident::Hygiene::new_scope(), mv$(toks))) ); +    } +}; + +void Expand_init_assert() +{ +    if( TARGETVER_1_29 ) +    { +        Register_Synext_Macro("assert", ::std::unique_ptr<ExpandProcMacro>(new CExpander_assert)); +    } +} + diff --git a/src/expand/file_line.cpp b/src/expand/file_line.cpp index 7a827ccf..2bf85ffd 100644 --- a/src/expand/file_line.cpp +++ b/src/expand/file_line.cpp @@ -46,6 +46,14 @@ class CExpanderColumn:          return box$( TTStreamO(sp, TokenTree(Token((uint64_t)get_top_span(sp).start_ofs, CORETYPE_U32))) );      }  }; +class CExpanderUnstableColumn: +    public ExpandProcMacro +{ +    ::std::unique_ptr<TokenStream> expand(const Span& sp, const AST::Crate& crate, const ::std::string& ident, const TokenTree& tt, AST::Module& mod) override +    { +        return box$( TTStreamO(sp, TokenTree(Token((uint64_t)get_top_span(sp).start_ofs, CORETYPE_U32))) ); +    } +};  class CExpanderModulePath:      public ExpandProcMacro @@ -65,5 +73,6 @@ class CExpanderModulePath:  STATIC_MACRO("file", CExpanderFile);  STATIC_MACRO("line", CExpanderLine);  STATIC_MACRO("column", CExpanderColumn); +STATIC_MACRO("__rust_unstable_column", CExpanderUnstableColumn);  STATIC_MACRO("module_path", CExpanderModulePath); diff --git a/src/expand/lang_item.cpp b/src/expand/lang_item.cpp index 789ad88e..62527ac9 100644 --- a/src/expand/lang_item.cpp +++ b/src/expand/lang_item.cpp @@ -30,6 +30,7 @@ void handle_lang_item(const Span& sp, AST::Crate& crate, const AST::Path& path,      else if( name == "copy" ) {          DEBUG("Bind 'copy' to " << path);      } +    else if( TARGETVER_1_29 && name == "clone" ) {}   // - Trait      // ops traits      else if( name == "drop" ) { DEBUG("Bind '"<<name<<"' to " << path); }      else if( name == "add" ) { DEBUG("Bind '"<<name<<"' to " << path); } @@ -67,7 +68,8 @@ void handle_lang_item(const Span& sp, AST::Crate& crate, const AST::Path& path,      else if( name == "fn_once" ) { DEBUG("Bind '"<<name<<"' to " << path); }      else if( name == "eq"  ) { DEBUG("Bind '"<<name<<"' to " << path); } -    else if( name == "ord" ) { DEBUG("Bind '"<<name<<"' to " << path); } +    else if( TARGETVER_1_19 && name == "ord" ) { DEBUG("Bind '"<<name<<"' to " << path); } +    else if( TARGETVER_1_29 && name == "partial_ord" ) { DEBUG("Bind '"<<name<<"' to " << path); }    // New name for v1.29      else if( name == "unsize" ) { DEBUG("Bind '"<<name<<"' to " << path); }      else if( name == "coerce_unsized" ) { DEBUG("Bind '"<<name<<"' to " << path); }      else if( name == "freeze" ) { DEBUG("Bind '"<<name<<"' to " << path); } @@ -84,6 +86,12 @@ void handle_lang_item(const Span& sp, AST::Crate& crate, const AST::Path& path,      else if( name == "range_from" ) { }      else if( name == "range_to" ) { }      else if( name == "unsafe_cell" ) { } +    else if( TARGETVER_1_29 && name == "alloc_layout") { } +    else if( TARGETVER_1_29 && name == "panic_info" ) {}    // Struct + +    // Generators +    else if( TARGETVER_1_29 && name == "generator" ) {}   // - Trait +    else if( TARGETVER_1_29 && name == "generator_state" ) {}   // - State enum      // Statics      else if( name == "msvc_try_filter" ) { } @@ -96,6 +104,7 @@ void handle_lang_item(const Span& sp, AST::Crate& crate, const AST::Path& path,      }      else if( name == "str_eq" ) { }      else if( name == "drop_in_place" ) { } +    else if( name == "align_offset" ) { }      // - builtin `box` support      else if( name == "exchange_malloc" ) { }      else if( name == "exchange_free" ) { } @@ -148,6 +157,9 @@ public:          (Struct,              handle_lang_item(sp, crate, path, attr.string(), AST::ITEM_STRUCT);              ), +        (Enum, +            handle_lang_item(sp, crate, path, attr.string(), AST::ITEM_ENUM); +            ),          (Trait,              handle_lang_item(sp, crate, path, attr.string(), AST::ITEM_TRAIT);              ) @@ -176,6 +188,7 @@ public:          // collections          else if( name == "str" ) {}          else if( name == "slice" ) {} +        else if( TARGETVER_1_29 && name == "slice_u8" ) {}          // std - interestingly          else if( name == "f32" ) {}          else if( name == "f64" ) {} diff --git a/src/expand/mod.cpp b/src/expand/mod.cpp index 5d6d3234..872105a6 100644 --- a/src/expand/mod.cpp +++ b/src/expand/mod.cpp @@ -41,6 +41,12 @@ void Register_Synext_Macro_Static(MacroDef* def) {      g_macros_list = def;  } +void Expand_Init() +{ +    // TODO: Initialise all macros here. +    void Expand_init_assert(); Expand_init_assert(); +} +  void ExpandDecorator::unexpected(const Span& sp, const AST::Attribute& mi, const char* loc_str) const  { @@ -86,7 +92,7 @@ void Expand_Attrs(::AST::AttributeList& attrs, AttrStage stage,  ::AST::Crate& c      Expand_Attrs(attrs, stage,  [&](const auto& sp, const auto& d, const auto& a){ d.handle(sp, a, crate, mod, impl); });  } -::std::unique_ptr<TokenStream> Expand_Macro( +::std::unique_ptr<TokenStream> Expand_Macro_Inner(      const ::AST::Crate& crate, LList<const AST::Module*> modstack, ::AST::Module& mod,      Span mi_span, const ::std::string& name, const ::std::string& input_ident, TokenTree& input_tt      ) @@ -144,6 +150,17 @@ void Expand_Attrs(::AST::AttributeList& attrs, AttrStage stage,  ::AST::Crate& c      // Error - Unknown macro name      ERROR(mi_span, E0000, "Unknown macro '" << name << "'");  } +::std::unique_ptr<TokenStream> Expand_Macro( +    const ::AST::Crate& crate, LList<const AST::Module*> modstack, ::AST::Module& mod, +    Span mi_span, const ::std::string& name, const ::std::string& input_ident, TokenTree& input_tt +    ) +{ +    auto rv = Expand_Macro_Inner(crate, modstack, mod, mi_span, name, input_ident, input_tt); +    assert(rv); +    rv->parse_state().module = &mod; +    rv->parse_state().crate = &crate; +    return rv; +}  ::std::unique_ptr<TokenStream> Expand_Macro(const ::AST::Crate& crate, LList<const AST::Module*> modstack, ::AST::Module& mod, ::AST::MacroInvocation& mi)  {      return Expand_Macro(crate, modstack, mod,  mi.span(), mi.name(), mi.input_ident(), mi.input_tt()); diff --git a/src/hir/from_ast.cpp b/src/hir/from_ast.cpp index 7f25a42b..5dbf9c03 100644 --- a/src/hir/from_ast.cpp +++ b/src/hir/from_ast.cpp @@ -901,6 +901,9 @@ namespace {              else if( repr_str == "simd" ) {                  is_simd = true;              } +            else if( repr_str == "transparent" ) { +                // TODO: Mark so the C backend knows that it's supposed to be transparent +            }              else {                  TODO(a.span(), "Handle struct repr '" << repr_str << "'");              } @@ -1247,7 +1250,8 @@ namespace {          else TU_IFLET(::HIR::TypeRef::Data, arg_self_ty.m_data, Path, e,              // Box - Compare with `owned_box` lang item              TU_IFLET(::HIR::Path::Data, e.path.m_data, Generic, pe, -                if( pe.m_path == g_crate_ptr->get_lang_item_path(sp, "owned_box") ) +                auto p = g_crate_ptr->get_lang_item_path_opt("owned_box"); +                if( pe.m_path == p )                  {                      if( pe.m_params.m_types.size() == 1 && pe.m_params.m_types[0] == self_type )                      { diff --git a/src/include/main_bindings.hpp b/src/include/main_bindings.hpp index c9e573d4..8085eb4c 100644 --- a/src/include/main_bindings.hpp +++ b/src/include/main_bindings.hpp @@ -18,6 +18,7 @@ namespace AST {  /// Parse a crate from the given file  extern AST::Crate Parse_Crate(::std::string mainfile); +extern void Expand_Init();  extern void Expand(::AST::Crate& crate);  extern void Expand_TestHarness(::AST::Crate& crate);  extern void Expand_ProcMacro(::AST::Crate& crate); diff --git a/src/macro_rules/eval.cpp b/src/macro_rules/eval.cpp index a393ba46..cda51ebe 100644 --- a/src/macro_rules/eval.cpp +++ b/src/macro_rules/eval.cpp @@ -1189,7 +1189,8 @@ namespace              }              if(lex.consume_if(TOK_AT))                  continue; -            if( lex.consume_if(TOK_TRIPLE_DOT) ) +            // ... or ..= +            if( lex.consume_if(TOK_TRIPLE_DOT) || lex.consume_if(TOK_DOUBLE_DOT_EQUAL) )              {                  switch(lex.next())                  { @@ -1491,6 +1492,7 @@ namespace              case TOK_DOUBLE_AMP:              case TOK_DOUBLE_PIPE:              case TOK_DOUBLE_DOT: +            case TOK_DOUBLE_DOT_EQUAL:              case TOK_TRIPLE_DOT:                  lex.consume();                  break; diff --git a/src/macro_rules/parse.cpp b/src/macro_rules/parse.cpp index b3b1014e..00cf7cf7 100644 --- a/src/macro_rules/parse.cpp +++ b/src/macro_rules/parse.cpp @@ -49,8 +49,7 @@ public:              switch( GET_TOK(tok, lex) )              {              // TODO: Allow any reserved word -            case TOK_RWORD_TYPE: -            case TOK_RWORD_PUB: +            case TOK_RWORD_PUB ... TOK_RWORD_UNSIZED:              case TOK_IDENT: {                  ::std::string   name = tok.type() == TOK_IDENT ? mv$(tok.str()) : FMT(tok);                  GET_CHECK_TOK(tok, lex, TOK_COLON); @@ -200,10 +199,13 @@ public:                  default:                      throw ParseError::Unexpected(lex, tok);                  } - +            } +            else if( tok.type() == TOK_RWORD_CRATE ) +            { +                ret.push_back( MacroExpansionEnt( (1<<30) | 0 ) );              }              //else if( tok.type() == TOK_IDENT || tok_is_rword(tok.type()) ) -            else if( tok.type() == TOK_IDENT || tok.type() == TOK_RWORD_TYPE || tok.type() == TOK_RWORD_PUB ) +            else if( tok.type() == TOK_IDENT || tok.type() >= TOK_RWORD_PUB )              {                  // Look up the named parameter in the list of param names for this arm                  auto name = tok.type() == TOK_IDENT ? tok.str() : FMT(tok); @@ -222,10 +224,6 @@ public:                  }                  ret.push_back( MacroExpansionEnt(idx) );              } -            else if( tok.type() == TOK_RWORD_CRATE ) -            { -                ret.push_back( MacroExpansionEnt( (1<<30) | 0 ) ); -            }              else              {                  throw ParseError::Unexpected(lex, tok); diff --git a/src/main.cpp b/src/main.cpp index 8f2740fc..85afcb33 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -221,6 +221,8 @@ int main(int argc, char *argv[])          Cfg_SetFlag("test");      } +    Expand_Init(); +      try      {          // Parse the crate into AST diff --git a/src/parse/eTokenType.enum.h b/src/parse/eTokenType.enum.h index 5104142b..4408c45a 100644 --- a/src/parse/eTokenType.enum.h +++ b/src/parse/eTokenType.enum.h @@ -58,6 +58,7 @@ _(TOK_SLASH)  _(TOK_DOT)  _(TOK_DOUBLE_DOT) +_(TOK_DOUBLE_DOT_EQUAL)  _(TOK_TRIPLE_DOT)  _(TOK_EQUAL) diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp index 5194e1d8..e5d7981d 100644 --- a/src/parse/expr.cpp +++ b/src/parse/expr.cpp @@ -706,7 +706,7 @@ ExprNodeP Parse_Expr1_1(TokenStream& lex)      ExprNodeP   left, right;      // Inclusive range to a value -    if( GET_TOK(tok, lex) == TOK_TRIPLE_DOT ) { +    if( GET_TOK(tok, lex) == TOK_TRIPLE_DOT || (TARGETVER_1_29 && tok.type() == TOK_DOUBLE_DOT_EQUAL) ) {          right = next(lex);          return NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::RANGE_INC, nullptr, mv$(right) );      } @@ -746,6 +746,13 @@ LEFTASSOC(Parse_Expr1_2, Parse_Expr1_5,      case TOK_TRIPLE_DOT:          rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::RANGE_INC, mv$(rv), next(lex) );          break; +    case TOK_DOUBLE_DOT_EQUAL: +        if( TARGETVER_1_29 ) +        { +            rv = NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::RANGE_INC, mv$(rv), next(lex) ); +            break; +        } +        // Fall through  )  // 1: Bool OR  LEFTASSOC(Parse_Expr1_5, Parse_Expr2, diff --git a/src/parse/lex.cpp b/src/parse/lex.cpp index 8376eeee..0b145379 100644 --- a/src/parse/lex.cpp +++ b/src/parse/lex.cpp @@ -83,8 +83,10 @@ static const struct {    TOKENT("-=", TOK_DASH_EQUAL),    TOKENT("->", TOK_THINARROW),    TOKENT(".",  TOK_DOT), +  // NOTE: These have special handling when following numbers    TOKENT("..", TOK_DOUBLE_DOT),    TOKENT("...",TOK_TRIPLE_DOT), +  TOKENT("..=",TOK_DOUBLE_DOT_EQUAL),    TOKENT("/" , TOK_SLASH),    TOKENT("/*", BLOCKCOMMENT),    TOKENT("//", LINECOMMENT), @@ -402,9 +404,13 @@ Token Lexer::getTokenInt()                          // Double/Triple Dot                          if( ch == '.' )                          { -                            if( this->getc() == '.') { +                            ch = this->getc(); +                            if( ch == '.') {                                  this->m_next_tokens.push_back(TOK_TRIPLE_DOT);                              } +                            else if( ch == '=') { +                                this->m_next_tokens.push_back(TOK_DOUBLE_DOT_EQUAL); +                            }                              else {                                  this->ungetc();                                  this->m_next_tokens.push_back(TOK_DOUBLE_DOT); diff --git a/src/parse/pattern.cpp b/src/parse/pattern.cpp index f6d61728..239bac80 100644 --- a/src/parse/pattern.cpp +++ b/src/parse/pattern.cpp @@ -113,6 +113,7 @@ AST::Pattern Parse_Pattern(TokenStream& lex, bool is_refutable)              break;          // Known value `IDENT ...`          case TOK_TRIPLE_DOT: +        case TOK_DOUBLE_DOT_EQUAL:              break;          // Known binding `ident @`          case TOK_AT: @@ -156,7 +157,9 @@ AST::Pattern Parse_PatternReal(TokenStream& lex, bool is_refutable)      }      auto ps = lex.start_span();      AST::Pattern    ret = Parse_PatternReal1(lex, is_refutable); -    if( GET_TOK(tok, lex) == TOK_TRIPLE_DOT ) +    if( (GET_TOK(tok, lex) == TOK_TRIPLE_DOT) +     || (TARGETVER_1_29 && tok.type() == TOK_DOUBLE_DOT_EQUAL) +      )      {          if( !ret.data().is_Value() )              throw ParseError::Generic(lex, "Using '...' with a non-value on left"); diff --git a/src/parse/root.cpp b/src/parse/root.cpp index 68ad570b..ef1fb439 100644 --- a/src/parse/root.cpp +++ b/src/parse/root.cpp @@ -18,6 +18,7 @@  #include <expand/cfg.hpp>   // check_cfg - for `mod nonexistant;`  #include <fstream>  // Used by directory path  #include "lex.hpp"  // New file lexer +#include <parse/interpolated_fragment.hpp>  #include <ast/expr.hpp>  template<typename T> @@ -649,9 +650,7 @@ AST::Trait Parse_TraitDef(TokenStream& lex, const AST::AttributeList& meta_items          // TODO: Just add these as `where Self: <foo>` (would that break typecheck?)          do {              if( GET_TOK(tok, lex) == TOK_LIFETIME ) { -                // TODO: Need a better way of indiciating 'static than just an invalid path -                ASSERT_BUG(lex.point_span(), tok.str() == "static", "TODO: Support lifetimes other than 'static in trait bounds"); -                supertraits.push_back( make_spanned( Span(tok.get_pos()), Type_TraitPath{ {}, AST::Path() } ) ); +                params.add_bound(::AST::GenericBound::make_TypeLifetime({ TypeRef(lex.point_span(), "Self"), ::AST::LifetimeRef(lex.get_ident(tok)) }));              }              else if( tok.type() == TOK_BRACE_OPEN ) {                  break; @@ -988,14 +987,26 @@ AST::Attribute Parse_MetaItem(TokenStream& lex)  {      TRACE_FUNCTION;      Token tok; -    GET_TOK(tok, lex); -    if( tok.type() == TOK_INTERPOLATED_META ) { +    if( lex.lookahead(0) == TOK_INTERPOLATED_META ) { +        GET_TOK(tok, lex);          return mv$(tok.frag_meta());      }      auto ps = lex.start_span(); -    CHECK_TOK(tok, TOK_IDENT); +    GET_TOK(tok, lex); + +    switch(tok.type()) +    { +    case TOK_IDENT: +        break; +    case TOK_INTEGER: +        if( TARGETVER_1_29 ) +            return AST::Attribute(lex.end_span(ps), "", tok.to_str()); +    default: +        throw ParseError::Unexpected(lex, tok, {TOK_IDENT, TOK_INTEGER}); +    } +      ::std::string   name = mv$(tok.str());      switch(GET_TOK(tok, lex))      { @@ -1006,6 +1017,10 @@ AST::Attribute Parse_MetaItem(TokenStream& lex)              return AST::Attribute(lex.end_span(ps), name, tok.str());          case TOK_INTERPOLATED_EXPR: {              auto n = tok.take_frag_node(); +            void Expand_BareExpr(const AST::Crate& , const AST::Module&, ::std::unique_ptr<AST::ExprNode>& n); +            assert( lex.parse_state().crate ); +            assert( lex.parse_state().module ); +            Expand_BareExpr(*lex.parse_state().crate, *lex.parse_state().module, n);              if( auto* v = dynamic_cast<::AST::ExprNode_String*>(&*n) )              {                  return AST::Attribute(lex.end_span(ps), name, mv$(v->m_value)); @@ -1013,9 +1028,15 @@ AST::Attribute Parse_MetaItem(TokenStream& lex)              else              {                  // - Force an error. -                CHECK_TOK(tok, TOK_STRING); +                throw ParseError::Unexpected(lex, Token(InterpolatedFragment(InterpolatedFragment::EXPR, n.release())), TOK_STRING);              }              break; } +        case TOK_INTEGER: +            if( TARGETVER_1_29 ) +                return AST::Attribute(lex.end_span(ps), name, tok.to_str()); +        case TOK_IDENT: +            if( TARGETVER_1_29 ) +                return AST::Attribute(lex.end_span(ps), name, tok.to_str());          default:              // - Force an error.              CHECK_TOK(tok, TOK_STRING); @@ -1311,8 +1332,19 @@ void Parse_Use_Set(TokenStream& lex, const ProtoSpan& ps, const AST::Path& base_              break ;          }          else { -            CHECK_TOK(tok, TOK_IDENT); -            path = base_path + AST::PathNode(tok.str(), {}); +            path = ::AST::Path(base_path); + +            while(1) +            { +                CHECK_TOK(tok, TOK_IDENT); +                path += AST::PathNode(tok.str(), {}); +                if( !TARGETVER_1_29 ) +                    break; +                if( lex.lookahead(0) != TOK_DOUBLE_COLON ) +                    break; +                GET_CHECK_TOK(tok, lex, TOK_DOUBLE_COLON); +                GET_TOK(tok, lex); +            }              name = mv$(tok.str());          } @@ -1706,6 +1738,19 @@ bool Parse_MacroInvocation_Opt(TokenStream& lex,  AST::MacroInvocation& out_inv)              }              return ::AST::Named< ::AST::Item> { "", mv$(impl), false };              } +        // `unsafe auto trait` +        case TOK_IDENT: +            if( TARGETVER_1_29 && tok.str() == "auto" ) { +                GET_CHECK_TOK(tok, lex, TOK_RWORD_TRAIT); +                GET_CHECK_TOK(tok, lex, TOK_IDENT); +                item_name = mv$(tok.str()); +                auto tr = Parse_TraitDef(lex, meta_items); +                tr.set_is_unsafe(); +                tr.set_is_marker(); +                item_data = ::AST::Item( ::std::move(tr) ); +                break; +            } +            //goto default;          default:              throw ParseError::Unexpected(lex, tok, {TOK_RWORD_FN, TOK_RWORD_TRAIT, TOK_RWORD_IMPL});          } @@ -1742,6 +1787,15 @@ bool Parse_MacroInvocation_Opt(TokenStream& lex,  AST::MacroInvocation& out_inv)              item_name = mv$(tok.str());              item_data = ::AST::Item( Parse_Union(lex, meta_items) );          } +        // `auto trait` +        else if( TARGETVER_1_29 && tok.str() == "auto" ) { +            GET_CHECK_TOK(tok, lex, TOK_RWORD_TRAIT); +            GET_CHECK_TOK(tok, lex, TOK_IDENT); +            item_name = mv$(tok.str()); +            auto tr = Parse_TraitDef(lex, meta_items); +            tr.set_is_marker(); +            item_data = ::AST::Item( ::std::move(tr) ); +        }          else {              throw ParseError::Unexpected(lex, tok);          } @@ -1959,6 +2013,7 @@ AST::Crate Parse_Crate(::std::string mainfile)      crate.root_module().m_file_info.path = mainpath;      crate.root_module().m_file_info.controls_dir = true; +    lex.parse_state().crate = &crate;      Parse_ModRoot(lex, crate.root_module(), crate.m_attrs);      return crate; diff --git a/src/parse/token.cpp b/src/parse/token.cpp index 115df135..f1471453 100644 --- a/src/parse/token.cpp +++ b/src/parse/token.cpp @@ -359,8 +359,9 @@ struct EscapedString {      case TOK_SLASH:     return "/";      case TOK_DOT:   return "."; -    case TOK_DOUBLE_DOT:    return "..."; -    case TOK_TRIPLE_DOT:    return ".."; +    case TOK_DOUBLE_DOT:    return ".."; +    case TOK_DOUBLE_DOT_EQUAL:  return "..="; +    case TOK_TRIPLE_DOT:    return "...";      case TOK_EQUAL: return "=";      case TOK_PLUS_EQUAL:    return "+="; @@ -484,13 +485,13 @@ struct EscapedString {          os << ":" << *reinterpret_cast<AST::Path*>(tok.m_data.as_Fragment());          break;      case TOK_INTERPOLATED_EXPR: -        os << ":" << *reinterpret_cast<AST::ExprNode*>(tok.m_data.as_Fragment()); +        os << ":" << *reinterpret_cast<const AST::ExprNode*>(tok.m_data.as_Fragment());          break;      case TOK_INTERPOLATED_STMT: -        os << ":" << *reinterpret_cast<AST::ExprNode*>(tok.m_data.as_Fragment()); +        os << ":" << *reinterpret_cast<const AST::ExprNode*>(tok.m_data.as_Fragment());          break;      case TOK_INTERPOLATED_BLOCK: -        os << ":" << *reinterpret_cast<AST::ExprNode*>(tok.m_data.as_Fragment()); +        os << ":" << *reinterpret_cast<const AST::ExprNode*>(tok.m_data.as_Fragment());          break;      case TOK_INTERPOLATED_META:          os << ":" << *reinterpret_cast<AST::Attribute*>(tok.m_data.as_Fragment()); diff --git a/src/parse/tokenstream.hpp b/src/parse/tokenstream.hpp index a9d325c2..25b6a3c1 100644 --- a/src/parse/tokenstream.hpp +++ b/src/parse/tokenstream.hpp @@ -16,6 +16,7 @@  namespace AST {      class Module; +    class Crate;      class AttributeList;  } @@ -27,6 +28,7 @@ struct ParseState      // A debugging hook that disables expansion of macros      bool no_expand_macros = false; +    const ::AST::Crate* crate = nullptr;      ::AST::Module*  module = nullptr;      ::AST::AttributeList*   parent_attrs = nullptr; | 
