diff options
author | John Hodge <tpg@mutabah.net> | 2018-05-20 22:01:59 +0800 |
---|---|---|
committer | John Hodge <tpg@mutabah.net> | 2018-05-20 22:01:59 +0800 |
commit | de9ecd7a2d70359b34e77ded57e5aa9284345ac5 (patch) | |
tree | 29ab42c6c06960720bd67f0b8ebaec807ad0284e /src/parse | |
parent | 134be5198993096ab5216b6d52a8937430c733b0 (diff) | |
download | mrust-de9ecd7a2d70359b34e77ded57e5aa9284345ac5.tar.gz |
AST - Refactor lifetime/HRB handling
Diffstat (limited to 'src/parse')
-rw-r--r-- | src/parse/common.hpp | 2 | ||||
-rw-r--r-- | src/parse/paths.cpp | 4 | ||||
-rw-r--r-- | src/parse/root.cpp | 52 | ||||
-rw-r--r-- | src/parse/tokenstream.cpp | 4 | ||||
-rw-r--r-- | src/parse/types.cpp | 77 |
5 files changed, 85 insertions, 54 deletions
diff --git a/src/parse/common.hpp b/src/parse/common.hpp index 1ca86128..49499c86 100644 --- a/src/parse/common.hpp +++ b/src/parse/common.hpp @@ -40,7 +40,7 @@ extern ::std::vector<AST::PathNode> Parse_PathNodes(TokenStream& lex, eParsePath extern AST::PathParams Parse_Path_GenericList(TokenStream& lex); -extern ::std::vector< ::std::string> Parse_HRB(TokenStream& lex); +extern AST::HigherRankedBounds Parse_HRB(TokenStream& lex); extern AST::AttributeList Parse_ItemAttrs(TokenStream& lex); extern void Parse_ParentAttrs(TokenStream& lex, AST::AttributeList& out); extern AST::Attribute Parse_MetaItem(TokenStream& lex); diff --git a/src/parse/paths.cpp b/src/parse/paths.cpp index 59b6b939..d103840e 100644 --- a/src/parse/paths.cpp +++ b/src/parse/paths.cpp @@ -203,7 +203,7 @@ AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generi Token tok; ::std::vector<TypeRef> types; - ::std::vector< ::std::string> lifetimes; + ::std::vector<AST::LifetimeRef> lifetimes; ::std::vector< ::std::pair< ::std::string, TypeRef > > assoc_bounds; do { @@ -214,7 +214,7 @@ AST::Path Parse_Path(TokenStream& lex, bool is_abs, eParsePathGenericMode generi switch(GET_TOK(tok, lex)) { case TOK_LIFETIME: - lifetimes.push_back( tok.str() ); + lifetimes.push_back(AST::LifetimeRef(/*lex.point_span(),*/ lex.get_ident(mv$(tok)) )); break; case TOK_IDENT: if( LOOK_AHEAD(lex) == TOK_EQUAL ) diff --git a/src/parse/root.cpp b/src/parse/root.cpp index 35da3a76..2b027bf9 100644 --- a/src/parse/root.cpp +++ b/src/parse/root.cpp @@ -119,12 +119,12 @@ 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 { auto attrs = Parse_ItemAttrs(lex); @@ -133,17 +133,25 @@ bool Parse_Publicity(TokenStream& lex, bool allow_restricted=true) 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; +} + +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,10 +164,9 @@ 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 ) { @@ -168,17 +175,17 @@ void Parse_TypeBound(TokenStream& lex, AST::GenericParams& ret, TypeRef checked_ } )); } 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 ret.add_bound( AST::GenericBound::make_IsTrait({ - checked_type.clone(), mv$(lifetimes), Parse_Path(lex, PATH_GENERIC_TYPE) + mv$(outer_hrbs), checked_type.clone(), mv$(inner_hrls), Parse_Path(lex, PATH_GENERIC_TYPE) }) ); } } while( GET_TOK(tok, lex) == TOK_PLUS ); @@ -199,14 +206,12 @@ AST::GenericParams Parse_GenericParams(TokenStream& lex) PUTBACK(tok, lex); auto attrs = Parse_ItemAttrs(lex); - (void)attrs; // TODO: Attributes on generic params 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 +228,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 +263,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 +275,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 { @@ -355,9 +360,9 @@ AST::Function Parse_FunctionDef(TokenStream& lex, ::std::string abi, bool allow_ 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); @@ -622,6 +627,7 @@ AST::Trait Parse_TraitDef(TokenStream& lex, const AST::AttributeList& meta_items do { if( GET_TOK(tok, lex) == TOK_LIFETIME ) { // TODO: Need a better way of indiciating 'static than just an invalid path + // TODO: Ensure that it's 'static supertraits.push_back( make_spanned( Span(tok.get_pos()), AST::Path() ) ); } else if( tok.type() == TOK_BRACE_OPEN ) { diff --git a/src/parse/tokenstream.cpp b/src/parse/tokenstream.cpp index 625f12db..611df2ff 100644 --- a/src/parse/tokenstream.cpp +++ b/src/parse/tokenstream.cpp @@ -140,6 +140,10 @@ Ident TokenStream::get_ident(Token tok) const if(tok.type() == TOK_IDENT) { return Ident(getHygiene(), tok.str()); } + else if(tok.type() == TOK_LIFETIME) { + // TODO: Maybe only when it's explicitly asked for? + return Ident(getHygiene(), tok.str()); + } else if( tok.type() == TOK_INTERPOLATED_IDENT ) { TODO(getPosition(), "get_ident from TOK_INTERPOLATED_IDENT"); } diff --git a/src/parse/types.cpp b/src/parse/types.cpp index 26785cf7..b0b43426 100644 --- a/src/parse/types.cpp +++ b/src/parse/types.cpp @@ -13,8 +13,8 @@ // === PROTOTYPES === //TypeRef Parse_Type(TokenStream& lex, bool allow_trait_list); TypeRef Parse_Type_Int(TokenStream& lex, bool allow_trait_list); -TypeRef Parse_Type_Fn(TokenStream& lex, ::std::vector<::std::string> hrls = {}); -TypeRef Parse_Type_Path(TokenStream& lex, ::std::vector<::std::string> hrls, bool allow_trait_list); +TypeRef Parse_Type_Fn(TokenStream& lex, AST::HigherRankedBounds hrbs = {}); +TypeRef Parse_Type_Path(TokenStream& lex, AST::HigherRankedBounds hrbs, bool allow_trait_list); TypeRef Parse_Type_ErasedType(TokenStream& lex, bool allow_trait_list); // === CODE === @@ -196,7 +196,7 @@ TypeRef Parse_Type_Int(TokenStream& lex, bool allow_trait_list) throw ParseError::BugCheck("Reached end of Parse_Type"); } -TypeRef Parse_Type_Fn(TokenStream& lex, ::std::vector<::std::string> hrls) +TypeRef Parse_Type_Fn(TokenStream& lex, ::AST::HigherRankedBounds hrbs) { auto ps = lex.start_span(); // TODO: HRLs @@ -262,36 +262,52 @@ TypeRef Parse_Type_Fn(TokenStream& lex, ::std::vector<::std::string> hrls) return TypeRef(TypeRef::TagFunction(), lex.end_span(ps), is_unsafe, mv$(abi), mv$(args), is_variadic, mv$(ret_type)); } -TypeRef Parse_Type_Path(TokenStream& lex, ::std::vector<::std::string> hrls, bool allow_trait_list) +TypeRef Parse_Type_Path(TokenStream& lex, ::AST::HigherRankedBounds hrbs, bool allow_trait_list) { Token tok; auto ps = lex.start_span(); - if( ! allow_trait_list ) + if( hrbs.empty() && !allow_trait_list ) { return TypeRef(TypeRef::TagPath(), lex.end_span(ps), Parse_Path(lex, PATH_GENERIC_TYPE)); } else { - ::std::vector<AST::Path> traits; - ::std::vector< ::std::string> lifetimes; - do { - if( LOOK_AHEAD(lex) == TOK_LIFETIME ) { - GET_TOK(tok, lex); - lifetimes.push_back( tok.str() ); + ::std::vector<Type_TraitPath> traits; + ::std::vector<AST::LifetimeRef> lifetimes; + + traits.push_back(Type_TraitPath { mv$(hrbs), Parse_Path(lex, PATH_GENERIC_TYPE) }); + + if( allow_trait_list ) + { + while( GET_TOK(tok, lex) == TOK_PLUS ) + { + if( LOOK_AHEAD(lex) == TOK_LIFETIME ) { + GET_TOK(tok, lex); + lifetimes.push_back(AST::LifetimeRef( /*lex.point_span(),*/ lex.get_ident(mv$(tok)) )); + } + else + { + if( lex.lookahead(0) == TOK_RWORD_FOR ) + { + hrbs = Parse_HRB(lex); + } + traits.push_back({ mv$(hrbs), Parse_Path(lex, PATH_GENERIC_TYPE) }); + } } - else - traits.push_back( Parse_Path(lex, PATH_GENERIC_TYPE) ); - } while( GET_TOK(tok, lex) == TOK_PLUS ); - PUTBACK(tok, lex); - if( hrls.size() > 0 || traits.size() > 1 || lifetimes.size() > 0 ) { - if( lifetimes.size() ) - DEBUG("TODO: Lifetime bounds on trait objects"); - return TypeRef(lex.end_span(ps), mv$(hrls), ::std::move(traits)); + PUTBACK(tok, lex); } - else { - return TypeRef(TypeRef::TagPath(), lex.end_span(ps), mv$(traits.at(0))); + + if( !traits[0].hrbs.empty() || traits.size() > 1 || lifetimes.size() > 0 ) + { + if( lifetimes.empty()) + lifetimes.push_back(AST::LifetimeRef()); + return TypeRef(lex.end_span(ps), mv$(traits), mv$(lifetimes)); + } + else + { + return TypeRef(TypeRef::TagPath(), lex.end_span(ps), mv$(traits.at(0).path)); } } } @@ -300,20 +316,25 @@ TypeRef Parse_Type_ErasedType(TokenStream& lex, bool allow_trait_list) Token tok; auto ps = lex.start_span(); - ::std::vector<AST::Path> traits; - ::std::vector< ::std::string> lifetimes; + ::std::vector<Type_TraitPath> traits; + ::std::vector<AST::LifetimeRef> lifetimes; do { if( LOOK_AHEAD(lex) == TOK_LIFETIME ) { GET_TOK(tok, lex); - lifetimes.push_back( tok.str() ); + lifetimes.push_back(AST::LifetimeRef( /*lex.point_span(),*/ lex.get_ident(mv$(tok)) )); } else - traits.push_back( Parse_Path(lex, PATH_GENERIC_TYPE) ); + { + AST::HigherRankedBounds hrbs; + if( lex.lookahead(0) == TOK_RWORD_FOR ) + { + hrbs = Parse_HRB(lex); + } + traits.push_back({ mv$(hrbs), Parse_Path(lex, PATH_GENERIC_TYPE) }); + } } while( GET_TOK(tok, lex) == TOK_PLUS ); PUTBACK(tok, lex); - if( lifetimes.size() ) - DEBUG("TODO: Lifetime bounds on erased types"); - return TypeRef(lex.end_span(ps), TypeData::make_ErasedType({ {}, mv$(traits) })); + return TypeRef(lex.end_span(ps), TypeData::make_ErasedType({ mv$(traits), mv$(lifetimes) })); } |