@@ -5,7 +5,7 @@ use crate::alloc::prelude::*;
5
5
use crate :: alloc:: { self , BTreeMap , BTreeSet , Box , HashMap , String , Vec } ;
6
6
use crate :: ast:: { self , Span , Spanned } ;
7
7
use crate :: compile:: { self , WithSpan } ;
8
- use crate :: macros:: { quote, MacroContext , Quote } ;
8
+ use crate :: macros:: { quote, MacroContext , Quote , ToTokens , TokenStream } ;
9
9
use crate :: parse:: { Parse , Parser , Peek , Peeker } ;
10
10
use crate :: runtime:: format;
11
11
use crate :: runtime:: ValueKind ;
@@ -49,14 +49,11 @@ impl FormatArgs {
49
49
}
50
50
}
51
51
52
- let format = match format. take_kind ( ) . with_span ( & self . format ) ? {
53
- ValueKind :: String ( string) => string,
54
- _ => {
55
- return Err ( compile:: Error :: msg (
56
- & self . format ,
57
- "format argument must be a string" ,
58
- ) ) ;
59
- }
52
+ let ValueKind :: String ( format) = format. take_kind ( ) . with_span ( & self . format ) ? else {
53
+ return Err ( compile:: Error :: msg (
54
+ & self . format ,
55
+ "format argument must be a string" ,
56
+ ) ) ;
60
57
} ;
61
58
62
59
let mut unused_pos = ( 0 ..pos. len ( ) ) . try_collect :: < BTreeSet < _ > > ( ) ?;
@@ -65,19 +62,19 @@ impl FormatArgs {
65
62
. map ( |( key, n) | Ok :: < _ , alloc:: Error > ( ( key. try_clone ( ) ?, n. span ( ) ) ) )
66
63
. try_collect :: < alloc:: Result < BTreeMap < _ , _ > > > ( ) ??;
67
64
68
- let expanded = match expand_format_spec (
65
+ let result = expand_format_spec (
69
66
cx,
70
67
self . format . span ( ) ,
71
68
& format,
72
69
& pos,
73
70
& mut unused_pos,
74
71
& named,
75
72
& mut unused_named,
76
- ) {
73
+ ) ;
74
+
75
+ let expanded = match result {
77
76
Ok ( expanded) => expanded,
78
- Err ( message) => {
79
- return Err ( compile:: Error :: msg ( self . format . span ( ) , message) ) ;
80
- }
77
+ Err ( message) => return Err ( compile:: Error :: msg ( self . format . span ( ) , message) ) ,
81
78
} ;
82
79
83
80
if let Some ( expr) = unused_pos. into_iter ( ) . flat_map ( |n| pos. get ( n) ) . next ( ) {
@@ -174,18 +171,27 @@ fn expand_format_spec<'a>(
174
171
let mut name = String :: new ( ) ;
175
172
let mut width = String :: new ( ) ;
176
173
let mut precision = String :: new ( ) ;
177
- let mut buf = String :: new ( ) ;
178
174
175
+ let mut buf = String :: new ( ) ;
179
176
let mut components = Vec :: new ( ) ;
180
177
let mut count = 0 ;
178
+ let mut start = Some ( 0 ) ;
181
179
182
- while let Some ( value ) = iter. next ( ) {
183
- match value {
180
+ while let Some ( ( at , a , b ) ) = iter. next ( ) {
181
+ match ( a , b ) {
184
182
( '}' , '}' ) => {
183
+ if let Some ( start) = start. take ( ) {
184
+ buf. try_push_str ( & input[ start..at] ) ?;
185
+ }
186
+
185
187
buf. try_push ( '}' ) ?;
186
188
iter. next ( ) ;
187
189
}
188
190
( '{' , '{' ) => {
191
+ if let Some ( start) = start. take ( ) {
192
+ buf. try_push_str ( & input[ start..at] ) ?;
193
+ }
194
+
189
195
buf. try_push ( '{' ) ?;
190
196
iter. next ( ) ;
191
197
}
@@ -196,8 +202,12 @@ fn expand_format_spec<'a>(
196
202
) ) ;
197
203
}
198
204
( '{' , _) => {
205
+ if let Some ( start) = start. take ( ) {
206
+ buf. try_push_str ( & input[ start..at] ) ?;
207
+ }
208
+
199
209
if !buf. is_empty ( ) {
200
- components. try_push ( C :: Literal ( buf. try_clone ( ) ? . try_into_boxed_str ( ) ?) ) ?;
210
+ components. try_push ( C :: Literal ( Box :: try_from ( & buf[ .. ] ) ?) ) ?;
201
211
buf. clear ( ) ;
202
212
}
203
213
@@ -215,14 +225,20 @@ fn expand_format_spec<'a>(
215
225
unused_named,
216
226
) ?) ?;
217
227
}
218
- ( a, _) => {
219
- buf. try_push ( a) ?;
228
+ _ => {
229
+ if start. is_none ( ) {
230
+ start = Some ( at) ;
231
+ }
220
232
}
221
233
}
222
234
}
223
235
236
+ if let Some ( start) = start. take ( ) {
237
+ buf. try_push_str ( & input[ start..] ) ?;
238
+ }
239
+
224
240
if !buf. is_empty ( ) {
225
- components. try_push ( C :: Literal ( buf. try_clone ( ) ? . try_into_boxed_str ( ) ?) ) ?;
241
+ components. try_push ( C :: Literal ( Box :: try_from ( & buf[ .. ] ) ?) ) ?;
226
242
buf. clear ( ) ;
227
243
}
228
244
@@ -235,7 +251,7 @@ fn expand_format_spec<'a>(
235
251
for c in components {
236
252
match c {
237
253
C :: Literal ( literal) => {
238
- let lit = cx. lit ( & * literal) ?;
254
+ let lit = cx. lit ( literal. as_ref ( ) ) ?;
239
255
args. try_push ( quote ! ( #lit) ) ?;
240
256
}
241
257
C :: Format {
@@ -314,10 +330,28 @@ fn expand_format_spec<'a>(
314
330
#[ builtin] template!( #( args) , * )
315
331
} ) ;
316
332
333
+ enum ExprOrIdent < ' a > {
334
+ Expr ( & ' a ast:: Expr ) ,
335
+ Ident ( ast:: Ident ) ,
336
+ }
337
+
338
+ impl ToTokens for ExprOrIdent < ' _ > {
339
+ fn to_tokens (
340
+ & self ,
341
+ cx : & mut MacroContext < ' _ , ' _ , ' _ > ,
342
+ stream : & mut TokenStream ,
343
+ ) -> alloc:: Result < ( ) > {
344
+ match self {
345
+ Self :: Expr ( expr) => expr. to_tokens ( cx, stream) ,
346
+ Self :: Ident ( ident) => ident. to_tokens ( cx, stream) ,
347
+ }
348
+ }
349
+ }
350
+
317
351
enum C < ' a > {
318
352
Literal ( Box < str > ) ,
319
353
Format {
320
- expr : & ' a ast :: Expr ,
354
+ expr : ExprOrIdent < ' a > ,
321
355
fill : Option < char > ,
322
356
align : Option < format:: Alignment > ,
323
357
width : Option < usize > ,
@@ -384,11 +418,8 @@ fn expand_format_spec<'a>(
384
418
let mut mode = Mode :: Start ;
385
419
386
420
loop {
387
- let ( a, b) = match iter. current ( ) {
388
- Some ( item) => item,
389
- _ => {
390
- return Err ( compile:: Error :: msg ( span, "unexpected end of format string" ) ) ;
391
- }
421
+ let Some ( ( _, a, b) ) = iter. current ( ) else {
422
+ return Err ( compile:: Error :: msg ( span, "unexpected end of format string" ) ) ;
392
423
} ;
393
424
394
425
match mode {
@@ -577,7 +608,20 @@ fn expand_format_spec<'a>(
577
608
None
578
609
} ;
579
610
580
- let expr = if !name. is_empty ( ) {
611
+ let expr = ' expr: {
612
+ if name. is_empty ( ) {
613
+ let Some ( expr) = pos. get ( * count) else {
614
+ return Err ( compile:: Error :: msg (
615
+ span,
616
+ format ! ( "missing positional argument #{count}" ) ,
617
+ ) ) ;
618
+ } ;
619
+
620
+ unused_pos. remove ( count) ;
621
+ * count += 1 ;
622
+ break ' expr ExprOrIdent :: Expr ( expr) ;
623
+ } ;
624
+
581
625
if let Ok ( n) = str:: parse :: < usize > ( name) {
582
626
let expr = match pos. get ( n) {
583
627
Some ( expr) => * expr,
@@ -590,35 +634,17 @@ fn expand_format_spec<'a>(
590
634
} ;
591
635
592
636
unused_pos. remove ( & n) ;
593
- expr
594
- } else {
595
- let expr = match named. get ( name. as_str ( ) ) {
596
- Some ( n) => & n. expr ,
597
- None => {
598
- return Err ( compile:: Error :: msg (
599
- span,
600
- format ! ( "missing named argument `{}`" , name) ,
601
- ) ) ;
602
- }
603
- } ;
637
+ break ' expr ExprOrIdent :: Expr ( expr) ;
638
+ }
604
639
640
+ if let Some ( n) = named. get ( name. as_str ( ) ) {
605
641
unused_named. remove ( name. as_str ( ) ) ;
606
- expr
642
+ break ' expr ExprOrIdent :: Expr ( & n . expr ) ;
607
643
}
608
- } else {
609
- let expr = match pos. get ( * count) {
610
- Some ( expr) => * expr,
611
- None => {
612
- return Err ( compile:: Error :: msg (
613
- span,
614
- format ! ( "missing positional argument #{}" , count) ,
615
- ) ) ;
616
- }
617
- } ;
618
644
619
- unused_pos . remove ( count ) ;
620
- * count += 1 ;
621
- expr
645
+ let mut ident = cx . ident ( name . as_str ( ) ) ? ;
646
+ ident . span = span ;
647
+ ExprOrIdent :: Ident ( ident )
622
648
} ;
623
649
624
650
let width = if !width. is_empty ( ) {
@@ -648,30 +674,28 @@ fn expand_format_spec<'a>(
648
674
}
649
675
650
676
struct Iter < ' a > {
651
- iter : str:: Chars < ' a > ,
652
- a : Option < char > ,
653
- b : Option < char > ,
677
+ iter : str:: CharIndices < ' a > ,
678
+ a : Option < ( usize , char ) > ,
679
+ b : Option < ( usize , char ) > ,
654
680
}
655
681
656
682
impl < ' a > Iter < ' a > {
657
683
fn new ( input : & ' a str ) -> Self {
658
- let mut iter = input. chars ( ) ;
659
-
684
+ let mut iter = input. char_indices ( ) ;
660
685
let a = iter. next ( ) ;
661
686
let b = iter. next ( ) ;
662
-
663
687
Self { iter, a, b }
664
688
}
665
689
666
- fn current ( & self ) -> Option < ( char , char ) > {
667
- let a = self . a ?;
668
- let b = self . b . unwrap_or_default ( ) ;
669
- Some ( ( a, b) )
690
+ fn current ( & self ) -> Option < ( usize , char , char ) > {
691
+ let ( pos , a ) = self . a ?;
692
+ let ( _ , b ) = self . b . unwrap_or_default ( ) ;
693
+ Some ( ( pos , a, b) )
670
694
}
671
695
}
672
696
673
697
impl Iterator for Iter < ' _ > {
674
- type Item = ( char , char ) ;
698
+ type Item = ( usize , char , char ) ;
675
699
676
700
fn next ( & mut self ) -> Option < Self :: Item > {
677
701
let value = self . current ( ) ?;
0 commit comments