@@ -2997,8 +2997,216 @@ TokenCollector::visit (BareFunctionType &type)
2997
2997
void
2998
2998
TokenCollector::visit (AST::FormatArgs &fmt)
2999
2999
{
3000
- rust_sorry_at (fmt.get_locus (), " %s:%u: unimplemented FormatArgs visitor" ,
3001
- __FILE__, __LINE__);
3000
+ push (Rust::Token::make_identifier (fmt.get_locus (), " format_args" ));
3001
+ push (Rust::Token::make (EXCLAM, fmt.get_locus ()));
3002
+ push (Rust::Token::make (LEFT_PAREN, fmt.get_locus ()));
3003
+
3004
+ std::string reconstructed_template = " \" " ;
3005
+ const auto &template_pieces = fmt.get_template ();
3006
+
3007
+ for (const auto &piece : template_pieces.get_pieces ())
3008
+ {
3009
+ if (piece.tag == Fmt::ffi::Piece::Tag::String)
3010
+ {
3011
+ std::string literal = piece.string ._0 .to_string ();
3012
+ for (char c : literal)
3013
+ {
3014
+ if (c == ' "' || c == ' \\ ' )
3015
+ {
3016
+ reconstructed_template += ' \\ ' ;
3017
+ }
3018
+ else if (c == ' \n ' )
3019
+ {
3020
+ reconstructed_template += " \\ n" ;
3021
+ continue ;
3022
+ }
3023
+ else if (c == ' \r ' )
3024
+ {
3025
+ reconstructed_template += " \\ r" ;
3026
+ continue ;
3027
+ }
3028
+ else if (c == ' \t ' )
3029
+ {
3030
+ reconstructed_template += " \\ t" ;
3031
+ continue ;
3032
+ }
3033
+ reconstructed_template += c;
3034
+ }
3035
+ }
3036
+ else if (piece.tag == Fmt::ffi::Piece::Tag::NextArgument)
3037
+ {
3038
+ reconstructed_template += " {" ;
3039
+
3040
+ const auto &argument = piece.next_argument ._0 ;
3041
+ const auto &position = argument.position ;
3042
+
3043
+ switch (position.tag )
3044
+ {
3045
+ case Fmt::ffi::Position::Tag::ArgumentImplicitlyIs:
3046
+ break ;
3047
+ case Fmt::ffi::Position::Tag::ArgumentIs:
3048
+ reconstructed_template
3049
+ += std::to_string (position.argument_is ._0 );
3050
+ break ;
3051
+ case Fmt::ffi::Position::Tag::ArgumentNamed:
3052
+ reconstructed_template += position.argument_named ._0 .to_string ();
3053
+ break ;
3054
+ }
3055
+
3056
+ // Add format specifiers if any (like :?, :x, etc.)
3057
+ const auto &format_spec = argument.format ;
3058
+
3059
+ bool has_format_spec = false ;
3060
+ std::string format_part;
3061
+
3062
+ // For now, skipping the complex format specifications that use FFIOpt
3063
+ // since FFIOpt::get_opt() has a bug.
3064
+
3065
+ // Alignment
3066
+ if (format_spec.align != Fmt::ffi::Alignment::AlignUnknown)
3067
+ {
3068
+ has_format_spec = true ;
3069
+ switch (format_spec.align )
3070
+ {
3071
+ case Fmt::ffi::Alignment::AlignLeft:
3072
+ format_part += " <" ;
3073
+ break ;
3074
+ case Fmt::ffi::Alignment::AlignRight:
3075
+ format_part += " >" ;
3076
+ break ;
3077
+ case Fmt::ffi::Alignment::AlignCenter:
3078
+ format_part += " ^" ;
3079
+ break ;
3080
+ case Fmt::ffi::Alignment::AlignUnknown:
3081
+ break ;
3082
+ }
3083
+ }
3084
+
3085
+ // Alternate flag
3086
+ if (format_spec.alternate )
3087
+ {
3088
+ has_format_spec = true ;
3089
+ format_part += " #" ;
3090
+ }
3091
+
3092
+ // Zero pad flag
3093
+ if (format_spec.zero_pad )
3094
+ {
3095
+ has_format_spec = true ;
3096
+ format_part += " 0" ;
3097
+ }
3098
+
3099
+ // Width
3100
+ if (format_spec.width .tag != Fmt::ffi::Count::Tag::CountImplied)
3101
+ {
3102
+ has_format_spec = true ;
3103
+ switch (format_spec.width .tag )
3104
+ {
3105
+ case Fmt::ffi::Count::Tag::CountIs:
3106
+ format_part += std::to_string (format_spec.width .count_is ._0 );
3107
+ break ;
3108
+ case Fmt::ffi::Count::Tag::CountIsParam:
3109
+ format_part
3110
+ += std::to_string (format_spec.width .count_is_param ._0 )
3111
+ + " $" ;
3112
+ break ;
3113
+ case Fmt::ffi::Count::Tag::CountIsName:
3114
+ format_part
3115
+ += format_spec.width .count_is_name ._0 .to_string () + " $" ;
3116
+ break ;
3117
+ case Fmt::ffi::Count::Tag::CountIsStar:
3118
+ format_part += " *" ;
3119
+ break ;
3120
+ case Fmt::ffi::Count::Tag::CountImplied:
3121
+ break ;
3122
+ }
3123
+ }
3124
+
3125
+ // Precision
3126
+ if (format_spec.precision .tag != Fmt::ffi::Count::Tag::CountImplied)
3127
+ {
3128
+ has_format_spec = true ;
3129
+ format_part += " ." ;
3130
+ switch (format_spec.precision .tag )
3131
+ {
3132
+ case Fmt::ffi::Count::Tag::CountIs:
3133
+ format_part
3134
+ += std::to_string (format_spec.precision .count_is ._0 );
3135
+ break ;
3136
+ case Fmt::ffi::Count::Tag::CountIsParam:
3137
+ format_part
3138
+ += std::to_string (format_spec.precision .count_is_param ._0 )
3139
+ + " $" ;
3140
+ break ;
3141
+ case Fmt::ffi::Count::Tag::CountIsName:
3142
+ format_part
3143
+ += format_spec.precision .count_is_name ._0 .to_string ()
3144
+ + " $" ;
3145
+ break ;
3146
+ case Fmt::ffi::Count::Tag::CountIsStar:
3147
+ format_part += " *" ;
3148
+ break ;
3149
+ case Fmt::ffi::Count::Tag::CountImplied:
3150
+ break ;
3151
+ }
3152
+ }
3153
+
3154
+ // Type/trait (like ?, x, X, etc.)
3155
+ std::string type_str = format_spec.ty .to_string ();
3156
+ if (!type_str.empty ())
3157
+ {
3158
+ has_format_spec = true ;
3159
+ format_part += type_str;
3160
+ }
3161
+
3162
+ // Add the format specification if any
3163
+ if (has_format_spec)
3164
+ {
3165
+ reconstructed_template += " :" ;
3166
+ reconstructed_template += format_part;
3167
+ }
3168
+
3169
+ reconstructed_template += " }" ;
3170
+ }
3171
+ }
3172
+ reconstructed_template += " \" " ;
3173
+
3174
+ push (Rust::Token::make_string (fmt.get_locus (), reconstructed_template));
3175
+
3176
+ // Visit format arguments if any exist
3177
+ auto &arguments = fmt.get_arguments ();
3178
+ if (!arguments.empty ())
3179
+ {
3180
+ push (Rust::Token::make (COMMA, fmt.get_locus ()));
3181
+
3182
+ auto &args = arguments.get_args ();
3183
+ for (size_t i = 0 ; i < args.size (); ++i)
3184
+ {
3185
+ if (i > 0 )
3186
+ {
3187
+ push (Rust::Token::make (COMMA, fmt.get_locus ()));
3188
+ }
3189
+
3190
+ auto kind = args[i].get_kind ();
3191
+
3192
+ // Handle named arguments: name = expr
3193
+ if (kind.kind == FormatArgumentKind::Kind::Named)
3194
+ {
3195
+ auto ident = kind.get_ident ().as_string ();
3196
+ push (Rust::Token::make_identifier (fmt.get_locus (),
3197
+ std::move (ident)));
3198
+ push (Rust::Token::make (EQUAL, fmt.get_locus ()));
3199
+ }
3200
+ // Note: Captured arguments are handled implicitly in the template
3201
+ // reconstruction They don't need explicit "name =" syntax in the
3202
+ // reconstructed macro call
3203
+
3204
+ auto &expr = args[i].get_expr ();
3205
+ expr.accept_vis (*this );
3206
+ }
3207
+ }
3208
+
3209
+ push (Rust::Token::make (RIGHT_PAREN, fmt.get_locus ()));
3002
3210
}
3003
3211
3004
3212
void
0 commit comments