@@ -49,11 +49,13 @@ struct Context<'a, 'b:'a> {
49
49
name_types : HashMap < String , ArgumentType > ,
50
50
name_ordering : Vec < String > ,
51
51
52
- /// The latest consecutive literal strings
53
- literal : Option < String > ,
52
+ /// The latest consecutive literal strings, or empty if there weren't any.
53
+ literal : String ,
54
54
55
- /// Collection of the compiled `rt::Piece ` structures
55
+ /// Collection of the compiled `rt::Argument ` structures
56
56
pieces : Vec < Gc < ast:: Expr > > ,
57
+ /// Collection of string literals
58
+ str_pieces : Vec < Gc < ast:: Expr > > ,
57
59
name_positions : HashMap < String , uint > ,
58
60
method_statics : Vec < Gc < ast:: Item > > ,
59
61
@@ -370,28 +372,22 @@ impl<'a, 'b> Context<'a, 'b> {
370
372
}
371
373
}
372
374
373
- /// Translate the accumulated string literals to a static `rt::Piece`
374
- fn trans_literal_string ( & mut self ) -> Option < Gc < ast:: Expr > > {
375
+ /// Translate the accumulated string literals to a literal expression
376
+ fn trans_literal_string ( & mut self ) -> Gc < ast:: Expr > {
375
377
let sp = self . fmtsp ;
376
- self . literal . take ( ) . map ( |s| {
377
- let s = token:: intern_and_get_ident ( s. as_slice ( ) ) ;
378
- self . ecx . expr_call_global ( sp,
379
- self . rtpath ( "String" ) ,
380
- vec ! (
381
- self . ecx. expr_str( sp, s)
382
- ) )
383
- } )
378
+ let s = token:: intern_and_get_ident ( self . literal . as_slice ( ) ) ;
379
+ self . literal . clear ( ) ;
380
+ self . ecx . expr_str ( sp, s)
384
381
}
385
382
386
- /// Translate a `parse::Piece` to a static `rt::Piece`
383
+ /// Translate a `parse::Piece` to a static `rt::Argument` or append
384
+ /// to the `literal` string.
387
385
fn trans_piece ( & mut self , piece : & parse:: Piece ) -> Option < Gc < ast:: Expr > > {
386
+ // let mut is_not_default = true;
388
387
let sp = self . fmtsp ;
389
388
match * piece {
390
389
parse:: String ( s) => {
391
- match self . literal {
392
- Some ( ref mut sb) => sb. push_str ( s) ,
393
- ref mut empty => * empty = Some ( String :: from_str ( s) ) ,
394
- }
390
+ self . literal . push_str ( s) ;
395
391
None
396
392
}
397
393
parse:: Argument ( ref arg) => {
@@ -450,10 +446,9 @@ impl<'a, 'b> Context<'a, 'b> {
450
446
self . ecx. field_imm( sp, self . ecx. ident_of( "width" ) , width) ) ) ;
451
447
452
448
let path = self . ecx . path_global ( sp, self . rtpath ( "Argument" ) ) ;
453
- let s = self . ecx . expr_struct ( sp, path, vec ! (
449
+ Some ( self . ecx . expr_struct ( sp, path, vec ! (
454
450
self . ecx. field_imm( sp, self . ecx. ident_of( "position" ) , pos) ,
455
- self . ecx. field_imm( sp, self . ecx. ident_of( "format" ) , fmt) ) ) ;
456
- Some ( self . ecx . expr_call_global ( sp, self . rtpath ( "Argument" ) , vec ! ( s) ) )
451
+ self . ecx. field_imm( sp, self . ecx. ident_of( "format" ) , fmt) ) ) )
457
452
}
458
453
}
459
454
}
@@ -476,14 +471,38 @@ impl<'a, 'b> Context<'a, 'b> {
476
471
477
472
// Next, build up the static array which will become our precompiled
478
473
// format "string"
474
+ let fmt = self . ecx . expr_vec ( self . fmtsp , self . str_pieces . clone ( ) ) ;
475
+ let piece_ty = self . ecx . ty_rptr ( self . fmtsp ,
476
+ self . ecx . ty_ident ( self . fmtsp ,
477
+ self . ecx . ident_of ( "str" ) ) ,
478
+ Some ( self . ecx . lifetime ( self . fmtsp ,
479
+ self . ecx . ident_of (
480
+ "'static" ) . name ) ) ,
481
+ ast:: MutImmutable ) ;
482
+
483
+ let ty = ast:: TyFixedLengthVec (
484
+ piece_ty,
485
+ self . ecx . expr_uint ( self . fmtsp , self . str_pieces . len ( ) )
486
+ ) ;
487
+ let ty = self . ecx . ty ( self . fmtsp , ty) ;
488
+ let st = ast:: ItemStatic ( ty, ast:: MutImmutable , fmt) ;
489
+ let static_str_name = self . ecx . ident_of ( "__STATIC_FMTSTR" ) ;
490
+ let item = self . ecx . item ( self . fmtsp , static_str_name,
491
+ self . static_attrs ( ) , st) ;
492
+ let decl = respan ( self . fmtsp , ast:: DeclItem ( item) ) ;
493
+ lets. push ( box ( GC ) respan( self . fmtsp ,
494
+ ast:: StmtDecl ( box ( GC ) decl, ast:: DUMMY_NODE_ID ) ) ) ;
495
+
496
+ // Then, build up the static array which will become our precompiled
497
+ // format "string"
479
498
let fmt = self . ecx . expr_vec ( self . fmtsp , self . pieces . clone ( ) ) ;
480
499
let piece_ty = self . ecx . ty_path ( self . ecx . path_all (
481
500
self . fmtsp ,
482
501
true , vec ! (
483
502
self . ecx. ident_of( "std" ) ,
484
503
self . ecx. ident_of( "fmt" ) ,
485
504
self . ecx. ident_of( "rt" ) ,
486
- self . ecx. ident_of( "Piece " ) ) ,
505
+ self . ecx. ident_of( "Argument " ) ) ,
487
506
vec ! ( self . ecx. lifetime( self . fmtsp,
488
507
self . ecx. ident_of( "'static" ) . name) ) ,
489
508
Vec :: new ( )
@@ -494,8 +513,8 @@ impl<'a, 'b> Context<'a, 'b> {
494
513
) ;
495
514
let ty = self . ecx . ty ( self . fmtsp , ty) ;
496
515
let st = ast:: ItemStatic ( ty, ast:: MutImmutable , fmt) ;
497
- let static_name = self . ecx . ident_of ( "__STATIC_FMTSTR " ) ;
498
- let item = self . ecx . item ( self . fmtsp , static_name ,
516
+ let static_args_name = self . ecx . ident_of ( "__STATIC_FMTARGS " ) ;
517
+ let item = self . ecx . item ( self . fmtsp , static_args_name ,
499
518
self . static_attrs ( ) , st) ;
500
519
let decl = respan ( self . fmtsp , ast:: DeclItem ( item) ) ;
501
520
lets. push ( box ( GC ) respan( self . fmtsp ,
@@ -545,13 +564,14 @@ impl<'a, 'b> Context<'a, 'b> {
545
564
}
546
565
547
566
// Now create the fmt::Arguments struct with all our locals we created.
548
- let fmt = self . ecx . expr_ident ( self . fmtsp , static_name) ;
567
+ let pieces = self . ecx . expr_ident ( self . fmtsp , static_str_name) ;
568
+ let fmt = self . ecx . expr_ident ( self . fmtsp , static_args_name) ;
549
569
let args_slice = self . ecx . expr_ident ( self . fmtsp , slicename) ;
550
570
let result = self . ecx . expr_call_global ( self . fmtsp , vec ! (
551
571
self . ecx. ident_of( "std" ) ,
552
572
self . ecx. ident_of( "fmt" ) ,
553
573
self . ecx. ident_of( "Arguments" ) ,
554
- self . ecx. ident_of( "new" ) ) , vec ! ( fmt, args_slice) ) ;
574
+ self . ecx. ident_of( "new" ) ) , vec ! ( pieces , fmt, args_slice) ) ;
555
575
556
576
// We did all the work of making sure that the arguments
557
577
// structure is safe, so we can safely have an unsafe block.
@@ -718,8 +738,9 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span,
718
738
name_ordering : name_ordering,
719
739
nest_level : 0 ,
720
740
next_arg : 0 ,
721
- literal : None ,
741
+ literal : String :: new ( ) ,
722
742
pieces : Vec :: new ( ) ,
743
+ str_pieces : Vec :: new ( ) ,
723
744
method_statics : Vec :: new ( ) ,
724
745
fmtsp : sp,
725
746
} ;
@@ -739,8 +760,8 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span,
739
760
cx. verify_piece ( & piece) ;
740
761
match cx. trans_piece ( & piece) {
741
762
Some ( piece) => {
742
- cx. trans_literal_string ( ) . map ( |piece|
743
- cx. pieces . push ( piece ) ) ;
763
+ let s = cx. trans_literal_string ( ) ;
764
+ cx. str_pieces . push ( s ) ;
744
765
cx. pieces . push ( piece) ;
745
766
}
746
767
None => { }
@@ -758,7 +779,10 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span,
758
779
}
759
780
None => { }
760
781
}
761
- cx. trans_literal_string ( ) . map ( |piece| cx. pieces . push ( piece) ) ;
782
+ if !cx. literal . is_empty ( ) {
783
+ let s = cx. trans_literal_string ( ) ;
784
+ cx. str_pieces . push ( s) ;
785
+ }
762
786
763
787
// Make sure that all arguments were used and all arguments have types.
764
788
for ( i, ty) in cx. arg_types . iter ( ) . enumerate ( ) {
0 commit comments