summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@mutabah.net>2018-07-29 12:47:44 +0100
committerJohn Hodge <tpg@mutabah.net>2018-07-29 12:47:44 +0100
commitc971a6fa8375598ecf9c99ee6b086e8cf957f568 (patch)
treef7f431cbac52e6b25d311bedd503b6584c51bd37
parent5d4bf9e96d795623f1b32b2f1f2e57c4f74419fe (diff)
downloadmrust-c971a6fa8375598ecf9c99ee6b086e8cf957f568.tar.gz
All - Initial work on supporting 1.29 as a target version
-rw-r--r--Makefile1
-rw-r--r--rust-nightly-date2
-rw-r--r--src/ast/ast.hpp5
-rw-r--r--src/ast/attrs.hpp1
-rw-r--r--src/ast/path.hpp4
-rw-r--r--src/expand/assert.cpp89
-rw-r--r--src/expand/file_line.cpp9
-rw-r--r--src/expand/lang_item.cpp15
-rw-r--r--src/expand/mod.cpp19
-rw-r--r--src/hir/from_ast.cpp6
-rw-r--r--src/include/main_bindings.hpp1
-rw-r--r--src/macro_rules/eval.cpp4
-rw-r--r--src/macro_rules/parse.cpp14
-rw-r--r--src/main.cpp2
-rw-r--r--src/parse/eTokenType.enum.h1
-rw-r--r--src/parse/expr.cpp9
-rw-r--r--src/parse/lex.cpp8
-rw-r--r--src/parse/pattern.cpp5
-rw-r--r--src/parse/root.cpp73
-rw-r--r--src/parse/token.cpp11
-rw-r--r--src/parse/tokenstream.hpp2
21 files changed, 251 insertions, 30 deletions
diff --git a/Makefile b/Makefile
index 256bb6c6..5b21f186 100644
--- a/Makefile
+++ b/Makefile
@@ -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;