@@ -35,8 +35,12 @@ pub mod rt {
35
35
36
36
use ast:: { TokenTree , Generics , Expr } ;
37
37
38
+ use std:: iter;
39
+
38
40
pub use parse:: new_parser_from_tts;
39
41
pub use codemap:: { BytePos , Span , dummy_spanned} ;
42
+ pub use std:: iter:: IntoIterator ;
43
+ pub use parse:: attr:: ParserAttr ;
40
44
41
45
pub trait ToTokens {
42
46
fn to_tokens ( & self , _cx : & ExtCtxt ) -> Vec < TokenTree > ;
@@ -310,23 +314,6 @@ pub mod rt {
310
314
)
311
315
}
312
316
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_ }
330
317
impl_to_tokens_lifetime ! { & ' a str }
331
318
impl_to_tokens ! { ( ) }
332
319
impl_to_tokens ! { char }
@@ -399,14 +386,94 @@ pub mod rt {
399
386
400
387
}
401
388
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_ }
402
469
}
403
470
404
471
pub fn expand_quote_tokens < ' cx > ( cx : & ' cx mut ExtCtxt ,
405
472
sp : Span ,
406
473
tts : & [ ast:: TokenTree ] )
407
474
-> Box < base:: MacResult +' cx > {
408
475
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) ;
410
477
base:: MacEager :: expr ( expanded)
411
478
}
412
479
@@ -474,13 +541,13 @@ pub fn expand_quote_matcher(cx: &mut ExtCtxt,
474
541
-> Box < base:: MacResult +' static > {
475
542
let ( cx_expr, tts) = parse_arguments_to_quote ( cx, tts) ;
476
543
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 ( ) ) ;
478
545
let block = cx. expr_block (
479
546
cx. block_all ( sp,
480
547
vector,
481
548
Some ( cx. expr_ident ( sp, id_ext ( "tt" ) ) ) ) ) ;
482
549
483
- let expanded = expand_wrapper ( cx, sp, cx_expr, block, & [ & [ "syntax" , "ext" , "quote" , "rt" ] ] ) ;
550
+ let expanded = expand_wrapper ( cx, sp, cx_expr, block) ;
484
551
base:: MacEager :: expr ( expanded)
485
552
}
486
553
@@ -677,7 +744,8 @@ fn expr_mk_token(cx: &ExtCtxt, sp: Span, tok: &token::Token) -> P<ast::Expr> {
677
744
mk_token_path ( cx, sp, name)
678
745
}
679
746
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 > ) {
681
749
match * tt {
682
750
ast:: TtToken ( sp, SubstNt ( ident, _) ) => {
683
751
// 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
696
764
id_ext ( "extend" ) ,
697
765
vec ! ( e_to_toks) ) ;
698
766
699
- vec ! ( cx. stmt_expr( e_push) )
767
+ ( vec ! [ cx. stmt_expr( e_push) ] , vec ! [ ident ] )
700
768
}
701
769
ref tt @ ast:: TtToken ( _, MatchNt ( ..) ) if !matcher => {
702
770
let mut seq = vec ! [ ] ;
@@ -715,56 +783,122 @@ fn statements_mk_tt(cx: &ExtCtxt, tt: &ast::TokenTree, matcher: bool) -> Vec<P<a
715
783
cx. expr_ident ( sp, id_ext ( "tt" ) ) ,
716
784
id_ext ( "push" ) ,
717
785
vec ! ( e_tok) ) ;
718
- vec ! ( cx. stmt_expr( e_push) )
786
+ ( vec ! [ cx. stmt_expr( e_push) ] , vec ! [ ] )
719
787
} ,
720
788
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)
726
795
} ,
727
796
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), c...) in a.zip(b).zip(c)... {
837
+ // // (quasiquotation with $a, $b, $c, ...)
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
+ }
731
844
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_call_ident(sp, id_ext("unquote_wrap"),
850
+ // vec![zipped,
851
+ // one_or_more]);
852
+ zipped = cx. expr_method_call ( sp, zipped, id_ext ( "into_wrapped_iter" ) ,
853
+ vec ! [ one_or_more. clone( ) ] ) ;
854
+ let mut pat = cx. pat_ident ( sp, first) ;
855
+ for ident in iter {
856
+ // Assertion: zipped iterators must have at least one element.
857
+ let expr_ident = cx. expr_ident ( sp, ident) ;
858
+ // let expr = cx.expr_call_ident(sp, id_ext("iter_wrap"),
859
+ // vec![expr_ident,
860
+ // one_or_more]);
861
+ let expr = cx. expr_method_call ( sp, expr_ident,
862
+ id_ext ( "into_wrapped_iter" ) ,
863
+ vec ! [ one_or_more. clone( ) ] ) ;
864
+ zipped = cx. expr_method_call ( sp, zipped, id_ext ( "zip" ) , vec ! [ expr] ) ;
865
+ pat = cx. pat_tuple ( sp, vec ! ( pat, cx. pat_ident( sp, ident) ) ) ;
866
+ }
733
867
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 ) )
868
+ match seq . separator {
869
+ Some ( ref tok ) => {
870
+ // Intersperse the separator
871
+ stmts . extend ( statements_mk_tt ( cx , & ast :: TtToken ( sp, tok . clone ( ) ) ,
872
+ false ) . 0 . into_iter ( ) ) ;
873
+ }
874
+ None => { }
875
+ }
876
+
877
+ let stmt_for = cx . stmt_expr ( P ( ast :: Expr {
878
+ id : ast :: DUMMY_NODE_ID ,
879
+ node : ast:: ExprForLoop ( pat , zipped , cx . block ( sp , stmts , None ) , None ) ,
880
+ span : sp ,
881
+ } ) ) ;
882
+
883
+ let stmts_for = if seq . separator . is_some ( ) {
884
+ // Pop the last occurence of the separator
885
+ let tt = cx. expr_ident ( sp, id_ext ( "tt" ) ) ;
886
+ let len = cx . expr_method_call ( sp , tt . clone ( ) , id_ext ( "len " ) , vec ! ( ) ) ;
887
+ let _len_ident = gensym_ident ( "_len" ) ;
888
+ let _len = cx. expr_ident ( sp, _len_ident ) ;
889
+ let cond = cx . expr_binary ( sp , ast :: BiNe , len . clone ( ) , _len ) ;
890
+ let then = cx . expr_method_call ( sp , tt , id_ext ( "pop " ) , vec ! ( ) ) ;
891
+ let then = cx . expr_block ( cx . block ( sp , vec ! [ cx . stmt_expr ( then ) ] , None ) ) ;
892
+ let if_len_eq = cx . expr_if ( sp , cond , then , None ) ;
893
+ vec ! [ cx. stmt_let ( sp, false , _len_ident , len ) ,
894
+ stmt_for ,
895
+ cx . stmt_expr ( if_len_eq ) ]
896
+ } else {
897
+ vec ! [ stmt_for ]
898
+ } ;
899
+
900
+ ( stmts_for , idents )
901
+ }
768
902
}
769
903
}
770
904
}
@@ -832,20 +966,24 @@ fn mk_stmts_let(cx: &ExtCtxt, sp: Span) -> Vec<P<ast::Stmt>> {
832
966
vec ! ( stmt_let_sp, stmt_let_tt)
833
967
}
834
968
835
- fn statements_mk_tts ( cx : & ExtCtxt , tts : & [ ast:: TokenTree ] , matcher : bool ) -> Vec < P < ast:: Stmt > > {
836
- let mut ss = Vec :: new ( ) ;
969
+ fn statements_mk_tts ( cx : & ExtCtxt , tts : & [ ast:: TokenTree ] , matcher : bool ) -> ( Vec < P < ast:: Stmt > > ,
970
+ Vec < ast:: Ident > ) {
971
+ let mut stmts = Vec :: new ( ) ;
972
+ let mut idents = Vec :: new ( ) ;
837
973
for tt in tts {
838
- ss. extend ( statements_mk_tt ( cx, tt, matcher) . into_iter ( ) ) ;
974
+ let ( ss, is) = statements_mk_tt ( cx, tt, matcher) ;
975
+ stmts. extend ( ss. into_iter ( ) ) ;
976
+ idents. extend ( is. into_iter ( ) ) ;
839
977
}
840
- ss
978
+ ( stmts , idents )
841
979
}
842
980
843
981
fn expand_tts ( cx : & ExtCtxt , sp : Span , tts : & [ ast:: TokenTree ] )
844
982
-> ( P < ast:: Expr > , P < ast:: Expr > ) {
845
983
let ( cx_expr, tts) = parse_arguments_to_quote ( cx, tts) ;
846
984
847
985
let mut vector = mk_stmts_let ( cx, sp) ;
848
- vector. extend ( statements_mk_tts ( cx, & tts[ ..] , false ) . into_iter ( ) ) ;
986
+ vector. extend ( statements_mk_tts ( cx, & tts[ ..] , false ) . 0 . into_iter ( ) ) ;
849
987
let block = cx. expr_block (
850
988
cx. block_all ( sp,
851
989
vector,
@@ -857,13 +995,14 @@ fn expand_tts(cx: &ExtCtxt, sp: Span, tts: &[ast::TokenTree])
857
995
fn expand_wrapper ( cx : & ExtCtxt ,
858
996
sp : Span ,
859
997
cx_expr : P < ast:: Expr > ,
860
- expr : P < ast:: Expr > ,
861
- imports : & [ & [ & str ] ] ) -> P < ast:: Expr > {
998
+ expr : P < ast:: Expr > ) -> P < ast:: Expr > {
862
999
// Explicitly borrow to avoid moving from the invoker (#16992)
863
1000
let cx_expr_borrow = cx. expr_addr_of ( sp, cx. expr_deref ( sp, cx_expr) ) ;
864
1001
let stmt_let_ext_cx = cx. stmt_let ( sp, false , id_ext ( "ext_cx" ) , cx_expr_borrow) ;
865
1002
866
- let stmts = imports. iter ( ) . map ( |path| {
1003
+ let stmts = [
1004
+ & [ "syntax" , "ext" , "quote" , "rt" ]
1005
+ ] . iter ( ) . map ( |path| {
867
1006
// make item: `use ...;`
868
1007
let path = path. iter ( ) . map ( |s| s. to_string ( ) ) . collect ( ) ;
869
1008
cx. stmt_item ( sp, cx. item_use_glob ( sp, ast:: Inherited , ids_ext ( path) ) )
@@ -895,10 +1034,5 @@ fn expand_parse_call(cx: &ExtCtxt,
895
1034
let expr = cx. expr_method_call ( sp, new_parser_call, id_ext ( parse_method) ,
896
1035
arg_exprs) ;
897
1036
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
- }
1037
+ expand_wrapper ( cx, sp, cx_expr, expr)
904
1038
}
0 commit comments