@@ -57,7 +57,7 @@ struct Context<'a, 'b:'a> {
57
57
/// Collection of the compiled `rt::Argument` structures
58
58
pieces : Vec < P < ast:: Expr > > ,
59
59
/// Collection of string literals
60
- str_pieces : Vec < P < ast :: Expr > > ,
60
+ str_pieces : Vec < ( Span , token :: InternedString ) > ,
61
61
/// Stays `true` if all formatting parameters are default (as in "{}{}").
62
62
all_pieces_simple : bool ,
63
63
@@ -335,11 +335,11 @@ impl<'a, 'b> Context<'a, 'b> {
335
335
}
336
336
337
337
/// Translate the accumulated string literals to a literal expression
338
- fn trans_literal_string ( & mut self ) -> P < ast :: Expr > {
338
+ fn trans_string ( & mut self ) -> ( Span , token :: InternedString ) {
339
339
let sp = self . fmtsp ;
340
340
let s = token:: intern_and_get_ident ( & self . literal [ ] ) ;
341
341
self . literal . clear ( ) ;
342
- self . ecx . expr_str ( sp, s)
342
+ ( sp, s)
343
343
}
344
344
345
345
/// Translate a `parse::Piece` to a static `rt::Argument` or append
@@ -475,10 +475,15 @@ impl<'a, 'b> Context<'a, 'b> {
475
475
self . ecx . ty_ident ( self . fmtsp , self . ecx . ident_of ( "str" ) ) ,
476
476
Some ( static_lifetime) ,
477
477
ast:: MutImmutable ) ;
478
+
479
+ let str_pieces = self . str_pieces . iter ( )
480
+ . map ( |& ( sp, ref s) | self . ecx . expr_str ( sp, s. clone ( ) ) )
481
+ . collect ( ) ;
482
+
478
483
let pieces = Context :: static_array ( self . ecx ,
479
484
"__STATIC_FMTSTR" ,
480
485
piece_ty,
481
- self . str_pieces ) ;
486
+ str_pieces) ;
482
487
483
488
484
489
// Right now there is a bug such that for the expression:
@@ -627,6 +632,43 @@ impl<'a, 'b> Context<'a, 'b> {
627
632
}
628
633
}
629
634
635
+ pub fn expand_format_arg < ' cx > ( ecx : & ' cx mut ExtCtxt , sp : Span ,
636
+ tts : & [ ast:: TokenTree ] )
637
+ -> Box < base:: MacResult +' cx > {
638
+
639
+ match parse_args ( ecx, sp, tts) {
640
+ Some ( ( efmt, args, order, names) ) => {
641
+ if !args. is_empty ( ) || !order. is_empty ( ) || !names. is_empty ( ) {
642
+ ecx. span_err ( sp,
643
+ & format ! ( "requires no arguments, found {}" ,
644
+ args. len( ) + order. len( ) ) ) ;
645
+
646
+ DummyResult :: expr ( sp)
647
+ } else {
648
+ MacExpr :: new ( expand_preparsed_format_arg ( ecx, sp, efmt) )
649
+ }
650
+ }
651
+ None => DummyResult :: expr ( sp)
652
+ }
653
+ }
654
+
655
+ /// Take the various parts of `format_arg!(efmt)`
656
+ /// and construct the appropriate formatting expression.
657
+ pub fn expand_preparsed_format_arg ( ecx : & mut ExtCtxt , sp : Span ,
658
+ efmt : P < ast:: Expr > )
659
+ -> P < ast:: Expr > {
660
+ match parse_format_args ( ecx, sp, efmt, Vec :: new ( ) , Vec :: new ( ) , HashMap :: new ( ) ) {
661
+ Some ( cx) => {
662
+ let mut s = String :: new ( ) ;
663
+ for & ( _, ref part) in cx. str_pieces . iter ( ) {
664
+ s. push_str ( part. as_slice ( ) ) ;
665
+ }
666
+ cx. ecx . expr_str ( sp, token:: intern_and_get_ident ( & s[ ] ) )
667
+ }
668
+ None => DummyResult :: raw_expr ( sp) ,
669
+ }
670
+ }
671
+
630
672
pub fn expand_format_args < ' cx > ( ecx : & ' cx mut ExtCtxt , sp : Span ,
631
673
tts : & [ ast:: TokenTree ] )
632
674
-> Box < base:: MacResult +' cx > {
@@ -648,6 +690,18 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span,
648
690
name_ordering : Vec < String > ,
649
691
names : HashMap < String , P < ast:: Expr > > )
650
692
-> P < ast:: Expr > {
693
+ match parse_format_args ( ecx, sp, efmt, args, name_ordering, names) {
694
+ Some ( cx) => cx. into_expr ( ) ,
695
+ None => DummyResult :: raw_expr ( sp) ,
696
+ }
697
+ }
698
+
699
+ fn parse_format_args < ' a , ' b : ' a > ( ecx : & ' a mut ExtCtxt < ' b > , sp : Span ,
700
+ efmt : P < ast:: Expr > ,
701
+ args : Vec < P < ast:: Expr > > ,
702
+ name_ordering : Vec < String > ,
703
+ names : HashMap < String , P < ast:: Expr > > )
704
+ -> Option < Context < ' a , ' b > > {
651
705
let arg_types: Vec < _ > = ( 0 ..args. len ( ) ) . map ( |_| None ) . collect ( ) ;
652
706
let mut cx = Context {
653
707
ecx : ecx,
@@ -670,7 +724,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span,
670
724
efmt,
671
725
"format argument must be a string literal." ) {
672
726
Some ( ( fmt, _) ) => fmt,
673
- None => return DummyResult :: raw_expr ( sp )
727
+ None => return None
674
728
} ;
675
729
676
730
let mut parser = parse:: Parser :: new ( & fmt) ;
@@ -682,7 +736,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span,
682
736
cx. verify_piece ( & piece) ;
683
737
match cx. trans_piece ( & piece) {
684
738
Some ( piece) => {
685
- let s = cx. trans_literal_string ( ) ;
739
+ let s = cx. trans_string ( ) ;
686
740
cx. str_pieces . push ( s) ;
687
741
cx. pieces . push ( piece) ;
688
742
}
@@ -695,10 +749,10 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span,
695
749
if !parser. errors . is_empty ( ) {
696
750
cx. ecx . span_err ( cx. fmtsp , & format ! ( "invalid format string: {}" ,
697
751
parser. errors. remove( 0 ) ) [ ] ) ;
698
- return DummyResult :: raw_expr ( sp ) ;
752
+ return None ;
699
753
}
700
754
if !cx. literal . is_empty ( ) {
701
- let s = cx. trans_literal_string ( ) ;
755
+ let s = cx. trans_string ( ) ;
702
756
cx. str_pieces . push ( s) ;
703
757
}
704
758
@@ -714,5 +768,5 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span,
714
768
}
715
769
}
716
770
717
- cx . into_expr ( )
771
+ Some ( cx )
718
772
}
0 commit comments