1
- // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
1
+ // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2
2
// file at the top-level directory of this distribution and at
3
3
// http://rust-lang.org/COPYRIGHT.
4
4
//
@@ -401,7 +401,7 @@ pub fn expand_quote_tokens<'cx>(cx: &'cx mut ExtCtxt,
401
401
tts : & [ ast:: TokenTree ] )
402
402
-> Box < base:: MacResult +' cx > {
403
403
let ( cx_expr, expr) = expand_tts ( cx, sp, tts) ;
404
- let expanded = expand_wrapper ( cx, sp, cx_expr, expr) ;
404
+ let expanded = expand_wrapper ( cx, sp, cx_expr, expr, & [ & [ "syntax" , "ext" , "quote" , "rt" ] ] ) ;
405
405
base:: MacEager :: expr ( expanded)
406
406
}
407
407
@@ -465,6 +465,32 @@ pub fn expand_quote_stmt(cx: &mut ExtCtxt,
465
465
base:: MacEager :: expr ( expanded)
466
466
}
467
467
468
+ pub fn expand_quote_attr ( cx : & mut ExtCtxt ,
469
+ sp : Span ,
470
+ tts : & [ ast:: TokenTree ] )
471
+ -> Box < base:: MacResult +' static > {
472
+ let expanded = expand_parse_call ( cx, sp, "parse_attribute" ,
473
+ vec ! ( cx. expr_bool( sp, true ) ) , tts) ;
474
+
475
+ base:: MacEager :: expr ( expanded)
476
+ }
477
+
478
+ pub fn expand_quote_matcher ( cx : & mut ExtCtxt ,
479
+ sp : Span ,
480
+ tts : & [ ast:: TokenTree ] )
481
+ -> Box < base:: MacResult +' static > {
482
+ let ( cx_expr, tts) = parse_arguments_to_quote ( cx, tts) ;
483
+ let mut vector = mk_stmts_let ( cx, sp) ;
484
+ vector. extend ( statements_mk_tts ( cx, & tts[ ..] , true ) . into_iter ( ) ) ;
485
+ let block = cx. expr_block (
486
+ cx. block_all ( sp,
487
+ vector,
488
+ Some ( cx. expr_ident ( sp, id_ext ( "tt" ) ) ) ) ) ;
489
+
490
+ let expanded = expand_wrapper ( cx, sp, cx_expr, block, & [ & [ "syntax" , "ext" , "quote" , "rt" ] ] ) ;
491
+ base:: MacEager :: expr ( expanded)
492
+ }
493
+
468
494
fn ids_ext ( strs : Vec < String > ) -> Vec < ast:: Ident > {
469
495
strs. iter ( ) . map ( |str| str_to_ident ( & ( * str) ) ) . collect ( )
470
496
}
@@ -527,7 +553,7 @@ fn mk_delim(cx: &ExtCtxt, sp: Span, delim: token::DelimToken) -> P<ast::Expr> {
527
553
}
528
554
529
555
#[ allow( non_upper_case_globals) ]
530
- fn mk_token ( cx : & ExtCtxt , sp : Span , tok : & token:: Token ) -> P < ast:: Expr > {
556
+ fn expr_mk_token ( cx : & ExtCtxt , sp : Span , tok : & token:: Token ) -> P < ast:: Expr > {
531
557
macro_rules! mk_lit {
532
558
( $name: expr, $suffix: expr, $( $args: expr) ,* ) => { {
533
559
let inner = cx. expr_call( sp, mk_token_path( cx, sp, $name) , vec![ $( $args) ,* ] ) ;
@@ -606,6 +632,21 @@ fn mk_token(cx: &ExtCtxt, sp: Span, tok: &token::Token) -> P<ast::Expr> {
606
632
vec ! ( mk_name( cx, sp, ident. ident( ) ) ) ) ;
607
633
}
608
634
635
+ token:: MatchNt ( name, kind, namep, kindp) => {
636
+ return cx. expr_call ( sp,
637
+ mk_token_path ( cx, sp, "MatchNt" ) ,
638
+ vec ! ( mk_ident( cx, sp, name) ,
639
+ mk_ident( cx, sp, kind) ,
640
+ match namep {
641
+ ModName => mk_token_path( cx, sp, "ModName" ) ,
642
+ Plain => mk_token_path( cx, sp, "Plain" ) ,
643
+ } ,
644
+ match kindp {
645
+ ModName => mk_token_path( cx, sp, "ModName" ) ,
646
+ Plain => mk_token_path( cx, sp, "Plain" ) ,
647
+ } ) ) ;
648
+ }
649
+
609
650
token:: Interpolated ( _) => panic ! ( "quote! with interpolated token" ) ,
610
651
611
652
_ => ( )
@@ -642,7 +683,7 @@ fn mk_token(cx: &ExtCtxt, sp: Span, tok: &token::Token) -> P<ast::Expr> {
642
683
mk_token_path ( cx, sp, name)
643
684
}
644
685
645
- fn mk_tt ( cx : & ExtCtxt , tt : & ast:: TokenTree ) -> Vec < P < ast:: Stmt > > {
686
+ fn statements_mk_tt ( cx : & ExtCtxt , tt : & ast:: TokenTree , matcher : bool ) -> Vec < P < ast:: Stmt > > {
646
687
match * tt {
647
688
ast:: TtToken ( sp, SubstNt ( ident, _) ) => {
648
689
// tt.extend($ident.to_tokens(ext_cx).into_iter())
@@ -663,18 +704,18 @@ fn mk_tt(cx: &ExtCtxt, tt: &ast::TokenTree) -> Vec<P<ast::Stmt>> {
663
704
664
705
vec ! ( cx. stmt_expr( e_push) )
665
706
}
666
- ref tt @ ast:: TtToken ( _, MatchNt ( ..) ) => {
707
+ ref tt @ ast:: TtToken ( _, MatchNt ( ..) ) if !matcher => {
667
708
let mut seq = vec ! [ ] ;
668
709
for i in 0 ..tt. len ( ) {
669
710
seq. push ( tt. get_tt ( i) ) ;
670
711
}
671
- mk_tts ( cx, & seq[ ..] )
712
+ statements_mk_tts ( cx, & seq[ ..] , matcher )
672
713
}
673
714
ast:: TtToken ( sp, ref tok) => {
674
715
let e_sp = cx. expr_ident ( sp, id_ext ( "_sp" ) ) ;
675
716
let e_tok = cx. expr_call ( sp,
676
717
mk_ast_path ( cx, sp, "TtToken" ) ,
677
- vec ! ( e_sp, mk_token ( cx, sp, tok) ) ) ;
718
+ vec ! ( e_sp, expr_mk_token ( cx, sp, tok) ) ) ;
678
719
let e_push =
679
720
cx. expr_method_call ( sp,
680
721
cx. expr_ident ( sp, id_ext ( "tt" ) ) ,
@@ -683,27 +724,61 @@ fn mk_tt(cx: &ExtCtxt, tt: &ast::TokenTree) -> Vec<P<ast::Stmt>> {
683
724
vec ! ( cx. stmt_expr( e_push) )
684
725
} ,
685
726
ast:: TtDelimited ( _, ref delimed) => {
686
- mk_tt ( cx, & delimed. open_tt ( ) ) . into_iter ( )
687
- . chain ( delimed. tts . iter ( ) . flat_map ( |tt| mk_tt ( cx, tt) . into_iter ( ) ) )
688
- . chain ( mk_tt ( cx, & delimed. close_tt ( ) ) . into_iter ( ) )
727
+ statements_mk_tt ( cx, & delimed. open_tt ( ) , matcher) . into_iter ( )
728
+ . chain ( delimed. tts . iter ( )
729
+ . flat_map ( |tt| statements_mk_tt ( cx, tt, matcher) . into_iter ( ) ) )
730
+ . chain ( statements_mk_tt ( cx, & delimed. close_tt ( ) , matcher) . into_iter ( ) )
689
731
. collect ( )
690
732
} ,
691
- ast:: TtSequence ( ..) => panic ! ( "TtSequence in quote!" ) ,
692
- }
693
- }
733
+ ast:: TtSequence ( sp, ref seq) => {
734
+ if !matcher {
735
+ panic ! ( "TtSequence in quote!" ) ;
736
+ }
694
737
695
- fn mk_tts ( cx : & ExtCtxt , tts : & [ ast:: TokenTree ] ) -> Vec < P < ast:: Stmt > > {
696
- let mut ss = Vec :: new ( ) ;
697
- for tt in tts {
698
- ss. extend ( mk_tt ( cx, tt) . into_iter ( ) ) ;
738
+ let e_sp = cx. expr_ident ( sp, id_ext ( "_sp" ) ) ;
739
+
740
+ let stmt_let_tt = cx. stmt_let ( sp, true , id_ext ( "tt" ) , cx. expr_vec_ng ( sp) ) ;
741
+ let mut tts_stmts = vec ! [ stmt_let_tt] ;
742
+ tts_stmts. extend ( statements_mk_tts ( cx, & seq. tts [ ..] , matcher) . into_iter ( ) ) ;
743
+ let e_tts = cx. expr_block ( cx. block ( sp, tts_stmts,
744
+ Some ( cx. expr_ident ( sp, id_ext ( "tt" ) ) ) ) ) ;
745
+ let e_separator = match seq. separator {
746
+ Some ( ref sep) => cx. expr_some ( sp, expr_mk_token ( cx, sp, sep) ) ,
747
+ None => cx. expr_none ( sp) ,
748
+ } ;
749
+ let e_op = match seq. op {
750
+ ast:: ZeroOrMore => mk_ast_path ( cx, sp, "ZeroOrMore" ) ,
751
+ ast:: OneOrMore => mk_ast_path ( cx, sp, "OneOrMore" ) ,
752
+ } ;
753
+ let fields = vec ! [ cx. field_imm( sp, id_ext( "tts" ) , e_tts) ,
754
+ cx. field_imm( sp, id_ext( "separator" ) , e_separator) ,
755
+ cx. field_imm( sp, id_ext( "op" ) , e_op) ,
756
+ cx. field_imm( sp, id_ext( "num_captures" ) ,
757
+ cx. expr_usize( sp, seq. num_captures) ) ] ;
758
+ let seq_path = vec ! [ id_ext( "syntax" ) , id_ext( "ast" ) , id_ext( "SequenceRepetition" ) ] ;
759
+ let e_seq_struct = cx. expr_struct ( sp, cx. path_global ( sp, seq_path) , fields) ;
760
+ let e_rc_new = cx. expr_call_global ( sp, vec ! [ id_ext( "std" ) ,
761
+ id_ext( "rc" ) ,
762
+ id_ext( "Rc" ) ,
763
+ id_ext( "new" ) ] ,
764
+ vec ! [ e_seq_struct] ) ;
765
+ let e_tok = cx. expr_call ( sp,
766
+ mk_ast_path ( cx, sp, "TtSequence" ) ,
767
+ vec ! ( e_sp, e_rc_new) ) ;
768
+ let e_push =
769
+ cx. expr_method_call ( sp,
770
+ cx. expr_ident ( sp, id_ext ( "tt" ) ) ,
771
+ id_ext ( "push" ) ,
772
+ vec ! ( e_tok) ) ;
773
+ vec ! ( cx. stmt_expr( e_push) )
774
+ }
699
775
}
700
- ss
701
776
}
702
777
703
- fn expand_tts ( cx : & ExtCtxt , sp : Span , tts : & [ ast:: TokenTree ] )
704
- -> ( P < ast:: Expr > , P < ast:: Expr > ) {
778
+ fn parse_arguments_to_quote ( cx : & ExtCtxt , tts : & [ ast:: TokenTree ] )
779
+ -> ( P < ast:: Expr > , Vec < ast:: TokenTree > ) {
705
780
// NB: It appears that the main parser loses its mind if we consider
706
- // $foo as a TtNonterminal during the main parse, so we have to re-parse
781
+ // $foo as a SubstNt during the main parse, so we have to re-parse
707
782
// under quote_depth > 0. This is silly and should go away; the _guess_ is
708
783
// it has to do with transition away from supporting old-style macros, so
709
784
// try removing it when enough of them are gone.
@@ -719,6 +794,10 @@ fn expand_tts(cx: &ExtCtxt, sp: Span, tts: &[ast::TokenTree])
719
794
let tts = p. parse_all_token_trees ( ) ;
720
795
p. abort_if_errors ( ) ;
721
796
797
+ ( cx_expr, tts)
798
+ }
799
+
800
+ fn mk_stmts_let ( cx : & ExtCtxt , sp : Span ) -> Vec < P < ast:: Stmt > > {
722
801
// We also bind a single value, sp, to ext_cx.call_site()
723
802
//
724
803
// This causes every span in a token-tree quote to be attributed to the
@@ -756,8 +835,23 @@ fn expand_tts(cx: &ExtCtxt, sp: Span, tts: &[ast::TokenTree])
756
835
757
836
let stmt_let_tt = cx. stmt_let ( sp, true , id_ext ( "tt" ) , cx. expr_vec_ng ( sp) ) ;
758
837
759
- let mut vector = vec ! ( stmt_let_sp, stmt_let_tt) ;
760
- vector. extend ( mk_tts ( cx, & tts[ ..] ) . into_iter ( ) ) ;
838
+ vec ! ( stmt_let_sp, stmt_let_tt)
839
+ }
840
+
841
+ fn statements_mk_tts ( cx : & ExtCtxt , tts : & [ ast:: TokenTree ] , matcher : bool ) -> Vec < P < ast:: Stmt > > {
842
+ let mut ss = Vec :: new ( ) ;
843
+ for tt in tts {
844
+ ss. extend ( statements_mk_tt ( cx, tt, matcher) . into_iter ( ) ) ;
845
+ }
846
+ ss
847
+ }
848
+
849
+ fn expand_tts ( cx : & ExtCtxt , sp : Span , tts : & [ ast:: TokenTree ] )
850
+ -> ( P < ast:: Expr > , P < ast:: Expr > ) {
851
+ let ( cx_expr, tts) = parse_arguments_to_quote ( cx, tts) ;
852
+
853
+ let mut vector = mk_stmts_let ( cx, sp) ;
854
+ vector. extend ( statements_mk_tts ( cx, & tts[ ..] , false ) . into_iter ( ) ) ;
761
855
let block = cx. expr_block (
762
856
cx. block_all ( sp,
763
857
vector,
@@ -769,14 +863,14 @@ fn expand_tts(cx: &ExtCtxt, sp: Span, tts: &[ast::TokenTree])
769
863
fn expand_wrapper ( cx : & ExtCtxt ,
770
864
sp : Span ,
771
865
cx_expr : P < ast:: Expr > ,
772
- expr : P < ast:: Expr > ) -> P < ast:: Expr > {
866
+ expr : P < ast:: Expr > ,
867
+ imports : & [ & [ & str ] ] ) -> P < ast:: Expr > {
773
868
// Explicitly borrow to avoid moving from the invoker (#16992)
774
869
let cx_expr_borrow = cx. expr_addr_of ( sp, cx. expr_deref ( sp, cx_expr) ) ;
775
870
let stmt_let_ext_cx = cx. stmt_let ( sp, false , id_ext ( "ext_cx" ) , cx_expr_borrow) ;
776
871
777
- let stmts = [
778
- & [ "syntax" , "ext" , "quote" , "rt" ] ,
779
- ] . iter ( ) . map ( |path| {
872
+ let stmts = imports. iter ( ) . map ( |path| {
873
+ // make item: `use ...;`
780
874
let path = path. iter ( ) . map ( |s| s. to_string ( ) ) . collect ( ) ;
781
875
cx. stmt_item ( sp, cx. item_use_glob ( sp, ast:: Inherited , ids_ext ( path) ) )
782
876
} ) . chain ( Some ( stmt_let_ext_cx) . into_iter ( ) ) . collect ( ) ;
@@ -807,5 +901,10 @@ fn expand_parse_call(cx: &ExtCtxt,
807
901
let expr = cx. expr_method_call ( sp, new_parser_call, id_ext ( parse_method) ,
808
902
arg_exprs) ;
809
903
810
- expand_wrapper ( cx, sp, cx_expr, expr)
904
+ if parse_method == "parse_attribute" {
905
+ expand_wrapper ( cx, sp, cx_expr, expr, & [ & [ "syntax" , "ext" , "quote" , "rt" ] ,
906
+ & [ "syntax" , "parse" , "attr" ] ] )
907
+ } else {
908
+ expand_wrapper ( cx, sp, cx_expr, expr, & [ & [ "syntax" , "ext" , "quote" , "rt" ] ] )
909
+ }
811
910
}
0 commit comments