summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Hodge <tpg@ucc.asn.au>2019-01-05 16:32:14 +0800
committerJohn Hodge <tpg@ucc.asn.au>2019-01-05 16:32:14 +0800
commitfa3bf839ff871f862697ee1d992f0e6175c2a25b (patch)
tree8e39fffa7cbba1e4e3cc030b277e61f9f00257b2
parent0be0edd9de59072ca5b780993c2b0bbece0e7aa1 (diff)
downloadmrust-fa3bf839ff871f862697ee1d992f0e6175c2a25b.tar.gz
Expand - Macros in traits
-rw-r--r--src/expand/mod.cpp33
-rw-r--r--src/parse/common.hpp1
-rw-r--r--src/parse/root.cpp261
3 files changed, 167 insertions, 128 deletions
diff --git a/src/expand/mod.cpp b/src/expand/mod.cpp
index da37dea7..e4764be1 100644
--- a/src/expand/mod.cpp
+++ b/src/expand/mod.cpp
@@ -953,7 +953,7 @@ void Expand_Impl(::AST::Crate& crate, LList<const AST::Module*> modstack, ::AST:
TU_MATCH_DEF(AST::Item, (*i.data), (e),
(
- throw ::std::runtime_error("BUG: Unknown item type in impl block");
+ BUG(Span(), "Unknown item type in impl block - " << i.data->tag_str());
),
(None, ),
(MacroInv,
@@ -1214,17 +1214,44 @@ void Expand_Mod(::AST::Crate& crate, LList<const AST::Module*> modstack, ::AST::
),
(Trait,
Expand_GenericParams(crate, modstack, mod, e.params());
- for(auto& ti : e.items())
+ auto& trait_items = e.items();
+ for(size_t idx = 0; idx < trait_items.size(); idx ++)
{
+ auto& ti = trait_items[idx];
DEBUG(" - " << ti.name << " " << ti.data.tag_str());
auto attrs = mv$(ti.data.attrs);
Expand_Attrs(attrs, AttrStage::Pre, crate, AST::Path(), mod, ti.data);
TU_MATCH_DEF(AST::Item, (ti.data), (e),
(
- throw ::std::runtime_error("BUG: Unknown item type in impl block");
+ BUG(Span(), "Unknown item type in trait block - " << ti.data.tag_str());
),
(None, ),
+ (MacroInv,
+ if( e.name() != "" )
+ {
+ TRACE_FUNCTION_F("Macro invoke " << e.name());
+ // Move out of the module to avoid invalidation if a new macro invocation is added
+ auto mi_owned = mv$(e);
+
+ auto ttl = Expand_Macro(crate, modstack, mod, mi_owned);
+
+ if( ttl.get() )
+ {
+ // Re-parse tt
+ size_t insert_pos = idx+1;
+ while( ttl->lookahead(0) != TOK_EOF )
+ {
+ auto i = Parse_Trait_Item(*ttl);
+ trait_items.insert( trait_items.begin() + insert_pos, mv$(i) );
+ insert_pos ++;
+ }
+ // - Any new macro invocations ends up at the end of the list and handled
+ }
+ // Move back in (using the index, as the old pointer may be invalid)
+ trait_items[idx].data.as_MacroInv() = mv$(mi_owned);
+ }
+ ),
(Function,
Expand_GenericParams(crate, modstack, mod, e.params());
for(auto& arg : e.args()) {
diff --git a/src/parse/common.hpp b/src/parse/common.hpp
index c742fe4f..c8f51520 100644
--- a/src/parse/common.hpp
+++ b/src/parse/common.hpp
@@ -50,6 +50,7 @@ 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 AST::Named<AST::Item> Parse_Trait_Item(TokenStream& lex);
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/root.cpp b/src/parse/root.cpp
index 28a49287..c3fbfdd1 100644
--- a/src/parse/root.cpp
+++ b/src/parse/root.cpp
@@ -639,6 +639,141 @@ AST::Struct Parse_Struct(TokenStream& lex, const AST::AttributeList& meta_items)
}
}
+AST::Named<AST::Item> Parse_Trait_Item(TokenStream& lex)
+{
+ Token tok;
+
+ auto item_attrs = Parse_ItemAttrs(lex);
+ SET_ATTRS(lex, item_attrs);
+
+ auto ps = lex.start_span();
+ {
+ ::AST::MacroInvocation inv;
+ if( Parse_MacroInvocation_Opt(lex, inv) )
+ {
+ return AST::Named<AST::Item>( "", AST::Item(mv$(inv)), false );
+ }
+ }
+
+ GET_TOK(tok, lex);
+ bool is_specialisable = false;
+ if( tok.type() == TOK_IDENT && tok.str() == "default" ) {
+ is_specialisable = true;
+ GET_TOK(tok, lex);
+ }
+ // TODO: Mark specialisation
+ (void)is_specialisable;
+
+ bool fn_is_const = false;
+ bool fn_is_unsafe = false;
+ ::std::string abi = ABI_RUST;
+
+ ::std::string name;
+ ::AST::Item rv;
+ switch(tok.type())
+ {
+ case TOK_RWORD_STATIC: {
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ name = mv$(tok.str());
+ GET_CHECK_TOK(tok, lex, TOK_COLON);
+ auto ty = Parse_Type(lex);
+ GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
+
+ ::AST::Expr val;
+ if(GET_TOK(tok, lex) == TOK_EQUAL) {
+ val = Parse_Expr(lex);
+ GET_TOK(tok, lex);
+ }
+ CHECK_TOK(tok, TOK_SEMICOLON);
+
+ rv = ::AST::Static(::AST::Static::STATIC, mv$(ty), val);
+ break; }
+ case TOK_RWORD_CONST: {
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ name = mv$(tok.str());
+ GET_CHECK_TOK(tok, lex, TOK_COLON);
+ auto ty = Parse_Type(lex);
+
+ ::AST::Expr val;
+ if(GET_TOK(tok, lex) == TOK_EQUAL) {
+ val = Parse_Expr(lex);
+ GET_TOK(tok, lex);
+ }
+ CHECK_TOK(tok, TOK_SEMICOLON);
+
+ rv = ::AST::Static(AST::Static::CONST, mv$(ty), val);
+ break; }
+ // Associated type
+ case TOK_RWORD_TYPE: {
+ auto atype_params = ::AST::GenericParams { };
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ name = mv$(tok.str());
+ if( GET_TOK(tok, lex) == TOK_COLON )
+ {
+ // Bounded associated type
+ Parse_TypeBound(lex, atype_params, TypeRef(lex.point_span(), "Self", 0xFFFF));
+ GET_TOK(tok, lex);
+ }
+ if( tok.type() == TOK_RWORD_WHERE ) {
+ throw ParseError::Todo(lex, "Where clause on associated type");
+ }
+
+ TypeRef default_type = TypeRef( lex.point_span() );
+ if( tok.type() == TOK_EQUAL ) {
+ default_type = Parse_Type(lex);
+ GET_TOK(tok, lex);
+ }
+
+ CHECK_TOK(tok, TOK_SEMICOLON);
+ rv = ::AST::TypeAlias( mv$(atype_params), mv$(default_type) );
+ break; }
+
+ // Functions (possibly unsafe)
+ case TOK_RWORD_UNSAFE:
+ fn_is_unsafe = true;
+ if( GET_TOK(tok, lex) == TOK_RWORD_EXTERN )
+ case TOK_RWORD_EXTERN:
+ {
+ abi = "C";
+ if( GET_TOK(tok, lex) == TOK_STRING )
+ abi = tok.str();
+ else
+ PUTBACK(tok, lex);
+
+ GET_TOK(tok, lex);
+ }
+ CHECK_TOK(tok, TOK_RWORD_FN);
+ case TOK_RWORD_FN: {
+ GET_CHECK_TOK(tok, lex, TOK_IDENT);
+ name = mv$(tok.str());
+ // Self allowed, prototype-form allowed (optional names and no code)
+ auto fcn = Parse_FunctionDef(lex, abi, true, true, fn_is_unsafe, fn_is_const);
+ if( GET_TOK(tok, lex) == TOK_BRACE_OPEN )
+ {
+ PUTBACK(tok, lex);
+ // 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();
+ }
+ else if( tok.type() == TOK_SEMICOLON )
+ {
+ // Accept it
+ }
+ else
+ {
+ throw ParseError::Unexpected(lex, tok);
+ }
+ rv = ::std::move(fcn);
+ break; }
+ default:
+ throw ParseError::Unexpected(lex, tok);
+ }
+
+ rv.attrs = ::std::move( item_attrs );
+ return ::AST::Named<::AST::Item>( mv$(name), mv$(rv), true );
+}
+
AST::Trait Parse_TraitDef(TokenStream& lex, const AST::AttributeList& meta_items)
{
TRACE_FUNCTION;
@@ -689,131 +824,7 @@ AST::Trait Parse_TraitDef(TokenStream& lex, const AST::AttributeList& meta_items
{
PUTBACK(tok, lex);
- auto item_attrs = Parse_ItemAttrs(lex);
- SET_ATTRS(lex, item_attrs);
-
- auto ps = lex.start_span();
- {
- ::AST::MacroInvocation inv;
- if( Parse_MacroInvocation_Opt(lex, inv) )
- {
- trait.items().push_back( AST::Named<AST::Item>("", AST::Item(mv$(inv)), false) );
- continue ;
- }
- GET_TOK(tok, lex);
- }
-
- bool is_specialisable = false;
- if( tok.type() == TOK_IDENT && tok.str() == "default" ) {
- is_specialisable = true;
- GET_TOK(tok, lex);
- }
- // TODO: Mark specialisation
- (void)is_specialisable;
-
- bool fn_is_const = false;
- bool fn_is_unsafe = false;
- ::std::string abi = ABI_RUST;
- switch(tok.type())
- {
- case TOK_RWORD_STATIC: {
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- auto name = mv$(tok.str());
- GET_CHECK_TOK(tok, lex, TOK_COLON);
- auto ty = Parse_Type(lex);
- GET_CHECK_TOK(tok, lex, TOK_SEMICOLON);
-
- ::AST::Expr val;
- if(GET_TOK(tok, lex) == TOK_EQUAL) {
- val = Parse_Expr(lex);
- GET_TOK(tok, lex);
- }
- CHECK_TOK(tok, TOK_SEMICOLON);
-
- trait.add_static( mv$(name), mv$(item_attrs), ::AST::Static(AST::Static::STATIC, mv$(ty), val) );
- break; }
- case TOK_RWORD_CONST: {
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- auto name = mv$(tok.str());
- GET_CHECK_TOK(tok, lex, TOK_COLON);
- auto ty = Parse_Type(lex);
-
- ::AST::Expr val;
- if(GET_TOK(tok, lex) == TOK_EQUAL) {
- val = Parse_Expr(lex);
- GET_TOK(tok, lex);
- }
- CHECK_TOK(tok, TOK_SEMICOLON);
-
- trait.add_static( mv$(name), mv$(item_attrs), ::AST::Static(AST::Static::CONST, mv$(ty), val) );
- break; }
- // Associated type
- case TOK_RWORD_TYPE: {
- auto atype_params = ::AST::GenericParams { };
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- auto name = mv$(tok.str());
- if( GET_TOK(tok, lex) == TOK_COLON )
- {
- // Bounded associated type
- Parse_TypeBound(lex, atype_params, TypeRef(lex.point_span(), "Self", 0xFFFF));
- GET_TOK(tok, lex);
- }
- if( tok.type() == TOK_RWORD_WHERE ) {
- throw ParseError::Todo(lex, "Where clause on associated type");
- }
-
- TypeRef default_type = TypeRef( lex.point_span() );
- if( tok.type() == TOK_EQUAL ) {
- default_type = Parse_Type(lex);
- GET_TOK(tok, lex);
- }
-
- CHECK_TOK(tok, TOK_SEMICOLON);
- trait.add_type( ::std::move(name), mv$(item_attrs), ::std::move(default_type) );
- trait.items().back().data.as_Type().params() = mv$(atype_params);
- break; }
-
- // Functions (possibly unsafe)
- case TOK_RWORD_UNSAFE:
- fn_is_unsafe = true;
- if( GET_TOK(tok, lex) == TOK_RWORD_EXTERN )
- case TOK_RWORD_EXTERN:
- {
- abi = "C";
- if( GET_TOK(tok, lex) == TOK_STRING )
- abi = tok.str();
- else
- PUTBACK(tok, lex);
-
- GET_TOK(tok, lex);
- }
- CHECK_TOK(tok, TOK_RWORD_FN);
- case TOK_RWORD_FN: {
- GET_CHECK_TOK(tok, lex, TOK_IDENT);
- ::std::string name = mv$(tok.str());
- // Self allowed, prototype-form allowed (optional names and no code)
- auto fcn = Parse_FunctionDef(lex, abi, true, true, fn_is_unsafe, fn_is_const);
- if( GET_TOK(tok, lex) == TOK_BRACE_OPEN )
- {
- PUTBACK(tok, lex);
- // 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();
- }
- else if( tok.type() == TOK_SEMICOLON )
- {
- // Accept it
- }
- else
- {
- throw ParseError::Unexpected(lex, tok);
- }
- trait.add_function( ::std::move(name), mv$(item_attrs), ::std::move(fcn) );
- break; }
- default:
- throw ParseError::Unexpected(lex, tok);
- }
+ trait.items().push_back( Parse_Trait_Item(lex) );
}
return trait;