summaryrefslogtreecommitdiff
path: root/src/parse
diff options
context:
space:
mode:
Diffstat (limited to 'src/parse')
-rw-r--r--src/parse/common.hpp12
-rw-r--r--src/parse/expr.cpp27
-rw-r--r--src/parse/interpolated_fragment.cpp8
-rw-r--r--src/parse/interpolated_fragment.hpp4
-rw-r--r--src/parse/paths.cpp4
-rw-r--r--src/parse/pattern.cpp80
-rw-r--r--src/parse/root.cpp231
-rw-r--r--src/parse/token.cpp100
-rw-r--r--src/parse/token.hpp20
-rw-r--r--src/parse/tokenstream.cpp6
-rw-r--r--src/parse/tokenstream.hpp4
-rw-r--r--src/parse/types.cpp97
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) }));
}