summaryrefslogtreecommitdiff
path: root/src/parse/root.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/parse/root.cpp')
-rw-r--r--src/parse/root.cpp231
1 files changed, 129 insertions, 102 deletions
diff --git a/src/parse/root.cpp b/src/parse/root.cpp
index 8fa72fb3..68ad570b 100644
--- a/src/parse/root.cpp
+++ b/src/parse/root.cpp
@@ -41,10 +41,10 @@ Spanned<T> get_spanned(TokenStream& lex, ::std::function<T()> f) {
return input;
}
-AST::MetaItems Parse_ItemAttrs(TokenStream& lex);
-void Parse_ParentAttrs(TokenStream& lex, AST::MetaItems& out);
-AST::MetaItem Parse_MetaItem(TokenStream& lex);
-void Parse_ModRoot(TokenStream& lex, AST::Module& mod, AST::MetaItems& mod_attrs);
+AST::AttributeList Parse_ItemAttrs(TokenStream& lex);
+void Parse_ParentAttrs(TokenStream& lex, AST::AttributeList& out);
+AST::Attribute Parse_MetaItem(TokenStream& lex);
+void Parse_ModRoot(TokenStream& lex, AST::Module& mod, AST::AttributeList& mod_attrs);
bool Parse_MacroInvocation_Opt(TokenStream& lex, AST::MacroInvocation& out_inv);
//::AST::Path Parse_Publicity(TokenStream& lex)
@@ -119,31 +119,55 @@ bool Parse_Publicity(TokenStream& lex, bool allow_restricted=true)
}
}
-::std::vector< ::std::string> Parse_HRB(TokenStream& lex)
+::AST::HigherRankedBounds Parse_HRB(TokenStream& lex)
{
TRACE_FUNCTION;
Token tok;
- ::std::vector< ::std::string> lifetimes;
+ ::AST::HigherRankedBounds rv;
GET_CHECK_TOK(tok, lex, TOK_LT);
do {
- ::AST::MetaItems attrs = Parse_ItemAttrs(lex);
- (void)attrs; // TODO: Attributes on generic params
+ // Support empty lists and comma-terminated lists
+ if( lex.lookahead(0) == TOK_GT ) {
+ GET_TOK(tok, lex);
+ break;
+ }
+ auto attrs = Parse_ItemAttrs(lex);
switch(GET_TOK(tok, lex))
{
case TOK_LIFETIME:
- lifetimes.push_back(tok.str());
+ rv.m_lifetimes.push_back(::AST::LifetimeParam(lex.point_span(), ::std::move(attrs), Ident(lex.getHygiene(), tok.str())));
break;
default:
throw ParseError::Unexpected(lex, tok, Token(TOK_LIFETIME));
}
} while( GET_TOK(tok, lex) == TOK_COMMA );
CHECK_TOK(tok, TOK_GT);
- return lifetimes;
+ return rv;
+}
+::AST::HigherRankedBounds Parse_HRB_Opt(TokenStream& lex)
+{
+ if( lex.lookahead(0) == TOK_RWORD_FOR )
+ {
+ lex.getToken(); // Consume
+ return Parse_HRB(lex);
+ }
+ else
+ {
+ return ::AST::HigherRankedBounds();
+ }
+}
+
+namespace {
+ AST::LifetimeRef get_LifetimeRef(TokenStream& lex, Token tok)
+ {
+ CHECK_TOK(tok, TOK_LIFETIME);
+ return AST::LifetimeRef(/*lex.point_span(), */Ident(lex.getHygiene(), mv$(tok.str())));
+ }
}
/// Parse type parameters in a definition
-void Parse_TypeBound(TokenStream& lex, AST::GenericParams& ret, TypeRef checked_type, ::std::vector< ::std::string> lifetimes = {})
+void Parse_TypeBound(TokenStream& lex, AST::GenericParams& ret, TypeRef checked_type, AST::HigherRankedBounds outer_hrbs = {})
{
TRACE_FUNCTION;
Token tok;
@@ -156,29 +180,32 @@ void Parse_TypeBound(TokenStream& lex, AST::GenericParams& ret, TypeRef checked_
// return;
//}
- ::std::vector< ::std::string> hrls;
if(GET_TOK(tok, lex) == TOK_LIFETIME) {
ret.add_bound(AST::GenericBound::make_TypeLifetime( {
- checked_type.clone(), tok.str()
+ checked_type.clone(), get_LifetimeRef(lex, mv$(tok))
} ));
}
else if( tok.type() == TOK_QMARK ) {
+ auto hrbs = Parse_HRB_Opt(lex);
+ (void)hrbs; // The only valid ?Trait is Sized, which doesn't have any generics
ret.add_bound(AST::GenericBound::make_MaybeTrait( {
checked_type.clone(), Parse_Path(lex, PATH_GENERIC_TYPE)
} ));
}
else {
+ ::AST::HigherRankedBounds inner_hrls;
if( tok.type() == TOK_RWORD_FOR )
{
- hrls = Parse_HRB(lex);
+ inner_hrls = Parse_HRB(lex);
}
else {
PUTBACK(tok, lex);
}
- (void)hrls; // TODO: HRLs
+ auto trait_path = Parse_Path(lex, PATH_GENERIC_TYPE);
+ auto this_outer_hrbs = (lex.lookahead(0) == TOK_PLUS ? AST::HigherRankedBounds(outer_hrbs) : mv$(outer_hrbs));
ret.add_bound( AST::GenericBound::make_IsTrait({
- checked_type.clone(), mv$(lifetimes), Parse_Path(lex, PATH_GENERIC_TYPE)
+ mv$(this_outer_hrbs), checked_type.clone(), mv$(inner_hrls), mv$(trait_path)
}) );
}
} while( GET_TOK(tok, lex) == TOK_PLUS );
@@ -198,15 +225,13 @@ AST::GenericParams Parse_GenericParams(TokenStream& lex)
}
PUTBACK(tok, lex);
- ::AST::MetaItems attrs = Parse_ItemAttrs(lex);
- (void)attrs; // TODO: Attributes on generic params
+ auto attrs = Parse_ItemAttrs(lex);
GET_TOK(tok, lex);
if( tok.type() == TOK_IDENT )
{
- // TODO: Hygine
::std::string param_name = mv$(tok.str());
- ret.add_ty_param( AST::TypeParam( param_name ) );
+ ret.add_ty_param( AST::TypeParam( lex.point_span(), ::std::move(attrs), param_name ) );
auto param_ty = TypeRef(lex.point_span(), param_name);
if( GET_TOK(tok, lex) == TOK_COLON )
@@ -223,14 +248,14 @@ AST::GenericParams Parse_GenericParams(TokenStream& lex)
}
else if( tok.type() == TOK_LIFETIME )
{
- // TODO: Should lifetimes have hygine?
- ::std::string param_name = tok.str();
- ret.add_lft_param( param_name );
+ auto param_name = tok.str();
+ auto ref = get_LifetimeRef(lex, mv$(tok));
+ ret.add_lft_param(::AST::LifetimeParam(lex.point_span(), ::std::move(attrs), Ident(lex.getHygiene(), param_name) ));
if( GET_TOK(tok, lex) == TOK_COLON )
{
do {
GET_CHECK_TOK(tok, lex, TOK_LIFETIME);
- ret.add_bound(AST::GenericBound::make_Lifetime( {param_name, tok.str()} ));
+ ret.add_bound(AST::GenericBound::make_Lifetime({ AST::LifetimeRef(ref), get_LifetimeRef(lex, mv$(tok)) }));
} while( GET_TOK(tok, lex) == TOK_PLUS );
}
}
@@ -258,11 +283,11 @@ void Parse_WhereClause(TokenStream& lex, AST::GenericParams& params)
if( tok.type() == TOK_LIFETIME )
{
- auto lhs = mv$(tok.str());
+ auto lhs = get_LifetimeRef(lex, mv$(tok));
GET_CHECK_TOK(tok, lex, TOK_COLON);
do {
GET_CHECK_TOK(tok, lex, TOK_LIFETIME);
- auto rhs = mv$(tok.str());
+ auto rhs = get_LifetimeRef(lex, mv$(tok));
params.add_bound( AST::GenericBound::make_Lifetime({lhs, rhs}) );
} while( GET_TOK(tok, lex) == TOK_PLUS );
PUTBACK(tok, lex);
@@ -270,11 +295,11 @@ void Parse_WhereClause(TokenStream& lex, AST::GenericParams& params)
// Higher-ranked types/lifetimes
else if( tok.type() == TOK_RWORD_FOR )
{
- ::std::vector< ::std::string> lifetimes = Parse_HRB(lex);
+ auto hrbs = Parse_HRB(lex);
TypeRef type = Parse_Type(lex);
GET_CHECK_TOK(tok, lex, TOK_COLON);
- Parse_TypeBound(lex,params, mv$(type), mv$(lifetimes));
+ Parse_TypeBound(lex,params, mv$(type), mv$(hrbs));
}
else
{
@@ -346,38 +371,32 @@ AST::Function Parse_FunctionDef(TokenStream& lex, ::std::string abi, bool allow_
if( tok.type() == TOK_AMP )
{
// By-reference method?
- // TODO: If a lifetime is seen (and not a prototype), it is definitely a self binding
unsigned int ofs = 0;
+ // Handle a lifetime parameter name
if( lex.lookahead(0) == TOK_LIFETIME )
ofs ++;
if( lex.lookahead(ofs) == TOK_RWORD_SELF || (lex.lookahead(ofs) == TOK_RWORD_MUT && lex.lookahead(ofs+1) == TOK_RWORD_SELF) )
{
auto ps = lex.start_span();
- ::std::string lifetime;
+ AST::LifetimeRef lifetime;
if( GET_TOK(tok, lex) == TOK_LIFETIME ) {
- lifetime = tok.str();
+ lifetime = get_LifetimeRef(lex, mv$(tok));
GET_TOK(tok, lex);
}
- auto ty_sp = lex.end_span(ps);
+ bool is_mut = false;
if( tok.type() == TOK_RWORD_MUT )
{
- GET_CHECK_TOK(tok, lex, TOK_RWORD_SELF);
- args.push_back( ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "self"), TypeRef(TypeRef::TagReference(), ty_sp, true, TypeRef(ty_sp, "Self", 0xFFFF))) );
- }
- else
- {
- args.push_back( ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "self"), TypeRef(TypeRef::TagReference(), ty_sp, false, TypeRef(ty_sp, "Self", 0xFFFF))) );
+ is_mut = true;
+ GET_TOK(tok, lex);
}
- DEBUG("TODO: UFCS / self lifetimes");
+ CHECK_TOK(tok, TOK_RWORD_SELF);
+ auto sp = lex.end_span(ps);
+ args.push_back( ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), sp, "self"), TypeRef(TypeRef::TagReference(), sp, ::std::move(lifetime), is_mut, TypeRef(sp, "Self", 0xFFFF))) );
if( allow_self == false )
throw ParseError::Generic(lex, "Self binding not expected");
- //args.push_back( ::std::make_pair(
- // AST::Pattern(),
- // TypeRef(TypeRef::TagReference(), lifetime, (fcn_class == AST::Function::CLASS_MUTMETHOD), )
- //) );
// Prime tok for next step
GET_TOK(tok, lex);
@@ -394,6 +413,7 @@ AST::Function Parse_FunctionDef(TokenStream& lex, ::std::string abi, bool allow_
GET_TOK(tok, lex);
if( allow_self == false )
throw ParseError::Generic(lex, "Self binding not expected");
+ auto binding_sp = lex.end_span(ps);
TypeRef ty = TypeRef( lex.point_span(), "Self", 0xFFFF );
if( GET_TOK(tok, lex) == TOK_COLON ) {
// Typed mut self
@@ -402,7 +422,7 @@ AST::Function Parse_FunctionDef(TokenStream& lex, ::std::string abi, bool allow_
else {
PUTBACK(tok, lex);
}
- args.push_back( ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "self"), mv$(ty)) );
+ args.push_back( ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), binding_sp, "self"), mv$(ty)) );
GET_TOK(tok, lex);
}
}
@@ -411,6 +431,7 @@ AST::Function Parse_FunctionDef(TokenStream& lex, ::std::string abi, bool allow_
// By-value method
if( allow_self == false )
throw ParseError::Generic(lex, "Self binding not expected");
+ auto binding_sp = lex.end_span(ps);
TypeRef ty = TypeRef( lex.point_span(), "Self", 0xFFFF );
if( GET_TOK(tok, lex) == TOK_COLON ) {
// Typed mut self
@@ -419,7 +440,7 @@ AST::Function Parse_FunctionDef(TokenStream& lex, ::std::string abi, bool allow_
else {
PUTBACK(tok, lex);
}
- args.push_back( ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), "self"), mv$(ty)) );
+ args.push_back( ::std::make_pair( AST::Pattern(AST::Pattern::TagBind(), binding_sp, "self"), mv$(ty)) );
GET_TOK(tok, lex);
}
else
@@ -486,7 +507,7 @@ AST::Function Parse_FunctionDefWithCode(TokenStream& lex, ::std::string abi, boo
Token tok;
auto ret = Parse_FunctionDef(lex, abi, allow_self, false, is_unsafe, is_const);
GET_CHECK_TOK(tok, lex, TOK_BRACE_OPEN);
- // Enter a new hygine scope (TODO: Should this be in Parse_ExprBlock?)
+ // Enter a new hygine scope for the function (TODO: Should this be in Parse_ExprBlock?)
lex.push_hygine();
PUTBACK(tok, lex);
ret.set_code( Parse_ExprBlock(lex) );
@@ -523,7 +544,7 @@ AST::TypeAlias Parse_TypeAlias(TokenStream& lex)
return AST::TypeAlias( ::std::move(params), ::std::move(type) );
}
-AST::Struct Parse_Struct(TokenStream& lex, const AST::MetaItems& meta_items)
+AST::Struct Parse_Struct(TokenStream& lex, const AST::AttributeList& meta_items)
{
TRACE_FUNCTION;
@@ -547,7 +568,7 @@ AST::Struct Parse_Struct(TokenStream& lex, const AST::MetaItems& meta_items)
::std::vector<AST::TupleItem> refs;
while(lex.lookahead(0) != TOK_PAREN_CLOSE)
{
- AST::MetaItems item_attrs = Parse_ItemAttrs(lex);
+ auto item_attrs = Parse_ItemAttrs(lex);
SET_ATTRS(lex, item_attrs);
bool is_pub = Parse_Publicity(lex, /*allow_restricted=*/false); // HACK: Disable `pub(restricted)` syntax in tuple structs, due to ambiguity
@@ -582,7 +603,7 @@ AST::Struct Parse_Struct(TokenStream& lex, const AST::MetaItems& meta_items)
{
PUTBACK(tok, lex);
- AST::MetaItems item_attrs = Parse_ItemAttrs(lex);
+ auto item_attrs = Parse_ItemAttrs(lex);
SET_ATTRS(lex, item_attrs);
bool is_pub = Parse_Publicity(lex);
@@ -607,7 +628,7 @@ AST::Struct Parse_Struct(TokenStream& lex, const AST::MetaItems& meta_items)
}
}
-AST::Trait Parse_TraitDef(TokenStream& lex, const AST::MetaItems& meta_items)
+AST::Trait Parse_TraitDef(TokenStream& lex, const AST::AttributeList& meta_items)
{
TRACE_FUNCTION;
@@ -622,30 +643,27 @@ AST::Trait Parse_TraitDef(TokenStream& lex, const AST::MetaItems& meta_items)
}
// Trait bounds "trait Trait : 'lifetime + OtherTrait + OtherTrait2"
- ::std::vector<Spanned<AST::Path> > supertraits;
+ ::std::vector<Spanned<Type_TraitPath> > supertraits;
if(tok.type() == TOK_COLON)
{
+ // 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
- supertraits.push_back( make_spanned( Span(tok.get_pos()), AST::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() } ) );
}
else if( tok.type() == TOK_BRACE_OPEN ) {
break;
}
else {
PUTBACK(tok, lex);
- if( LOOK_AHEAD(lex) == TOK_RWORD_FOR )
- {
- GET_TOK(tok, lex);
- /*::std::vector< ::std::string> lifetimes =*/ Parse_HRB(lex);
- }
- supertraits.push_back( GET_SPANNED(::AST::Path, lex, Parse_Path(lex, PATH_GENERIC_TYPE)) );
+ auto hrbs = Parse_HRB_Opt(lex);
+ supertraits.push_back( GET_SPANNED(Type_TraitPath, lex, (Type_TraitPath{ mv$(hrbs), Parse_Path(lex, PATH_GENERIC_TYPE) })) );
}
} while( GET_TOK(tok, lex) == TOK_PLUS );
}
- // TODO: Support "for Sized?"
if(tok.type() == TOK_RWORD_WHERE)
{
//if( params.ty_params().size() == 0 )
@@ -662,7 +680,7 @@ AST::Trait Parse_TraitDef(TokenStream& lex, const AST::MetaItems& meta_items)
{
PUTBACK(tok, lex);
- AST::MetaItems item_attrs = Parse_ItemAttrs(lex);
+ auto item_attrs = Parse_ItemAttrs(lex);
SET_ATTRS(lex, item_attrs);
auto ps = lex.start_span();
@@ -747,7 +765,6 @@ AST::Trait Parse_TraitDef(TokenStream& lex, const AST::MetaItems& meta_items)
break; }
// Functions (possibly unsafe)
- // TODO: Const?
case TOK_RWORD_UNSAFE:
fn_is_unsafe = true;
if( GET_TOK(tok, lex) == TOK_RWORD_EXTERN )
@@ -770,8 +787,7 @@ AST::Trait Parse_TraitDef(TokenStream& lex, const AST::MetaItems& meta_items)
if( GET_TOK(tok, lex) == TOK_BRACE_OPEN )
{
PUTBACK(tok, lex);
- // Enter a new hygine scope for the function body.
- // - TODO: Should this just happen in Parse_ExprBlock?
+ // Enter a new hygine scope for the function body. (TODO: Should this be in Parse_ExprBlock?)
lex.push_hygine();
fcn.set_code( Parse_ExprBlock(lex) );
lex.pop_hygine();
@@ -784,7 +800,6 @@ AST::Trait Parse_TraitDef(TokenStream& lex, const AST::MetaItems& meta_items)
{
throw ParseError::Unexpected(lex, tok);
}
- // TODO: Store `item_attrs`
trait.add_function( ::std::move(name), mv$(item_attrs), ::std::move(fcn) );
break; }
default:
@@ -795,7 +810,7 @@ AST::Trait Parse_TraitDef(TokenStream& lex, const AST::MetaItems& meta_items)
return trait;
}
-AST::Enum Parse_EnumDef(TokenStream& lex, const AST::MetaItems& meta_items)
+AST::Enum Parse_EnumDef(TokenStream& lex, const AST::AttributeList& meta_items)
{
TRACE_FUNCTION;
@@ -823,7 +838,7 @@ AST::Enum Parse_EnumDef(TokenStream& lex, const AST::MetaItems& meta_items)
auto sp = lex.start_span();
PUTBACK(tok, lex);
- AST::MetaItems item_attrs = Parse_ItemAttrs(lex);
+ auto item_attrs = Parse_ItemAttrs(lex);
SET_ATTRS(lex, item_attrs);
GET_CHECK_TOK(tok, lex, TOK_IDENT);
@@ -841,8 +856,8 @@ AST::Enum Parse_EnumDef(TokenStream& lex, const AST::MetaItems& meta_items)
break;
}
- AST::MetaItems field_attrs = Parse_ItemAttrs(lex);
- (void)field_attrs; // TODO^
+ auto field_attrs = Parse_ItemAttrs(lex);
+ (void)field_attrs; // TODO: Store field_attrs
types.push_back( Parse_Type(lex) );
} while( GET_TOK(tok, lex) == TOK_COMMA );
@@ -862,7 +877,7 @@ AST::Enum Parse_EnumDef(TokenStream& lex, const AST::MetaItems& meta_items)
break;
}
- AST::MetaItems field_attrs = Parse_ItemAttrs(lex);
+ auto field_attrs = Parse_ItemAttrs(lex);
GET_CHECK_TOK(tok, lex, TOK_IDENT);
auto name = mv$(tok.str());
@@ -897,7 +912,7 @@ AST::Enum Parse_EnumDef(TokenStream& lex, const AST::MetaItems& meta_items)
return AST::Enum( mv$(params), mv$(variants) );
}
-::AST::Union Parse_Union(TokenStream& lex, AST::MetaItems& meta_items)
+::AST::Union Parse_Union(TokenStream& lex, AST::AttributeList& meta_items)
{
Token tok;
@@ -924,7 +939,7 @@ AST::Enum Parse_EnumDef(TokenStream& lex, const AST::MetaItems& meta_items)
break ;
}
- AST::MetaItems item_attrs = Parse_ItemAttrs(lex);
+ auto item_attrs = Parse_ItemAttrs(lex);
SET_ATTRS(lex, item_attrs);
bool is_pub = Parse_Publicity(lex);
@@ -943,9 +958,9 @@ AST::Enum Parse_EnumDef(TokenStream& lex, const AST::MetaItems& meta_items)
return ::AST::Union( mv$(params), mv$(variants) );
}
-AST::MetaItems Parse_ItemAttrs(TokenStream& lex)
+AST::AttributeList Parse_ItemAttrs(TokenStream& lex)
{
- AST::MetaItems rv;
+ AST::AttributeList rv;
Token tok;
while( lex.lookahead(0) == TOK_HASH )
{
@@ -956,7 +971,7 @@ AST::MetaItems Parse_ItemAttrs(TokenStream& lex)
}
return rv;
}
-void Parse_ParentAttrs(TokenStream& lex, AST::MetaItems& out)
+void Parse_ParentAttrs(TokenStream& lex, AST::AttributeList& out)
{
Token tok;
while( lex.lookahead(0) == TOK_HASH && lex.lookahead(1) == TOK_EXCLAM )
@@ -969,7 +984,7 @@ void Parse_ParentAttrs(TokenStream& lex, AST::MetaItems& out)
}
}
/// Parse a meta-item declaration (either #![ or #[)
-AST::MetaItem Parse_MetaItem(TokenStream& lex)
+AST::Attribute Parse_MetaItem(TokenStream& lex)
{
TRACE_FUNCTION;
Token tok;
@@ -979,6 +994,7 @@ AST::MetaItem Parse_MetaItem(TokenStream& lex)
return mv$(tok.frag_meta());
}
+ auto ps = lex.start_span();
CHECK_TOK(tok, TOK_IDENT);
::std::string name = mv$(tok.str());
switch(GET_TOK(tok, lex))
@@ -987,24 +1003,26 @@ AST::MetaItem Parse_MetaItem(TokenStream& lex)
switch(GET_TOK(tok, lex))
{
case TOK_STRING:
- return AST::MetaItem(name, tok.str());
+ return AST::Attribute(lex.end_span(ps), name, tok.str());
case TOK_INTERPOLATED_EXPR: {
auto n = tok.take_frag_node();
if( auto* v = dynamic_cast<::AST::ExprNode_String*>(&*n) )
{
- return AST::MetaItem(name, mv$(v->m_value));
+ return AST::Attribute(lex.end_span(ps), name, mv$(v->m_value));
}
else
{
+ // - Force an error.
CHECK_TOK(tok, TOK_STRING);
}
break; }
default:
+ // - Force an error.
CHECK_TOK(tok, TOK_STRING);
}
throw "";
case TOK_PAREN_OPEN: {
- ::std::vector<AST::MetaItem> items;
+ ::std::vector<AST::Attribute> items;
do {
if(LOOK_AHEAD(lex) == TOK_PAREN_CLOSE) {
GET_TOK(tok, lex);
@@ -1013,14 +1031,14 @@ AST::MetaItem Parse_MetaItem(TokenStream& lex)
items.push_back(Parse_MetaItem(lex));
} while(GET_TOK(tok, lex) == TOK_COMMA);
CHECK_TOK(tok, TOK_PAREN_CLOSE);
- return AST::MetaItem(name, mv$(items)); }
+ return AST::Attribute(lex.end_span(ps), name, mv$(items)); }
default:
PUTBACK(tok, lex);
- return AST::MetaItem(name);
+ return AST::Attribute(lex.end_span(ps), name);
}
}
-::AST::Item Parse_Impl(TokenStream& lex, AST::MetaItems attrs, bool is_unsafe=false)
+::AST::Item Parse_Impl(TokenStream& lex, AST::AttributeList attrs, bool is_unsafe=false)
{
TRACE_FUNCTION;
Token tok;
@@ -1057,7 +1075,7 @@ AST::MetaItem Parse_MetaItem(TokenStream& lex)
// negative impls can't have any content
GET_CHECK_TOK(tok, lex, TOK_BRACE_CLOSE);
- return ::AST::Item::make_NegImpl( AST::ImplDef(lex.end_span(ps), mv$(attrs), mv$(params), mv$(trait_path), mv$(impl_type) ) );
+ return ::AST::Item::make_NegImpl(AST::ImplDef( mv$(attrs), mv$(params), mv$(trait_path), mv$(impl_type) ));
}
// - Don't care which at this stage
@@ -1102,7 +1120,7 @@ AST::MetaItem Parse_MetaItem(TokenStream& lex)
Parse_ParentAttrs(lex, attrs);
- AST::Impl impl( AST::ImplDef( lex.end_span(ps), mv$(attrs), mv$(params), mv$(trait_path), mv$(impl_type) ) );
+ auto impl = AST::Impl(AST::ImplDef( mv$(attrs), mv$(params), mv$(trait_path), mv$(impl_type) ));
// A sequence of method implementations
while( lex.lookahead(0) != TOK_BRACE_CLOSE )
@@ -1119,7 +1137,7 @@ void Parse_Impl_Item(TokenStream& lex, AST::Impl& impl)
TRACE_FUNCTION;
Token tok;
- AST::MetaItems item_attrs = Parse_ItemAttrs(lex);
+ auto item_attrs = Parse_ItemAttrs(lex);
SET_ATTRS(lex, item_attrs);
{
@@ -1173,8 +1191,7 @@ void Parse_Impl_Item(TokenStream& lex, AST::Impl& impl)
GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
auto i = ::AST::Static(AST::Static::CONST, mv$(ty), mv$(val));
- // TODO: Attributes on associated constants
- impl.add_static( is_public, is_specialisable, mv$(name), mv$(i) /*, mv$(item_attrs)*/ );
+ impl.add_static( is_public, is_specialisable, mv$(name), mv$(i) );
break ;
}
else if( tok.type() == TOK_RWORD_UNSAFE )
@@ -1216,7 +1233,7 @@ void Parse_Impl_Item(TokenStream& lex, AST::Impl& impl)
impl.items().back().data->attrs = mv$(item_attrs); // Empty for functions
}
-AST::ExternBlock Parse_ExternBlock(TokenStream& lex, ::std::string abi, ::AST::MetaItems& block_attrs)
+AST::ExternBlock Parse_ExternBlock(TokenStream& lex, ::std::string abi, ::AST::AttributeList& block_attrs)
{
TRACE_FUNCTION;
Token tok;
@@ -1228,7 +1245,7 @@ AST::ExternBlock Parse_ExternBlock(TokenStream& lex, ::std::string abi, ::AST::M
while( GET_TOK(tok, lex) != TOK_BRACE_CLOSE )
{
PUTBACK(tok, lex);
- AST::MetaItems meta_items = Parse_ItemAttrs(lex);
+ auto meta_items = Parse_ItemAttrs(lex);
SET_ATTRS(lex, meta_items);
auto ps = lex.start_span();
@@ -1452,7 +1469,7 @@ bool Parse_MacroInvocation_Opt(TokenStream& lex, AST::MacroInvocation& out_inv)
return true;
}
-::AST::Named<::AST::Item> Parse_Mod_Item_S(TokenStream& lex, const AST::Module::FileInfo& mod_fileinfo, const ::AST::Path& mod_path, AST::MetaItems meta_items)
+::AST::Named<::AST::Item> Parse_Mod_Item_S(TokenStream& lex, const AST::Module::FileInfo& mod_fileinfo, const ::AST::Path& mod_path, AST::AttributeList meta_items)
{
TRACE_FUNCTION_F("mod_path="<<mod_path<<", meta_items="<<meta_items);
Token tok;
@@ -1644,7 +1661,6 @@ bool Parse_MacroInvocation_Opt(TokenStream& lex, AST::MacroInvocation& out_inv)
// `unsafe trait`
// `unsafe impl`
case TOK_RWORD_UNSAFE:
- meta_items.push_back( AST::MetaItem("#UNSAFE") );
switch(GET_TOK(tok, lex))
{
// `unsafe extern fn`
@@ -1669,16 +1685,27 @@ bool Parse_MacroInvocation_Opt(TokenStream& lex, AST::MacroInvocation& out_inv)
item_data = ::AST::Item( Parse_FunctionDefWithCode(lex, ABI_RUST, false, true,false/*unsafe,const*/) );
break;
// `unsafe trait`
- case TOK_RWORD_TRAIT:
+ case TOK_RWORD_TRAIT: {
GET_CHECK_TOK(tok, lex, TOK_IDENT);
item_name = mv$(tok.str());
- // TODO: Mark as unsafe
- meta_items.push_back( AST::MetaItem("#UNSAFE") );
- item_data = ::AST::Item( Parse_TraitDef(lex, meta_items) );
- break;
+ auto tr = Parse_TraitDef(lex, meta_items);
+ tr.set_is_unsafe();
+ item_data = ::AST::Item( ::std::move(tr) );
+ break; }
// `unsafe impl`
- case TOK_RWORD_IMPL:
- return ::AST::Named< ::AST::Item> { "", Parse_Impl(lex, mv$(meta_items), true), false };
+ case TOK_RWORD_IMPL: {
+ auto impl = Parse_Impl(lex, mv$(meta_items), true);
+ if( impl.is_Impl() ) {
+ impl.as_Impl().def().set_is_unsafe();
+ }
+ else if( impl.is_NegImpl() ) {
+ impl.as_NegImpl().set_is_unsafe();
+ }
+ else {
+ BUG(lex.point_span(), "Parse_Impl returned a variant other than Impl or NegImpl");
+ }
+ return ::AST::Named< ::AST::Item> { "", mv$(impl), false };
+ }
default:
throw ParseError::Unexpected(lex, tok, {TOK_RWORD_FN, TOK_RWORD_TRAIT, TOK_RWORD_IMPL});
}
@@ -1772,10 +1799,10 @@ bool Parse_MacroInvocation_Opt(TokenStream& lex, AST::MacroInvocation& out_inv)
// Check #[cfg] and don't load if it fails
struct H {
- static bool check_item_cfg(const ::AST::MetaItems& attrs)
+ static bool check_item_cfg(const ::AST::AttributeList& attrs)
{
for(const auto& at : attrs.m_items) {
- if( at.name() == "cfg" && !check_cfg(attrs.m_span, at) ) {
+ if( at.name() == "cfg" && !check_cfg(at.span(), at) ) {
return false;
}
}
@@ -1853,7 +1880,7 @@ bool Parse_MacroInvocation_Opt(TokenStream& lex, AST::MacroInvocation& out_inv)
return ::AST::Named< ::AST::Item> { mv$(item_name), mv$(item_data), is_public };
}
-void Parse_Mod_Item(TokenStream& lex, AST::Module& mod, AST::MetaItems meta_items)
+void Parse_Mod_Item(TokenStream& lex, AST::Module& mod, AST::AttributeList meta_items)
{
SET_MODULE(lex, mod);
lex.parse_state().parent_attrs = &meta_items;
@@ -1899,14 +1926,14 @@ void Parse_ModRoot_Items(TokenStream& lex, AST::Module& mod)
}
// Attributes on the following item
- AST::MetaItems meta_items = Parse_ItemAttrs(lex);
+ auto meta_items = Parse_ItemAttrs(lex);
DEBUG("meta_items = " << meta_items);
Parse_Mod_Item(lex, mod, mv$(meta_items));
}
}
-void Parse_ModRoot(TokenStream& lex, AST::Module& mod, AST::MetaItems& mod_attrs)
+void Parse_ModRoot(TokenStream& lex, AST::Module& mod, AST::AttributeList& mod_attrs)
{
TRACE_FUNCTION;