diff options
Diffstat (limited to 'src/parse')
-rw-r--r-- | src/parse/common.hpp | 12 | ||||
-rw-r--r-- | src/parse/expr.cpp | 27 | ||||
-rw-r--r-- | src/parse/interpolated_fragment.cpp | 8 | ||||
-rw-r--r-- | src/parse/interpolated_fragment.hpp | 4 | ||||
-rw-r--r-- | src/parse/paths.cpp | 4 | ||||
-rw-r--r-- | src/parse/pattern.cpp | 80 | ||||
-rw-r--r-- | src/parse/root.cpp | 231 | ||||
-rw-r--r-- | src/parse/token.cpp | 100 | ||||
-rw-r--r-- | src/parse/token.hpp | 20 | ||||
-rw-r--r-- | src/parse/tokenstream.cpp | 6 | ||||
-rw-r--r-- | src/parse/tokenstream.hpp | 4 | ||||
-rw-r--r-- | src/parse/types.cpp | 97 |
12 files changed, 298 insertions, 295 deletions
diff --git a/src/parse/common.hpp b/src/parse/common.hpp index ede08984..49499c86 100644 --- a/src/parse/common.hpp +++ b/src/parse/common.hpp @@ -40,17 +40,17 @@ 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::MetaItems Parse_ItemAttrs(TokenStream& lex); -extern void Parse_ParentAttrs(TokenStream& lex, AST::MetaItems& out); -extern AST::MetaItem Parse_MetaItem(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); extern ::AST::MacroInvocation Parse_MacroInvocation(ProtoSpan ps, ::std::string name, TokenStream& lex); extern TypeRef Parse_Type(TokenStream& lex, bool allow_trait_list = true); extern AST::Pattern Parse_Pattern(TokenStream& lex, bool is_refutable); extern void Parse_Impl_Item(TokenStream& lex, AST::Impl& impl); -extern void Parse_Mod_Item(TokenStream& lex, AST::Module& mod, AST::MetaItems meta_items); -extern ::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); +extern void Parse_Mod_Item(TokenStream& lex, AST::Module& mod, AST::AttributeList meta_items); +extern ::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); extern void Parse_ModRoot_Items(TokenStream& lex, AST::Module& mod); diff --git a/src/parse/expr.cpp b/src/parse/expr.cpp index 2ac13728..5194e1d8 100644 --- a/src/parse/expr.cpp +++ b/src/parse/expr.cpp @@ -20,7 +20,7 @@ using AST::ExprNode; using AST::ExprNodeP; -// TODO: Use a ProtoSpan +// TODO: Use a ProtoSpan instead of a point span? static inline ExprNodeP mk_exprnodep(const TokenStream& lex, AST::ExprNode* en){en->set_span(lex.point_span()); return ExprNodeP(en); } #define NEWNODE(type, ...) mk_exprnodep(lex, new type(__VA_ARGS__)) @@ -66,9 +66,10 @@ ExprNodeP Parse_ExprBlockNode(TokenStream& lex, bool is_unsafe/*=false*/) DEBUG("tok = " << tok); // NOTE: Doc comments can appear within a function and apply to the function - ::AST::MetaItems node_attrs; - Parse_ParentAttrs(lex, node_attrs); - (void)node_attrs; // TODO: Use these attributes + if( lex.parse_state().parent_attrs ) + { + Parse_ParentAttrs(lex, *lex.parse_state().parent_attrs); + } if( LOOK_AHEAD(lex) == TOK_BRACE_CLOSE ) break; @@ -98,7 +99,7 @@ ExprNodeP Parse_ExprBlockLine_WithItems(TokenStream& lex, ::std::shared_ptr<AST: { Token tok; - AST::MetaItems item_attrs = Parse_ItemAttrs(lex); + auto item_attrs = Parse_ItemAttrs(lex); GET_TOK(tok, lex); // `union Ident` - contextual keyword @@ -162,6 +163,7 @@ ExprNodeP Parse_ExprBlockLine_WithItems(TokenStream& lex, ::std::shared_ptr<AST: } else if( item_attrs.m_items.size() > 0 ) { // TODO: Is this an error? - Attributes on a expression that didn't yeild a node. + // - They should have applied to the item that was parsed? } else { } @@ -584,7 +586,7 @@ ExprNodeP Parse_Expr0(TokenStream& lex) //TRACE_FUNCTION; Token tok; - ::AST::MetaItems expr_attrs = Parse_ItemAttrs(lex); + auto expr_attrs = Parse_ItemAttrs(lex); ExprNodeP rv = Parse_Expr1(lex); auto op = AST::ExprNode_Assign::NONE; @@ -740,7 +742,6 @@ ExprNodeP Parse_Expr1_1(TokenStream& lex) return NEWNODE( AST::ExprNode_BinOp, AST::ExprNode_BinOp::RANGE, ::std::move(left), ::std::move(right) ); } -// TODO: Is this left associative? 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) ); @@ -915,8 +916,7 @@ ExprNodeP Parse_ExprFC(TokenStream& lex) GET_CHECK_TOK(tok, lex, TOK_SQUARE_CLOSE); break; case TOK_DOT: - // Field access / method call - // TODO: What about tuple indexing? + // Field access / method call / tuple index switch(GET_TOK(tok, lex)) { case TOK_IDENT: { @@ -996,7 +996,7 @@ ExprNodeP Parse_ExprVal_StructLiteral(TokenStream& lex, AST::Path path) ::AST::ExprNode_StructLiteral::t_values items; while( GET_TOK(tok, lex) == TOK_IDENT || tok.type() == TOK_HASH ) { - ::AST::MetaItems attrs; + ::AST::AttributeList attrs; // Note: Parse_ItemAttrs uses lookahead, so can't use it here. if( tok.type() == TOK_HASH ) { PUTBACK(tok, lex); @@ -1097,7 +1097,7 @@ ExprNodeP Parse_ExprVal(TokenStream& lex) return tok.take_frag_node(); - // TODO: Return/break/continue/... here? + // Return/break/continue/... also parsed here (but recurses back up to actually handle them) case TOK_RWORD_RETURN: case TOK_RWORD_CONTINUE: case TOK_RWORD_BREAK: @@ -1177,7 +1177,6 @@ ExprNodeP Parse_ExprVal(TokenStream& lex) return NEWNODE( AST::ExprNode_NamedValue, ::std::move(path) ); } case TOK_RWORD_MOVE: - // TODO: Annotate closure as move GET_TOK(tok, lex); if(tok.type() == TOK_PIPE) return Parse_ExprVal_Closure(lex, true); @@ -1271,7 +1270,9 @@ ExprNodeP Parse_ExprVal(TokenStream& lex) } ExprNodeP Parse_ExprMacro(TokenStream& lex, AST::Path path) { - ASSERT_BUG(lex.point_span(), path.is_trivial(), "TODO: Support path macros - " << path); + if( !path.is_trivial() ) { + TODO(lex.point_span(), "Support path macros - " << path); + } Token tok; ::std::string name = path.m_class.is_Local() ? path.m_class.as_Local().name : path.nodes()[0].name(); diff --git a/src/parse/interpolated_fragment.cpp b/src/parse/interpolated_fragment.cpp index 29a7ab5a..9b7979f3 100644 --- a/src/parse/interpolated_fragment.cpp +++ b/src/parse/interpolated_fragment.cpp @@ -21,7 +21,7 @@ InterpolatedFragment::~InterpolatedFragment() delete reinterpret_cast<AST::ExprNode*>(m_ptr); break; case InterpolatedFragment::META: - delete reinterpret_cast<AST::MetaItem*>(m_ptr); + delete reinterpret_cast<AST::Attribute*>(m_ptr); break; case InterpolatedFragment::ITEM: delete reinterpret_cast<AST::Named<AST::Item>*>(m_ptr); @@ -47,9 +47,9 @@ InterpolatedFragment::InterpolatedFragment(InterpolatedFragment::Type type, AST: m_ptr( ptr ) { } -InterpolatedFragment::InterpolatedFragment(AST::MetaItem v): +InterpolatedFragment::InterpolatedFragment(AST::Attribute v): m_type( InterpolatedFragment::META ), - m_ptr( new AST::MetaItem(mv$(v)) ) + m_ptr( new AST::Attribute(mv$(v)) ) { } InterpolatedFragment::InterpolatedFragment(::AST::Named<::AST::Item> v): @@ -106,7 +106,7 @@ InterpolatedFragment::InterpolatedFragment(TypeRef v): break; case InterpolatedFragment::META: - os << "meta[" << *reinterpret_cast<const AST::MetaItem*>(x.m_ptr) << "]"; + os << "meta[" << *reinterpret_cast<const AST::Attribute*>(x.m_ptr) << "]"; break; case InterpolatedFragment::ITEM: { const auto& named_item = *reinterpret_cast<const AST::Named<AST::Item>*>(x.m_ptr); diff --git a/src/parse/interpolated_fragment.hpp b/src/parse/interpolated_fragment.hpp index 1b18845a..857e77aa 100644 --- a/src/parse/interpolated_fragment.hpp +++ b/src/parse/interpolated_fragment.hpp @@ -10,7 +10,7 @@ namespace AST { class Pattern; class Path; class ExprNode; - class MetaItem; + class Attribute; template<typename T> struct Named; class Item; }; @@ -44,7 +44,7 @@ public: InterpolatedFragment(::AST::Pattern); InterpolatedFragment(::AST::Path); InterpolatedFragment(::TypeRef); - InterpolatedFragment(::AST::MetaItem ); + InterpolatedFragment(::AST::Attribute ); InterpolatedFragment(::AST::Named<AST::Item> ); ~InterpolatedFragment(); InterpolatedFragment(Type , ::AST::ExprNode*); 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/pattern.cpp b/src/parse/pattern.cpp index 974ff5fb..f6d61728 100644 --- a/src/parse/pattern.cpp +++ b/src/parse/pattern.cpp @@ -18,9 +18,9 @@ using AST::ExprNode; ::AST::Pattern::TuplePat Parse_PatternTuple(TokenStream& lex, bool is_refutable); AST::Pattern Parse_PatternReal_Slice(TokenStream& lex, bool is_refutable); -AST::Pattern Parse_PatternReal_Path(TokenStream& lex, AST::Path path, bool is_refutable); +AST::Pattern Parse_PatternReal_Path(TokenStream& lex, ProtoSpan ps, AST::Path path, bool is_refutable); AST::Pattern Parse_PatternReal(TokenStream& lex, bool is_refutable); -AST::Pattern Parse_PatternStruct(TokenStream& lex, AST::Path path, bool is_refutable); +AST::Pattern Parse_PatternStruct(TokenStream& lex, ProtoSpan ps, AST::Path path, bool is_refutable); AST::Pattern Parse_PatternReal(TokenStream& lex, bool is_refutable); AST::Pattern Parse_PatternReal1(TokenStream& lex, bool is_refutable); @@ -46,7 +46,7 @@ AST::Pattern Parse_Pattern(TokenStream& lex, bool is_refutable) if( tok.type() == TOK_IDENT && lex.lookahead(0) == TOK_EXCLAM ) { lex.getToken(); - return AST::Pattern( AST::Pattern::TagMacro(), box$(Parse_MacroInvocation(ps, tok.str(), lex))); + return AST::Pattern( AST::Pattern::TagMacro(), lex.end_span(ps), box$(Parse_MacroInvocation(ps, tok.str(), lex))); } if( tok.type() == TOK_INTERPOLATED_PATTERN ) { @@ -92,7 +92,7 @@ AST::Pattern Parse_Pattern(TokenStream& lex, bool is_refutable) if( GET_TOK(tok, lex) != TOK_AT ) { PUTBACK(tok, lex); - return AST::Pattern(AST::Pattern::TagBind(), mv$(bind_name), bind_type, is_mut); + return AST::Pattern(AST::Pattern::TagBind(), lex.end_span(ps), mv$(bind_name), bind_type, is_mut); } binding = AST::PatternBinding( mv$(bind_name), bind_type, is_mut ); @@ -126,11 +126,11 @@ AST::Pattern Parse_Pattern(TokenStream& lex, bool is_refutable) if( is_refutable ) { assert(bind_type == ::AST::PatternBinding::Type::MOVE); assert(is_mut == false); - return AST::Pattern(AST::Pattern::TagMaybeBind(), mv$(name)); + return AST::Pattern(AST::Pattern::TagMaybeBind(), lex.end_span(ps), mv$(name)); } // Otherwise, it IS a binding else { - return AST::Pattern(AST::Pattern::TagBind(), mv$(name), bind_type, is_mut); + return AST::Pattern(AST::Pattern::TagBind(), lex.end_span(ps), mv$(name), bind_type, is_mut); } break;} } @@ -154,6 +154,7 @@ AST::Pattern Parse_PatternReal(TokenStream& lex, bool is_refutable) GET_TOK(tok, lex); return mv$(tok.frag_pattern()); } + auto ps = lex.start_span(); AST::Pattern ret = Parse_PatternReal1(lex, is_refutable); if( GET_TOK(tok, lex) == TOK_TRIPLE_DOT ) { @@ -166,6 +167,7 @@ AST::Pattern Parse_PatternReal(TokenStream& lex, bool is_refutable) throw ParseError::Generic(lex, "Using '...' with a non-value on right"); auto rightval = mv$( right_pat.data().as_Value().start ); ret_v.end = mv$(rightval); + // TODO: use `ps` here? return ret; } @@ -178,6 +180,7 @@ AST::Pattern Parse_PatternReal(TokenStream& lex, bool is_refutable) AST::Pattern Parse_PatternReal1(TokenStream& lex, bool is_refutable) { TRACE_FUNCTION; + auto ps = lex.start_span(); Token tok; AST::Path path; @@ -185,11 +188,11 @@ AST::Pattern Parse_PatternReal1(TokenStream& lex, bool is_refutable) switch( GET_TOK(tok, lex) ) { case TOK_UNDERSCORE: - return AST::Pattern( ); + return AST::Pattern( lex.end_span(ps), AST::Pattern::Data() ); //case TOK_DOUBLE_DOT: // return AST::Pattern( AST::Pattern::TagWildcard() ); case TOK_RWORD_BOX: - return AST::Pattern( AST::Pattern::TagBox(), Parse_Pattern(lex, is_refutable) ); + return AST::Pattern( AST::Pattern::TagBox(), lex.end_span(ps), Parse_Pattern(lex, is_refutable) ); case TOK_DOUBLE_AMP: lex.putback(TOK_AMP); case TOK_AMP: { @@ -200,7 +203,7 @@ AST::Pattern Parse_PatternReal1(TokenStream& lex, bool is_refutable) is_mut = true; else PUTBACK(tok, lex); - return AST::Pattern( AST::Pattern::TagReference(), is_mut, Parse_Pattern(lex, is_refutable) ); + return AST::Pattern( AST::Pattern::TagReference(), lex.end_span(ps), is_mut, Parse_Pattern(lex, is_refutable) ); } case TOK_RWORD_SELF: case TOK_RWORD_SUPER: @@ -209,53 +212,53 @@ AST::Pattern Parse_PatternReal1(TokenStream& lex, bool is_refutable) case TOK_DOUBLE_LT: case TOK_INTERPOLATED_PATH: PUTBACK(tok, lex); - return Parse_PatternReal_Path( lex, Parse_Path(lex, PATH_GENERIC_EXPR), is_refutable ); + return Parse_PatternReal_Path( lex, ps, Parse_Path(lex, PATH_GENERIC_EXPR), is_refutable ); case TOK_DOUBLE_COLON: // 2. Paths are enum/struct names - return Parse_PatternReal_Path( lex, Parse_Path(lex, true, PATH_GENERIC_EXPR), is_refutable ); + return Parse_PatternReal_Path( lex, ps, Parse_Path(lex, true, PATH_GENERIC_EXPR), is_refutable ); case TOK_DASH: if(GET_TOK(tok, lex) == TOK_INTEGER) { auto dt = tok.datatype(); // TODO: Ensure that the type is ANY or a signed integer - return AST::Pattern( AST::Pattern::TagValue(), AST::Pattern::Value::make_Integer({dt, -tok.intval()}) ); + return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(ps), AST::Pattern::Value::make_Integer({dt, -tok.intval()}) ); } else if( tok.type() == TOK_FLOAT ) { - return AST::Pattern( AST::Pattern::TagValue(), AST::Pattern::Value::make_Float({tok.datatype(), -tok.floatval()}) ); + return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(ps), AST::Pattern::Value::make_Float({tok.datatype(), -tok.floatval()}) ); } else { throw ParseError::Unexpected(lex, tok, {TOK_INTEGER, TOK_FLOAT}); } case TOK_FLOAT: - return AST::Pattern( AST::Pattern::TagValue(), AST::Pattern::Value::make_Float({tok.datatype(), tok.floatval()}) ); + return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(ps), AST::Pattern::Value::make_Float({tok.datatype(), tok.floatval()}) ); case TOK_INTEGER: - return AST::Pattern( AST::Pattern::TagValue(), AST::Pattern::Value::make_Integer({tok.datatype(), tok.intval()}) ); + return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(ps), AST::Pattern::Value::make_Integer({tok.datatype(), tok.intval()}) ); case TOK_RWORD_TRUE: - return AST::Pattern( AST::Pattern::TagValue(), AST::Pattern::Value::make_Integer({CORETYPE_BOOL, 1}) ); + return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(ps), AST::Pattern::Value::make_Integer({CORETYPE_BOOL, 1}) ); case TOK_RWORD_FALSE: - return AST::Pattern( AST::Pattern::TagValue(), AST::Pattern::Value::make_Integer({CORETYPE_BOOL, 0}) ); + return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(ps), AST::Pattern::Value::make_Integer({CORETYPE_BOOL, 0}) ); case TOK_STRING: - return AST::Pattern( AST::Pattern::TagValue(), AST::Pattern::Value::make_String( mv$(tok.str()) ) ); + return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(ps), AST::Pattern::Value::make_String( mv$(tok.str()) ) ); case TOK_BYTESTRING: - return AST::Pattern( AST::Pattern::TagValue(), AST::Pattern::Value::make_ByteString({ mv$(tok.str()) }) ); + return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(ps), AST::Pattern::Value::make_ByteString({ mv$(tok.str()) }) ); case TOK_INTERPOLATED_EXPR: { auto e = tok.take_frag_node(); if( auto* n = dynamic_cast<AST::ExprNode_String*>(e.get()) ) { - return AST::Pattern( AST::Pattern::TagValue(), AST::Pattern::Value::make_String( mv$(n->m_value) ) ); + return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(ps), AST::Pattern::Value::make_String( mv$(n->m_value) ) ); } //else if( auto* n = dynamic_cast<AST::ExprNode_ByteString*>(e.get()) ) { - // return AST::Pattern( AST::Pattern::TagValue(), AST::Pattern::Value::make_ByteString( mv$(n->m_value) ) ); + // return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(ps), AST::Pattern::Value::make_ByteString( mv$(n->m_value) ) ); //} else if( auto* n = dynamic_cast<AST::ExprNode_Bool*>(e.get()) ) { - return AST::Pattern( AST::Pattern::TagValue(), AST::Pattern::Value::make_Integer({CORETYPE_BOOL, n->m_value}) ); + return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(ps), AST::Pattern::Value::make_Integer({CORETYPE_BOOL, n->m_value}) ); } else if( auto* n = dynamic_cast<AST::ExprNode_Integer*>(e.get()) ) { - return AST::Pattern( AST::Pattern::TagValue(), AST::Pattern::Value::make_Integer({n->m_datatype, n->m_value}) ); + return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(ps), AST::Pattern::Value::make_Integer({n->m_datatype, n->m_value}) ); } else if( auto* n = dynamic_cast<AST::ExprNode_Float*>(e.get()) ) { - return AST::Pattern( AST::Pattern::TagValue(), AST::Pattern::Value::make_Float({n->m_datatype, n->m_value}) ); + return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(ps), AST::Pattern::Value::make_Float({n->m_datatype, n->m_value}) ); } else { TODO(lex.point_span(), "Convert :expr into a pattern value - " << *e); @@ -263,32 +266,32 @@ AST::Pattern Parse_PatternReal1(TokenStream& lex, bool is_refutable) } break; case TOK_PAREN_OPEN: - return AST::Pattern( AST::Pattern::TagTuple(), Parse_PatternTuple(lex, is_refutable) ); + return AST::Pattern( AST::Pattern::TagTuple(), lex.end_span(ps), Parse_PatternTuple(lex, is_refutable) ); case TOK_SQUARE_OPEN: return Parse_PatternReal_Slice(lex, is_refutable); default: throw ParseError::Unexpected(lex, tok); } } -AST::Pattern Parse_PatternReal_Path(TokenStream& lex, AST::Path path, bool is_refutable) +AST::Pattern Parse_PatternReal_Path(TokenStream& lex, ProtoSpan ps, AST::Path path, bool is_refutable) { Token tok; switch( GET_TOK(tok, lex) ) { case TOK_PAREN_OPEN: - return AST::Pattern( AST::Pattern::TagNamedTuple(), mv$(path), Parse_PatternTuple(lex, is_refutable) ); + return AST::Pattern( AST::Pattern::TagNamedTuple(), lex.end_span(ps), mv$(path), Parse_PatternTuple(lex, is_refutable) ); case TOK_BRACE_OPEN: - return Parse_PatternStruct(lex, mv$(path), is_refutable); + return Parse_PatternStruct(lex, ps, mv$(path), is_refutable); default: PUTBACK(tok, lex); - return AST::Pattern( AST::Pattern::TagValue(), AST::Pattern::Value::make_Named(mv$(path)) ); + return AST::Pattern( AST::Pattern::TagValue(), lex.end_span(ps), AST::Pattern::Value::make_Named(mv$(path)) ); } } AST::Pattern Parse_PatternReal_Slice(TokenStream& lex, bool is_refutable) { - auto sp = lex.start_span(); + auto ps = lex.start_span(); Token tok; ::std::vector< ::AST::Pattern> leading; @@ -320,7 +323,7 @@ AST::Pattern Parse_PatternReal_Slice(TokenStream& lex, bool is_refutable) if( has_binding ) { if(is_split) - ERROR(lex.end_span(sp), E0000, "Multiple instances of .. in a slice pattern"); + ERROR(lex.end_span(ps), E0000, "Multiple instances of .. in a slice pattern"); inner_binding = mv$(binding); is_split = true; @@ -343,13 +346,13 @@ AST::Pattern Parse_PatternReal_Slice(TokenStream& lex, bool is_refutable) if( is_split ) { - return ::AST::Pattern( ::AST::Pattern::Data::make_SplitSlice({ mv$(leading), mv$(inner_binding), mv$(trailing) }) ); + return ::AST::Pattern( lex.end_span(ps), ::AST::Pattern::Data::make_SplitSlice({ mv$(leading), mv$(inner_binding), mv$(trailing) }) ); } else { assert( !inner_binding.is_valid() ); assert( trailing.empty() ); - return ::AST::Pattern( ::AST::Pattern::Data::make_Slice({ mv$(leading) }) ); + return ::AST::Pattern( lex.end_span(ps), ::AST::Pattern::Data::make_Slice({ mv$(leading) }) ); } } @@ -398,7 +401,7 @@ AST::Pattern Parse_PatternReal_Slice(TokenStream& lex, bool is_refutable) return ::AST::Pattern::TuplePat { mv$(leading), true, mv$(trailing) }; } -AST::Pattern Parse_PatternStruct(TokenStream& lex, AST::Path path, bool is_refutable) +AST::Pattern Parse_PatternStruct(TokenStream& lex, ProtoSpan ps, AST::Path path, bool is_refutable) { TRACE_FUNCTION; Token tok; @@ -449,7 +452,7 @@ AST::Pattern Parse_PatternStruct(TokenStream& lex, AST::Path path, bool is_refut i ++; } - return AST::Pattern(AST::Pattern::TagNamedTuple(), mv$(path), AST::Pattern::TuplePat { mv$(leading), has_split, mv$(trailing) }); + return AST::Pattern(AST::Pattern::TagNamedTuple(), lex.end_span(ps), mv$(path), AST::Pattern::TuplePat { mv$(leading), has_split, mv$(trailing) }); } bool is_exhaustive = true; @@ -465,6 +468,7 @@ AST::Pattern Parse_PatternStruct(TokenStream& lex, AST::Path path, bool is_refut break; } + auto inner_ps = lex.start_span(); bool is_short_bind = false; bool is_box = false; auto bind_type = AST::PatternBinding::Type::MOVE; @@ -499,12 +503,12 @@ AST::Pattern Parse_PatternStruct(TokenStream& lex, AST::Path path, bool is_refut AST::Pattern pat; if( is_short_bind || tok.type() != TOK_COLON ) { PUTBACK(tok, lex); - pat = AST::Pattern(); + pat = AST::Pattern(lex.end_span(inner_ps), {}); field_name = field_ident.name; pat.set_bind(mv$(field_ident), bind_type, is_mut); if( is_box ) { - pat = AST::Pattern(AST::Pattern::TagBox(), mv$(pat)); + pat = AST::Pattern(AST::Pattern::TagBox(), lex.end_span(inner_ps), mv$(pat)); } } else { @@ -517,6 +521,6 @@ AST::Pattern Parse_PatternStruct(TokenStream& lex, AST::Path path, bool is_refut } while( GET_TOK(tok, lex) == TOK_COMMA ); CHECK_TOK(tok, TOK_BRACE_CLOSE); - return AST::Pattern(AST::Pattern::TagStruct(), ::std::move(path), ::std::move(subpats), is_exhaustive); + return AST::Pattern(AST::Pattern::TagStruct(), lex.end_span(ps), ::std::move(path), ::std::move(subpats), is_exhaustive); } 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; diff --git a/src/parse/token.cpp b/src/parse/token.cpp index 768a96bc..115df135 100644 --- a/src/parse/token.cpp +++ b/src/parse/token.cpp @@ -33,7 +33,7 @@ Token::~Token() delete reinterpret_cast<AST::ExprNode*>(m_data.as_Fragment()); break; case TOK_INTERPOLATED_META: - delete reinterpret_cast<AST::MetaItem*>(m_data.as_Fragment()); + delete reinterpret_cast<AST::Attribute*>(m_data.as_Fragment()); break; default: break; @@ -92,7 +92,7 @@ Token::Token(const InterpolatedFragment& frag) break; case InterpolatedFragment::META: m_type = TOK_INTERPOLATED_META; - m_data = new AST::MetaItem( reinterpret_cast<const AST::MetaItem*>(frag.m_ptr)->clone() ); + m_data = new AST::Attribute( reinterpret_cast<const AST::Attribute*>(frag.m_ptr)->clone() ); break; case InterpolatedFragment::ITEM: { m_type = TOK_INTERPOLATED_ITEM; @@ -197,11 +197,11 @@ Token Token::clone() const rv.m_data = reinterpret_cast<AST::ExprNode*>(e)->clone().release(); break; case TOK_INTERPOLATED_META: - rv.m_data = new AST::MetaItem( reinterpret_cast<AST::MetaItem*>(e)->clone() ); + rv.m_data = new AST::Attribute( reinterpret_cast<AST::Attribute*>(e)->clone() ); break; case TOK_INTERPOLATED_ITEM: TODO(m_pos, "clone interpolated item"); - //rv.m_data = new AST::Named( AST::Item( reinterpret_cast<AST::MetaItem*>(e)->clone() ) ); + //rv.m_data = new AST::Named( AST::Item( reinterpret_cast<AST::Attribute*>(e)->clone() ) ); break; default: BUG(m_pos, "Fragment with invalid token type (" << *this << ")"); @@ -297,7 +297,7 @@ struct EscapedString { reinterpret_cast<const ::AST::Path*>(m_data.as_Fragment())->print_pretty(ss, true); return ss.str(); case TOK_INTERPOLATED_PATTERN: - // TODO: Use a configurable print + // TODO: Use a pretty printer too? return FMT( *reinterpret_cast<const ::AST::Pattern*>(m_data.as_Fragment()) ); case TOK_INTERPOLATED_STMT: case TOK_INTERPOLATED_BLOCK: @@ -312,9 +312,21 @@ struct EscapedString { // Value tokens case TOK_IDENT: return m_data.as_String(); case TOK_LIFETIME: return "'" + m_data.as_String(); - case TOK_INTEGER: return FMT(m_data.as_Integer().m_intval); // TODO: suffix for type + case TOK_INTEGER: + if( m_data.as_Integer().m_datatype == CORETYPE_ANY ) { + return FMT(m_data.as_Integer().m_intval); + } + else { + return FMT(m_data.as_Integer().m_intval << "_" << m_data.as_Integer().m_datatype); + } case TOK_CHAR: return FMT("'\\u{"<< ::std::hex << m_data.as_Integer().m_intval << "}"); - case TOK_FLOAT: return FMT(m_data.as_Float().m_floatval); + case TOK_FLOAT: + if( m_data.as_Float().m_datatype == CORETYPE_ANY ) { + return FMT(m_data.as_Float().m_floatval); + } + else { + return FMT(m_data.as_Float().m_floatval << "_" << m_data.as_Float().m_datatype); + } case TOK_STRING: return FMT("\"" << EscapedString(m_data.as_String()) << "\""); case TOK_BYTESTRING:return FMT("b\"" << m_data.as_String() << "\""); case TOK_HASH: return "#"; @@ -445,78 +457,6 @@ struct EscapedString { throw ParseError::BugCheck("Reached end of Token::to_str"); } -void operator%(::Serialiser& s, enum eTokenType c) { - s << Token::typestr(c); -} -void operator%(::Deserialiser& s, enum eTokenType& c) { - ::std::string n; - s.item(n); - c = Token::typefromstr(n); -} -void operator%(::Serialiser& s, enum eCoreType t) { - s << coretype_name(t); -} -void operator%(::Deserialiser& s, enum eCoreType& t) { - ::std::string n; - s.item(n); - t = coretype_fromstring(n); - ASSERT_BUG(Span(), t != CORETYPE_INVAL, "Invalid coretype '" << n << "'"); -} -SERIALISE_TYPE(Token::, "Token", { - s % m_type; - s << Token::Data::tag_to_str(m_data.tag()); - TU_MATCH(Token::Data, (m_data), (e), - (None, ), - (String, - s << e; - ), - (Integer, - s % e.m_datatype; - s.item( e.m_intval ); - ), - (Float, - s % e.m_datatype; - s.item( e.m_floatval ); - ), - (Fragment, - assert(!"Serialising interpolated macro fragment"); - ) - ) -},{ - s % m_type; - Token::Data::Tag tag; - { - ::std::string tag_str; - s.item( tag_str ); - tag = Token::Data::tag_from_str(tag_str); - } - switch(tag) - { - case Token::Data::TAGDEAD: break; - case Token::Data::TAG_None: break; - case Token::Data::TAG_String: { - ::std::string str; - s.item( str ); - m_data = Token::Data::make_String(str); - break; } - case Token::Data::TAG_Integer: { - enum eCoreType dt; - uint64_t v; - s % dt; - s.item( v ); - m_data = Token::Data::make_Integer({dt, v}); - break; } - case Token::Data::TAG_Float: { - enum eCoreType dt; - double v; - s % dt; - s.item( v ); - m_data = Token::Data::make_Float({dt, v}); - break; } - case Token::Data::TAG_Fragment: - assert(!"Serialising interpolated macro fragment"); - } -}); ::std::ostream& operator<<(::std::ostream& os, const Token& tok) { @@ -553,7 +493,7 @@ SERIALISE_TYPE(Token::, "Token", { os << ":" << *reinterpret_cast<AST::ExprNode*>(tok.m_data.as_Fragment()); break; case TOK_INTERPOLATED_META: - os << ":" << *reinterpret_cast<AST::MetaItem*>(tok.m_data.as_Fragment()); + os << ":" << *reinterpret_cast<AST::Attribute*>(tok.m_data.as_Fragment()); break; case TOK_INTERPOLATED_ITEM: { const auto& named_item = *reinterpret_cast<const AST::Named<AST::Item>*>(tok.m_data.as_Fragment()); diff --git a/src/parse/token.hpp b/src/parse/token.hpp index 0ef8f009..3605679b 100644 --- a/src/parse/token.hpp +++ b/src/parse/token.hpp @@ -9,9 +9,9 @@ #include <rc_string.hpp> #include <tagged_union.hpp> -#include <serialise.hpp> #include "../coretypes.hpp" #include <ident.hpp> +#include <memory> enum eTokenType { @@ -47,7 +47,7 @@ namespace AST { class Pattern; class Path; class ExprNode; - class MetaItem; + class Attribute; class Item; template<typename T> @@ -56,9 +56,11 @@ namespace AST { class InterpolatedFragment; -class Token: - public Serialisable +class Token { + friend class HirSerialiser; + friend class HirDeserialiser; + TAGGED_UNION(Data, None, (None, struct {}), (String, ::std::string), @@ -77,6 +79,12 @@ class Token: Data m_data; Position m_pos; + Token(enum eTokenType t, Data d, Position p): + m_type(t), + m_data( ::std::move(d) ), + m_pos( ::std::move(p) ) + { + } public: virtual ~Token(); Token(); @@ -115,7 +123,7 @@ public: TypeRef& frag_type() { assert(m_type == TOK_INTERPOLATED_TYPE); return *reinterpret_cast<TypeRef*>( m_data.as_Fragment() ); } AST::Path& frag_path() { assert(m_type == TOK_INTERPOLATED_PATH); return *reinterpret_cast<AST::Path*>( m_data.as_Fragment() ); } AST::Pattern& frag_pattern() { assert(m_type == TOK_INTERPOLATED_PATTERN); return *reinterpret_cast<AST::Pattern*>( m_data.as_Fragment() ); } - AST::MetaItem& frag_meta() { assert(m_type == TOK_INTERPOLATED_META); return *reinterpret_cast<AST::MetaItem*>( m_data.as_Fragment() ); } + AST::Attribute& frag_meta() { assert(m_type == TOK_INTERPOLATED_META); return *reinterpret_cast<AST::Attribute*>( m_data.as_Fragment() ); } ::std::unique_ptr<AST::ExprNode> take_frag_node(); ::AST::Named<AST::Item> take_frag_item(); @@ -141,8 +149,6 @@ public: static const char* typestr(enum eTokenType type); static eTokenType typefromstr(const ::std::string& s); - SERIALISABLE_PROTOTYPES(); - friend ::std::ostream& operator<<(::std::ostream& os, const Token& tok); }; extern ::std::ostream& operator<<(::std::ostream& os, const Token& tok); diff --git a/src/parse/tokenstream.cpp b/src/parse/tokenstream.cpp index 901312a3..611df2ff 100644 --- a/src/parse/tokenstream.cpp +++ b/src/parse/tokenstream.cpp @@ -140,8 +140,12 @@ 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(), ""); + TODO(getPosition(), "get_ident from TOK_INTERPOLATED_IDENT"); } else { throw ParseError::Unexpected(*this, tok); diff --git a/src/parse/tokenstream.hpp b/src/parse/tokenstream.hpp index 766e52bc..a9d325c2 100644 --- a/src/parse/tokenstream.hpp +++ b/src/parse/tokenstream.hpp @@ -16,7 +16,7 @@ namespace AST { class Module; - class MetaItems; + class AttributeList; } /// State the parser needs to pass down via a second channel. @@ -28,7 +28,7 @@ struct ParseState bool no_expand_macros = false; ::AST::Module* module = nullptr; - ::AST::MetaItems* parent_attrs = nullptr; + ::AST::AttributeList* parent_attrs = nullptr; ::AST::Module& get_current_mod() { assert(this->module); diff --git a/src/parse/types.cpp b/src/parse/types.cpp index 26785cf7..a07e66f8 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 === @@ -71,7 +71,6 @@ TypeRef Parse_Type_Int(TokenStream& lex, bool allow_trait_list) case TOK_RWORD_UNSAFE: case TOK_RWORD_EXTERN: case TOK_RWORD_FN: - // TODO: Handle HRLS in fn types return Parse_Type_Fn(lex, hrls); default: return Parse_Type_Path(lex, hrls, true); @@ -109,23 +108,21 @@ TypeRef Parse_Type_Int(TokenStream& lex, bool allow_trait_list) lex.putback(Token(TOK_AMP)); // '&' - Reference type case TOK_AMP: { - ::std::string lifetime; + AST::LifetimeRef lifetime; // Reference tok = lex.getToken(); if( tok.type() == TOK_LIFETIME ) { - lifetime = tok.str(); + lifetime = AST::LifetimeRef(/*lex.point_span(), */lex.get_ident(::std::move(tok))); tok = lex.getToken(); } + bool is_mut = false; if( tok.type() == TOK_RWORD_MUT ) { - // Mutable reference - return TypeRef(TypeRef::TagReference(), lex.end_span(ps), true, Parse_Type(lex, false)); + is_mut = true; } else { PUTBACK(tok, lex); - // Immutable reference - return TypeRef(TypeRef::TagReference(), lex.end_span(ps), false, Parse_Type(lex, false)); } - throw ParseError::BugCheck("Reached end of Parse_Type:AMP"); + return TypeRef(TypeRef::TagReference(), lex.end_span(ps), ::std::move(lifetime), is_mut, Parse_Type(lex, false)); } // '*' - Raw pointer case TOK_STAR: @@ -196,10 +193,9 @@ 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 TRACE_FUNCTION; Token tok; @@ -208,11 +204,13 @@ TypeRef Parse_Type_Fn(TokenStream& lex, ::std::vector<::std::string> hrls) GET_TOK(tok, lex); + // `unsafe` if( tok.type() == TOK_RWORD_UNSAFE ) { is_unsafe = true; GET_TOK(tok, lex); } + // `exern` if( tok.type() == TOK_RWORD_EXTERN ) { if( GET_TOK(tok, lex) == TOK_STRING ) { @@ -225,6 +223,7 @@ TypeRef Parse_Type_Fn(TokenStream& lex, ::std::vector<::std::string> hrls) abi = "C"; } } + // `fn` CHECK_TOK(tok, TOK_RWORD_FN); ::std::vector<TypeRef> args; @@ -250,6 +249,7 @@ TypeRef Parse_Type_Fn(TokenStream& lex, ::std::vector<::std::string> hrls) } GET_CHECK_TOK(tok, lex, TOK_PAREN_CLOSE); + // `-> RetType` TypeRef ret_type = TypeRef(TypeRef::TagUnit(), Span(tok.get_pos())); if( GET_TOK(tok, lex) == TOK_THINARROW ) { @@ -259,39 +259,55 @@ TypeRef Parse_Type_Fn(TokenStream& lex, ::std::vector<::std::string> hrls) PUTBACK(tok, lex); } - return TypeRef(TypeRef::TagFunction(), lex.end_span(ps), is_unsafe, mv$(abi), mv$(args), is_variadic, mv$(ret_type)); + return TypeRef(TypeRef::TagFunction(), lex.end_span(ps), mv$(hrbs), 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) })); } |