@@ -35,8 +35,12 @@ pub mod rt {
3535
3636 use ast:: { TokenTree , Generics , Expr } ;
3737
38+ use std:: iter;
39+
3840 pub use parse:: new_parser_from_tts;
3941 pub use codemap:: { BytePos , Span , dummy_spanned} ;
42+ pub use std:: iter:: IntoIterator ;
43+ pub use parse:: attr:: ParserAttr ;
4044
4145 pub trait ToTokens {
4246 fn to_tokens ( & self , _cx : & ExtCtxt ) -> Vec < TokenTree > ;
@@ -310,23 +314,6 @@ pub mod rt {
310314 )
311315 }
312316
313- impl_to_tokens ! { ast:: Ident }
314- impl_to_tokens ! { ast:: Path }
315- impl_to_tokens ! { P <ast:: Item > }
316- impl_to_tokens ! { P <ast:: ImplItem > }
317- impl_to_tokens ! { P <ast:: TraitItem > }
318- impl_to_tokens ! { P <ast:: Pat > }
319- impl_to_tokens ! { ast:: Arm }
320- impl_to_tokens_lifetime ! { & ' a [ P <ast:: Item >] }
321- impl_to_tokens ! { ast:: Ty }
322- impl_to_tokens_lifetime ! { & ' a [ ast:: Ty ] }
323- impl_to_tokens ! { Generics }
324- impl_to_tokens ! { ast:: WhereClause }
325- impl_to_tokens ! { P <ast:: Stmt > }
326- impl_to_tokens ! { P <ast:: Expr > }
327- impl_to_tokens ! { ast:: Block }
328- impl_to_tokens ! { ast:: Arg }
329- impl_to_tokens ! { ast:: Attribute_ }
330317 impl_to_tokens_lifetime ! { & ' a str }
331318 impl_to_tokens ! { ( ) }
332319 impl_to_tokens ! { char }
@@ -399,14 +386,94 @@ pub mod rt {
399386
400387 }
401388
389+ pub struct IterWrapper < I > {
390+ inner : I ,
391+ empty : bool ,
392+ }
393+
394+ impl < T , I : Iterator < Item =T > > Iterator for IterWrapper < I > {
395+ type Item = T ;
396+ fn next ( & mut self ) -> Option < T > {
397+ match self . inner . next ( ) {
398+ Some ( elem) => {
399+ self . empty = false ;
400+ Some ( elem)
401+ }
402+ None => {
403+ assert ! ( !self . empty, "a fragment must repeat at least once in quasiquotation" ) ;
404+ None
405+ }
406+ }
407+ }
408+ }
409+
410+ pub trait IntoWrappedIter {
411+ type Item ;
412+ type IntoIter : Iterator < Item =Self :: Item > ;
413+ fn into_wrapped_iter ( self , one_or_more : bool ) -> IterWrapper < Self :: IntoIter > ;
414+ }
415+
416+ impl < I : IntoIterator > IntoWrappedIter for I {
417+ type Item = I :: Item ;
418+ type IntoIter = I :: IntoIter ;
419+ fn into_wrapped_iter ( self , one_or_more : bool ) -> IterWrapper < I :: IntoIter > {
420+ IterWrapper { empty : one_or_more, inner : self . into_iter ( ) }
421+ }
422+ }
423+
424+ impl < T : Clone > IntoWrappedIter for Spanned < T > {
425+ type Item = Spanned < T > ;
426+ type IntoIter = iter:: Repeat < Spanned < T > > ;
427+ fn into_wrapped_iter ( self , one_or_more : bool ) -> IterWrapper < iter:: Repeat < Spanned < T > > > {
428+ IterWrapper { empty : one_or_more, inner : iter:: repeat ( self ) }
429+ }
430+ }
431+
432+ impl IntoWrappedIter for TokenTree {
433+ type Item = TokenTree ;
434+ type IntoIter = iter:: Repeat < TokenTree > ;
435+ fn into_wrapped_iter ( self , one_or_more : bool ) -> IterWrapper < iter:: Repeat < TokenTree > > {
436+ IterWrapper { empty : one_or_more, inner : iter:: repeat ( self ) }
437+ }
438+ }
439+
440+ macro_rules! impl_to_tokens_local {
441+ ( $t: ty) => (
442+ impl_to_tokens!( $t) ;
443+
444+ impl IntoWrappedIter for $t {
445+ type Item = $t;
446+ type IntoIter = iter:: Repeat <$t>;
447+ fn into_wrapped_iter( self , one_or_more: bool ) -> IterWrapper <iter:: Repeat <$t>> {
448+ IterWrapper { empty: one_or_more, inner: iter:: repeat( self ) }
449+ }
450+ }
451+ )
452+ }
453+
454+ impl_to_tokens_local ! { ast:: Ident }
455+ impl_to_tokens_local ! { ast:: Path }
456+ impl_to_tokens_local ! { P <ast:: Item > }
457+ impl_to_tokens_local ! { P <ast:: ImplItem > }
458+ impl_to_tokens_local ! { P <ast:: TraitItem > }
459+ impl_to_tokens_local ! { P <ast:: Pat > }
460+ impl_to_tokens_local ! { ast:: Arm }
461+ impl_to_tokens_local ! { ast:: Ty }
462+ impl_to_tokens_local ! { Generics }
463+ impl_to_tokens_local ! { ast:: WhereClause }
464+ impl_to_tokens_local ! { P <ast:: Stmt > }
465+ impl_to_tokens_local ! { P <ast:: Expr > }
466+ impl_to_tokens_local ! { ast:: Block }
467+ impl_to_tokens_local ! { ast:: Arg }
468+ impl_to_tokens_local ! { ast:: Attribute_ }
402469}
403470
404471pub fn expand_quote_tokens < ' cx > ( cx : & ' cx mut ExtCtxt ,
405472 sp : Span ,
406473 tts : & [ ast:: TokenTree ] )
407474 -> Box < base:: MacResult +' cx > {
408475 let ( cx_expr, expr) = expand_tts ( cx, sp, tts) ;
409- let expanded = expand_wrapper ( cx, sp, cx_expr, expr, & [ & [ "syntax" , "ext" , "quote" , "rt" ] ] ) ;
476+ let expanded = expand_wrapper ( cx, sp, cx_expr, expr) ;
410477 base:: MacEager :: expr ( expanded)
411478}
412479
@@ -474,13 +541,13 @@ pub fn expand_quote_matcher(cx: &mut ExtCtxt,
474541 -> Box < base:: MacResult +' static > {
475542 let ( cx_expr, tts) = parse_arguments_to_quote ( cx, tts) ;
476543 let mut vector = mk_stmts_let ( cx, sp) ;
477- vector. extend ( statements_mk_tts ( cx, & tts[ ..] , true ) . into_iter ( ) ) ;
544+ vector. extend ( statements_mk_tts ( cx, & tts[ ..] , true ) . 0 . into_iter ( ) ) ;
478545 let block = cx. expr_block (
479546 cx. block_all ( sp,
480547 vector,
481548 Some ( cx. expr_ident ( sp, id_ext ( "tt" ) ) ) ) ) ;
482549
483- let expanded = expand_wrapper ( cx, sp, cx_expr, block, & [ & [ "syntax" , "ext" , "quote" , "rt" ] ] ) ;
550+ let expanded = expand_wrapper ( cx, sp, cx_expr, block) ;
484551 base:: MacEager :: expr ( expanded)
485552}
486553
@@ -677,7 +744,8 @@ fn expr_mk_token(cx: &ExtCtxt, sp: Span, tok: &token::Token) -> P<ast::Expr> {
677744 mk_token_path ( cx, sp, name)
678745}
679746
680- fn statements_mk_tt ( cx : & ExtCtxt , tt : & ast:: TokenTree , matcher : bool ) -> Vec < P < ast:: Stmt > > {
747+ fn statements_mk_tt ( cx : & ExtCtxt , tt : & ast:: TokenTree , matcher : bool ) -> ( Vec < P < ast:: Stmt > > ,
748+ Vec < ast:: Ident > ) {
681749 match * tt {
682750 ast:: TtToken ( sp, SubstNt ( ident, _) ) => {
683751 // tt.extend($ident.to_tokens(ext_cx).into_iter())
@@ -696,7 +764,7 @@ fn statements_mk_tt(cx: &ExtCtxt, tt: &ast::TokenTree, matcher: bool) -> Vec<P<a
696764 id_ext ( "extend" ) ,
697765 vec ! ( e_to_toks) ) ;
698766
699- vec ! ( cx. stmt_expr( e_push) )
767+ ( vec ! [ cx. stmt_expr( e_push) ] , vec ! [ ident ] )
700768 }
701769 ref tt @ ast:: TtToken ( _, MatchNt ( ..) ) if !matcher => {
702770 let mut seq = vec ! [ ] ;
@@ -715,56 +783,117 @@ fn statements_mk_tt(cx: &ExtCtxt, tt: &ast::TokenTree, matcher: bool) -> Vec<P<a
715783 cx. expr_ident ( sp, id_ext ( "tt" ) ) ,
716784 id_ext ( "push" ) ,
717785 vec ! ( e_tok) ) ;
718- vec ! ( cx. stmt_expr( e_push) )
786+ ( vec ! [ cx. stmt_expr( e_push) ] , vec ! [ ] )
719787 } ,
720788 ast:: TtDelimited ( _, ref delimed) => {
721- statements_mk_tt ( cx, & delimed. open_tt ( ) , matcher) . into_iter ( )
722- . chain ( delimed. tts . iter ( )
723- . flat_map ( |tt| statements_mk_tt ( cx, tt, matcher) . into_iter ( ) ) )
724- . chain ( statements_mk_tt ( cx, & delimed. close_tt ( ) , matcher) . into_iter ( ) )
725- . collect ( )
789+ let ( stmts, idents) = statements_mk_tts ( cx, & delimed. tts [ ..] , matcher) ;
790+ ( statements_mk_tt ( cx, & delimed. open_tt ( ) , matcher) . 0 . into_iter ( )
791+ . chain ( stmts. into_iter ( ) )
792+ . chain ( statements_mk_tt ( cx, & delimed. close_tt ( ) , matcher) . 0 . into_iter ( ) )
793+ . collect ( ) ,
794+ idents)
726795 } ,
727796 ast:: TtSequence ( sp, ref seq) => {
728- if !matcher {
729- panic ! ( "TtSequence in quote!" ) ;
730- }
797+ if matcher {
798+ let e_sp = cx. expr_ident ( sp, id_ext ( "_sp" ) ) ;
799+
800+ let stmt_let_tt = cx. stmt_let ( sp, true , id_ext ( "tt" ) , cx. expr_vec_ng ( sp) ) ;
801+ let mut tts_stmts = vec ! [ stmt_let_tt] ;
802+ tts_stmts. extend ( statements_mk_tts ( cx, & seq. tts [ ..] , matcher) . 0 . into_iter ( ) ) ;
803+ let e_tts = cx. expr_block ( cx. block ( sp, tts_stmts,
804+ Some ( cx. expr_ident ( sp, id_ext ( "tt" ) ) ) ) ) ;
805+ let e_separator = match seq. separator {
806+ Some ( ref sep) => cx. expr_some ( sp, expr_mk_token ( cx, sp, sep) ) ,
807+ None => cx. expr_none ( sp) ,
808+ } ;
809+ let e_op = match seq. op {
810+ ast:: ZeroOrMore => mk_ast_path ( cx, sp, "ZeroOrMore" ) ,
811+ ast:: OneOrMore => mk_ast_path ( cx, sp, "OneOrMore" ) ,
812+ } ;
813+ let fields = vec ! [ cx. field_imm( sp, id_ext( "tts" ) , e_tts) ,
814+ cx. field_imm( sp, id_ext( "separator" ) , e_separator) ,
815+ cx. field_imm( sp, id_ext( "op" ) , e_op) ,
816+ cx. field_imm( sp, id_ext( "num_captures" ) ,
817+ cx. expr_usize( sp, seq. num_captures) ) ] ;
818+ let seq_path = vec ! [ id_ext( "syntax" ) , id_ext( "ast" ) , id_ext( "SequenceRepetition" ) ] ;
819+ let e_seq_struct = cx. expr_struct ( sp, cx. path_global ( sp, seq_path) , fields) ;
820+ let e_rc_new = cx. expr_call_global ( sp, vec ! [ id_ext( "std" ) ,
821+ id_ext( "rc" ) ,
822+ id_ext( "Rc" ) ,
823+ id_ext( "new" ) ] ,
824+ vec ! [ e_seq_struct] ) ;
825+ let e_tok = cx. expr_call ( sp,
826+ mk_ast_path ( cx, sp, "TtSequence" ) ,
827+ vec ! ( e_sp, e_rc_new) ) ;
828+ let e_push =
829+ cx. expr_method_call ( sp,
830+ cx. expr_ident ( sp, id_ext ( "tt" ) ) ,
831+ id_ext ( "push" ) ,
832+ vec ! ( e_tok) ) ;
833+ ( vec ! [ cx. stmt_expr( e_push) ] , vec ! [ ] )
834+ } else {
835+ // Repeating fragments in a loop:
836+ // for (...(a, b), ...) in a.into_wrapped_iter().zip(b.into_wrapped_iter())... {
837+ // // (quasiquotation with $a, $b, ...)
838+ //}
839+ let ( mut stmts, idents) = statements_mk_tts ( cx, & seq. tts [ ..] , matcher) ;
840+ if idents. is_empty ( ) {
841+ cx. span_fatal ( sp, "attempted to repeat an expression containing \
842+ no syntax variables matched as repeating at this depth") ;
843+ }
731844
732- let e_sp = cx. expr_ident ( sp, id_ext ( "_sp" ) ) ;
845+ let mut iter = idents. clone ( ) . into_iter ( ) ;
846+ let first = iter. next ( ) . unwrap ( ) ;
847+ let mut zipped = cx. expr_ident ( sp, first) ;
848+ let one_or_more = cx. expr_bool ( sp, seq. op == ast:: OneOrMore ) ;
849+ zipped = cx. expr_method_call ( sp, zipped, id_ext ( "into_wrapped_iter" ) ,
850+ vec ! [ one_or_more. clone( ) ] ) ;
851+ let mut pat = cx. pat_ident ( sp, first) ;
852+ for ident in iter {
853+ // Assertion: zipped iterators must have at least one element
854+ // if one_or_more == `true`.
855+ let expr_ident = cx. expr_ident ( sp, ident) ;
856+ let expr = cx. expr_method_call ( sp, expr_ident,
857+ id_ext ( "into_wrapped_iter" ) ,
858+ vec ! [ one_or_more. clone( ) ] ) ;
859+ zipped = cx. expr_method_call ( sp, zipped, id_ext ( "zip" ) , vec ! [ expr] ) ;
860+ pat = cx. pat_tuple ( sp, vec ! ( pat, cx. pat_ident( sp, ident) ) ) ;
861+ }
733862
734- let stmt_let_tt = cx . stmt_let ( sp , true , id_ext ( "tt" ) , cx . expr_vec_ng ( sp ) ) ;
735- let mut tts_stmts = vec ! [ stmt_let_tt ] ;
736- tts_stmts . extend ( statements_mk_tts ( cx , & seq . tts [ .. ] , matcher ) . into_iter ( ) ) ;
737- let e_tts = cx . expr_block ( cx . block ( sp, tts_stmts ,
738- Some ( cx . expr_ident ( sp , id_ext ( "tt" ) ) ) ) ) ;
739- let e_separator = match seq . separator {
740- Some ( ref sep ) => cx . expr_some ( sp , expr_mk_token ( cx , sp , sep ) ) ,
741- None => cx . expr_none ( sp ) ,
742- } ;
743- let e_op = match seq . op {
744- ast :: ZeroOrMore => mk_ast_path ( cx , sp , "ZeroOrMore" ) ,
745- ast:: OneOrMore => mk_ast_path ( cx , sp , "OneOrMore" ) ,
746- } ;
747- let fields = vec ! [ cx . field_imm ( sp , id_ext ( "tts" ) , e_tts ) ,
748- cx . field_imm ( sp , id_ext ( "separator" ) , e_separator ) ,
749- cx . field_imm ( sp , id_ext ( "op" ) , e_op ) ,
750- cx . field_imm ( sp , id_ext ( "num_captures" ) ,
751- cx. expr_usize ( sp, seq . num_captures ) ) ] ;
752- let seq_path = vec ! [ id_ext ( "syntax" ) , id_ext( "ast " ) , id_ext ( "SequenceRepetition" ) ] ;
753- let e_seq_struct = cx . expr_struct ( sp , cx . path_global ( sp , seq_path ) , fields ) ;
754- let e_rc_new = cx. expr_call_global ( sp, vec ! [ id_ext ( "std" ) ,
755- id_ext ( "rc" ) ,
756- id_ext( "Rc " ) ,
757- id_ext ( "new" ) ] ,
758- vec ! [ e_seq_struct ] ) ;
759- let e_tok = cx. expr_call ( sp,
760- mk_ast_path ( cx , sp , "TtSequence" ) ,
761- vec ! ( e_sp , e_rc_new ) ) ;
762- let e_push =
763- cx . expr_method_call ( sp ,
764- cx . expr_ident ( sp , id_ext ( "tt" ) ) ,
765- id_ext ( "push" ) ,
766- vec ! ( e_tok ) ) ;
767- vec ! ( cx . stmt_expr ( e_push ) )
863+ match seq . separator {
864+ Some ( ref tok ) => {
865+ // Intersperse the separator
866+ stmts . extend ( statements_mk_tt ( cx , & ast :: TtToken ( sp, tok . clone ( ) ) ,
867+ false ) . 0 . into_iter ( ) ) ;
868+ }
869+ None => { }
870+ }
871+
872+ let stmt_for = cx . stmt_expr ( P ( ast :: Expr {
873+ id : ast :: DUMMY_NODE_ID ,
874+ node : ast:: ExprForLoop ( pat , zipped , cx . block ( sp , stmts , None ) , None ) ,
875+ span : sp ,
876+ } ) ) ;
877+
878+ let stmts_for = if seq . separator . is_some ( ) {
879+ // Pop the last occurence of the separator
880+ let tt = cx. expr_ident ( sp, id_ext ( "tt" ) ) ;
881+ let len = cx . expr_method_call ( sp , tt . clone ( ) , id_ext ( "len " ) , vec ! ( ) ) ;
882+ let _len_ident = gensym_ident ( "_len" ) ;
883+ let _len = cx. expr_ident ( sp, _len_ident ) ;
884+ let cond = cx . expr_binary ( sp , ast :: BiNe , len . clone ( ) , _len ) ;
885+ let then = cx . expr_method_call ( sp , tt , id_ext ( "pop " ) , vec ! ( ) ) ;
886+ let then = cx . expr_block ( cx . block ( sp , vec ! [ cx . stmt_expr ( then ) ] , None ) ) ;
887+ let if_len_eq = cx . expr_if ( sp , cond , then , None ) ;
888+ vec ! [ cx. stmt_let ( sp, false , _len_ident , len ) ,
889+ stmt_for ,
890+ cx . stmt_expr ( if_len_eq ) ]
891+ } else {
892+ vec ! [ stmt_for ]
893+ } ;
894+
895+ ( stmts_for , idents )
896+ }
768897 }
769898 }
770899}
@@ -832,20 +961,24 @@ fn mk_stmts_let(cx: &ExtCtxt, sp: Span) -> Vec<P<ast::Stmt>> {
832961 vec ! ( stmt_let_sp, stmt_let_tt)
833962}
834963
835- fn statements_mk_tts ( cx : & ExtCtxt , tts : & [ ast:: TokenTree ] , matcher : bool ) -> Vec < P < ast:: Stmt > > {
836- let mut ss = Vec :: new ( ) ;
964+ fn statements_mk_tts ( cx : & ExtCtxt , tts : & [ ast:: TokenTree ] , matcher : bool ) -> ( Vec < P < ast:: Stmt > > ,
965+ Vec < ast:: Ident > ) {
966+ let mut stmts = Vec :: new ( ) ;
967+ let mut idents = Vec :: new ( ) ;
837968 for tt in tts {
838- ss. extend ( statements_mk_tt ( cx, tt, matcher) . into_iter ( ) ) ;
969+ let ( ss, is) = statements_mk_tt ( cx, tt, matcher) ;
970+ stmts. extend ( ss. into_iter ( ) ) ;
971+ idents. extend ( is. into_iter ( ) ) ;
839972 }
840- ss
973+ ( stmts , idents )
841974}
842975
843976fn expand_tts ( cx : & ExtCtxt , sp : Span , tts : & [ ast:: TokenTree ] )
844977 -> ( P < ast:: Expr > , P < ast:: Expr > ) {
845978 let ( cx_expr, tts) = parse_arguments_to_quote ( cx, tts) ;
846979
847980 let mut vector = mk_stmts_let ( cx, sp) ;
848- vector. extend ( statements_mk_tts ( cx, & tts[ ..] , false ) . into_iter ( ) ) ;
981+ vector. extend ( statements_mk_tts ( cx, & tts[ ..] , false ) . 0 . into_iter ( ) ) ;
849982 let block = cx. expr_block (
850983 cx. block_all ( sp,
851984 vector,
@@ -857,13 +990,14 @@ fn expand_tts(cx: &ExtCtxt, sp: Span, tts: &[ast::TokenTree])
857990fn expand_wrapper ( cx : & ExtCtxt ,
858991 sp : Span ,
859992 cx_expr : P < ast:: Expr > ,
860- expr : P < ast:: Expr > ,
861- imports : & [ & [ & str ] ] ) -> P < ast:: Expr > {
993+ expr : P < ast:: Expr > ) -> P < ast:: Expr > {
862994 // Explicitly borrow to avoid moving from the invoker (#16992)
863995 let cx_expr_borrow = cx. expr_addr_of ( sp, cx. expr_deref ( sp, cx_expr) ) ;
864996 let stmt_let_ext_cx = cx. stmt_let ( sp, false , id_ext ( "ext_cx" ) , cx_expr_borrow) ;
865997
866- let stmts = imports. iter ( ) . map ( |path| {
998+ let stmts = [
999+ & [ "syntax" , "ext" , "quote" , "rt" ]
1000+ ] . iter ( ) . map ( |path| {
8671001 // make item: `use ...;`
8681002 let path = path. iter ( ) . map ( |s| s. to_string ( ) ) . collect ( ) ;
8691003 cx. stmt_item ( sp, cx. item_use_glob ( sp, ast:: Inherited , ids_ext ( path) ) )
@@ -895,10 +1029,5 @@ fn expand_parse_call(cx: &ExtCtxt,
8951029 let expr = cx. expr_method_call ( sp, new_parser_call, id_ext ( parse_method) ,
8961030 arg_exprs) ;
8971031
898- if parse_method == "parse_attribute" {
899- expand_wrapper ( cx, sp, cx_expr, expr, & [ & [ "syntax" , "ext" , "quote" , "rt" ] ,
900- & [ "syntax" , "parse" , "attr" ] ] )
901- } else {
902- expand_wrapper ( cx, sp, cx_expr, expr, & [ & [ "syntax" , "ext" , "quote" , "rt" ] ] )
903- }
1032+ expand_wrapper ( cx, sp, cx_expr, expr)
9041033}
0 commit comments