@@ -45,12 +45,22 @@ struct Context<'a, 'b:'a> {
4545 /// The span of the format string literal.
4646 fmtsp : Span ,
4747
48- /// Parsed argument expressions and the types that we've found so far for
49- /// them.
48+ /// List of parsed argument expressions.
5049 /// Named expressions are resolved early, and are appended to the end of
5150 /// argument expressions.
51+ ///
52+ /// Example showing the various data structures in motion:
53+ ///
54+ /// * Original: `"{foo:o} {:o} {foo:x} {0:x} {1:o} {:x} {1:x} {0:o}"`
55+ /// * Implicit argument resolution: `"{foo:o} {0:o} {foo:x} {0:x} {1:o} {1:x} {1:x} {0:o}"`
56+ /// * Name resolution: `"{2:o} {0:o} {2:x} {0:x} {1:o} {1:x} {1:x} {0:o}"`
57+ /// * `arg_types` (in JSON): `[[0, 1, 0], [0, 1, 1], [0, 1]]`
58+ /// * `arg_unique_types` (in simplified JSON): `[["o", "x"], ["o", "x"], ["o", "x"]]`
59+ /// * `names` (in JSON): `{"foo": 2}`
5260 args : Vec < P < ast:: Expr > > ,
61+ /// Placeholder slot numbers indexed by argument.
5362 arg_types : Vec < Vec < usize > > ,
63+ /// Unique format specs seen for each argument.
5464 arg_unique_types : Vec < Vec < ArgumentType > > ,
5565 /// Map from named arguments to their resolved indices.
5666 names : HashMap < String , usize > ,
@@ -69,13 +79,31 @@ struct Context<'a, 'b:'a> {
6979 /// final generated static argument array. We record the starting indices
7080 /// corresponding to each positional argument, and number of references
7181 /// consumed so far for each argument, to facilitate correct `Position`
72- /// mapping in `trans_piece`.
82+ /// mapping in `trans_piece`. In effect this can be seen as a "flattened"
83+ /// version of `arg_unique_types`.
84+ ///
85+ /// Again with the example described above in docstring for `args`:
86+ ///
87+ /// * `arg_index_map` (in JSON): `[[0, 1, 0], [2, 3, 3], [4, 5]]`
7388 arg_index_map : Vec < Vec < usize > > ,
7489
90+ /// Starting offset of count argument slots.
7591 count_args_index_offset : usize ,
7692
93+ /// Count argument slots and tracking data structures.
94+ /// Count arguments are separately tracked for de-duplication in case
95+ /// multiple references are made to one argument. For example, in this
96+ /// format string:
97+ ///
98+ /// * Original: `"{:.*} {:.foo$} {1:.*} {:.0$}"`
99+ /// * Implicit argument resolution: `"{1:.0$} {2:.foo$} {1:.3$} {4:.0$}"`
100+ /// * Name resolution: `"{1:.0$} {2:.5$} {1:.3$} {4:.0$}"`
101+ /// * `count_positions` (in JSON): `{0: 0, 5: 1, 3: 2}`
102+ /// * `count_args`: `vec![Exact(0), Exact(5), Exact(3)]`
77103 count_args : Vec < Position > ,
104+ /// Relative slot numbers for count arguments.
78105 count_positions : HashMap < usize , usize > ,
106+ /// Number of count slots assigned.
79107 count_positions_count : usize ,
80108
81109 /// Current position of the implicit positional arg pointer, as if it
@@ -160,6 +188,8 @@ fn parse_args(ecx: &mut ExtCtxt, sp: Span, tts: &[tokenstream::TokenTree])
160188
161189impl < ' a , ' b > Context < ' a , ' b > {
162190 fn resolve_name_inplace ( & self , p : & mut parse:: Piece ) {
191+ // NOTE: the `unwrap_or` branch is needed in case of invalid format
192+ // arguments, e.g. `format_args!("{foo}")`.
163193 let lookup = |s| * self . names . get ( s) . unwrap_or ( & 0 ) ;
164194
165195 match * p {
@@ -178,9 +208,9 @@ impl<'a, 'b> Context<'a, 'b> {
178208 }
179209 }
180210
181- /// Verifies one piece of a parse string. All errors are not emitted as
182- /// fatal so we can continue giving errors about this and possibly other
183- /// format strings.
211+ /// Verifies one piece of a parse string, and remembers it if valid.
212+ /// All errors are not emitted as fatal so we can continue giving errors
213+ /// about this and possibly other format strings.
184214 fn verify_piece ( & mut self , p : & parse:: Piece ) {
185215 match * p {
186216 parse:: String ( ..) => { }
@@ -223,6 +253,8 @@ impl<'a, 'b> Context<'a, 'b> {
223253 }
224254 }
225255
256+ /// Actually verifies and tracks a given format placeholder
257+ /// (a.k.a. argument).
226258 fn verify_arg_type ( & mut self , arg : Position , ty : ArgumentType ) {
227259 match arg {
228260 Exact ( arg) => {
@@ -276,14 +308,15 @@ impl<'a, 'b> Context<'a, 'b> {
276308 }
277309 }
278310
279- // NOTE: Keep the ordering the same as `into_expr`'s expansion would do!
311+ /// Builds the mapping between format placeholders and argument objects.
280312 fn build_index_map ( & mut self ) {
313+ // NOTE: Keep the ordering the same as `into_expr`'s expansion would do!
281314 let args_len = self . args . len ( ) ;
282315 self . arg_index_map . reserve ( args_len) ;
283316
284317 let mut sofar = 0usize ;
285318
286- // Generate mapping for positional args
319+ // Map the arguments
287320 for i in 0 ..args_len {
288321 let ref arg_types = self . arg_types [ i] ;
289322 let mut arg_offsets = Vec :: with_capacity ( arg_types. len ( ) ) ;
@@ -294,8 +327,7 @@ impl<'a, 'b> Context<'a, 'b> {
294327 sofar += self . arg_unique_types [ i] . len ( ) ;
295328 }
296329
297- // Record starting index for counts, which appear just
298- // after the positional args
330+ // Record starting index for counts, which appear just after arguments
299331 self . count_args_index_offset = sofar;
300332 }
301333
@@ -471,8 +503,8 @@ impl<'a, 'b> Context<'a, 'b> {
471503 ecx. expr_block ( ecx. block ( sp, vec ! [ stmt, ecx. stmt_expr( ecx. expr_ident( sp, name) ) ] ) )
472504 }
473505
474- /// Actually builds the expression which the iformat ! block will be expanded
475- /// to
506+ /// Actually builds the expression which the format_args ! block will be
507+ /// expanded to
476508 fn into_expr ( mut self ) -> P < ast:: Expr > {
477509 let mut locals = Vec :: new ( ) ;
478510 let mut counts = Vec :: new ( ) ;
@@ -642,6 +674,8 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, sp: Span,
642674 args : Vec < P < ast:: Expr > > ,
643675 names : HashMap < String , usize > )
644676 -> P < ast:: Expr > {
677+ // NOTE: this verbose way of initializing `Vec<Vec<ArgumentType>>` is because
678+ // `ArgumentType` does not derive `Clone`.
645679 let arg_types: Vec < _ > = ( 0 ..args. len ( ) ) . map ( |_| Vec :: new ( ) ) . collect ( ) ;
646680 let arg_unique_types: Vec < _ > = ( 0 ..args. len ( ) ) . map ( |_| Vec :: new ( ) ) . collect ( ) ;
647681 let macsp = ecx. call_site ( ) ;
0 commit comments