diff options
author | John Hodge <tpg@mutabah.net> | 2018-07-29 12:47:44 +0100 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2018-07-29 12:47:44 +0100 |
commit | c971a6fa8375598ecf9c99ee6b086e8cf957f568 (patch) | |
tree | f7f431cbac52e6b25d311bedd503b6584c51bd37 | |
parent | 5d4bf9e96d795623f1b32b2f1f2e57c4f74419fe (diff) | |
download | mrust-c971a6fa8375598ecf9c99ee6b086e8cf957f568.tar.gz |
All - Initial work on supporting 1.29 as a target version
-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; |