Coverage Report

Created: 2025-09-08 21:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/home/noah/src/ruchy/src/backend/transpiler/dispatcher.rs
Line
Count
Source
1
//! Dispatcher functions to reduce complexity in transpiler
2
//!
3
//! This module contains delegated transpilation functions to keep
4
//! cyclomatic complexity below 10 for each function.
5
6
use super::Transpiler;
7
use crate::frontend::ast::{Expr, ExprKind, Literal};
8
use anyhow::{bail, Result};
9
use proc_macro2::TokenStream;
10
use quote::{format_ident, quote};
11
12
impl Transpiler {
13
    /// Transpile basic expressions (literals, identifiers, strings)
14
0
    pub(super) fn transpile_basic_expr(&self, expr: &Expr) -> Result<TokenStream> {
15
0
        match &expr.kind {
16
0
            ExprKind::Literal(lit) => Ok(Self::transpile_literal(lit)),
17
0
            ExprKind::Identifier(name) => Ok(Self::transpile_identifier(name)),
18
0
            ExprKind::QualifiedName { module, name } => {
19
0
                Ok(Self::transpile_qualified_name(module, name))
20
            }
21
0
            ExprKind::StringInterpolation { parts } => self.transpile_string_interpolation(parts),
22
0
            ExprKind::TypeCast { expr, target_type } => self.transpile_type_cast(expr, target_type),
23
0
            _ => unreachable!("Non-basic expression in transpile_basic_expr"),
24
        }
25
0
    }
26
27
0
    fn transpile_type_cast(&self, expr: &Expr, target_type: &str) -> Result<TokenStream> {
28
0
        let expr_tokens = self.transpile_expr(expr)?;
29
        
30
        // Map Ruchy types to Rust types
31
0
        let rust_type = match target_type {
32
0
            "i32" => quote! { i32 },
33
0
            "i64" => quote! { i64 },
34
0
            "f32" => quote! { f32 },
35
0
            "f64" => quote! { f64 },
36
0
            "usize" => quote! { usize },
37
0
            "u8" => quote! { u8 },
38
0
            "u16" => quote! { u16 },
39
0
            "u32" => quote! { u32 },
40
0
            "u64" => quote! { u64 },
41
0
            "i8" => quote! { i8 },
42
0
            "i16" => quote! { i16 },
43
0
            _ => bail!("Unsupported cast target type: {}", target_type),
44
        };
45
        
46
0
        Ok(quote! { (#expr_tokens as #rust_type) })
47
0
    }
48
49
0
    fn transpile_identifier(name: &str) -> TokenStream {
50
        // Check if this is a module path like "math::add"
51
0
        if name.contains("::") {
52
            // Split into module path components
53
0
            let parts: Vec<&str> = name.split("::").collect();
54
0
            let mut tokens = Vec::new();
55
            
56
0
            for (i, part) in parts.iter().enumerate() {
57
0
                let safe_part = if matches!(*part, "self" | "Self" | "super" | "crate") {
58
0
                    (*part).to_string()
59
0
                } else if Self::is_rust_reserved_keyword(part) {
60
0
                    format!("r#{part}")
61
                } else {
62
0
                    (*part).to_string()
63
                };
64
                
65
0
                let ident = format_ident!("{}", safe_part);
66
0
                tokens.push(quote! { #ident });
67
                
68
0
                if i < parts.len() - 1 {
69
0
                    tokens.push(quote! { :: });
70
0
                }
71
            }
72
            
73
0
            quote! { #(#tokens)* }
74
        } else {
75
            // Handle single identifier with Rust reserved keywords
76
0
            let safe_name = if matches!(name, "self" | "Self" | "super" | "crate") {
77
                // These keywords cannot be raw identifiers, use them as-is
78
0
                name.to_string()
79
0
            } else if Self::is_rust_reserved_keyword(name) {
80
0
                format!("r#{name}")
81
            } else {
82
0
                name.to_string()
83
            };
84
            
85
0
            let ident = format_ident!("{}", safe_name);
86
0
            quote! { #ident }
87
        }
88
0
    }
89
90
0
    fn transpile_qualified_name(module: &str, name: &str) -> TokenStream {
91
        // Handle nested qualified names like "net::TcpListener"
92
0
        let module_parts: Vec<&str> = module.split("::").collect();
93
0
        let name_ident = format_ident!("{}", name);
94
        
95
0
        if module_parts.len() == 1 {
96
            // Simple case: single module name
97
0
            let module_ident = format_ident!("{}", module_parts[0]);
98
0
            quote! { #module_ident::#name_ident }
99
        } else {
100
            // Complex case: nested path like "net::TcpListener"
101
0
            let mut tokens = TokenStream::new();
102
0
            for (i, part) in module_parts.iter().enumerate() {
103
0
                if i > 0 {
104
0
                    tokens.extend(quote! { :: });
105
0
                }
106
0
                let part_ident = format_ident!("{}", part);
107
0
                tokens.extend(quote! { #part_ident });
108
            }
109
0
            quote! { #tokens::#name_ident }
110
        }
111
0
    }
112
113
    /// Transpile operator and control flow expressions (split for complexity)
114
0
    pub(super) fn transpile_operator_control_expr(&self, expr: &Expr) -> Result<TokenStream> {
115
0
        match &expr.kind {
116
            // Operators
117
            ExprKind::Binary { .. }
118
            | ExprKind::Unary { .. }
119
            | ExprKind::Assign { .. }
120
            | ExprKind::CompoundAssign { .. }
121
            | ExprKind::Await { .. }
122
0
            | ExprKind::AsyncBlock { .. } => self.transpile_operator_only_expr(expr),
123
            // Control flow
124
            ExprKind::If { .. }
125
            | ExprKind::IfLet { .. }
126
            | ExprKind::WhileLet { .. }
127
            | ExprKind::Match { .. }
128
            | ExprKind::For { .. }
129
            | ExprKind::While { .. }
130
            | ExprKind::Loop { .. }
131
0
            | ExprKind::TryCatch { .. } => self.transpile_control_flow_only_expr(expr),
132
0
            _ => unreachable!("Non-operator/control expression in transpile_operator_control_expr"),
133
        }
134
0
    }
135
136
0
    fn transpile_operator_only_expr(&self, expr: &Expr) -> Result<TokenStream> {
137
0
        match &expr.kind {
138
0
            ExprKind::Binary { left, op, right } => self.transpile_binary(left, *op, right),
139
0
            ExprKind::Unary { op, operand } => self.transpile_unary(*op, operand),
140
0
            ExprKind::Assign { target, value } => self.transpile_assign(target, value),
141
0
            ExprKind::CompoundAssign { target, op, value } => self.transpile_compound_assign(target, *op, value),
142
0
            ExprKind::Await { expr } => self.transpile_await(expr),
143
0
            ExprKind::AsyncBlock { body } => self.transpile_async_block(body),
144
0
            _ => unreachable!(),
145
        }
146
0
    }
147
148
0
    fn transpile_control_flow_only_expr(&self, expr: &Expr) -> Result<TokenStream> {
149
0
        match &expr.kind {
150
            ExprKind::If {
151
0
                condition,
152
0
                then_branch,
153
0
                else_branch,
154
0
            } => self.transpile_if(condition, then_branch, else_branch.as_deref()),
155
0
            ExprKind::Match { expr, arms } => self.transpile_match(expr, arms),
156
0
            ExprKind::For { var, pattern, iter, body } => self.transpile_for(var, pattern.as_ref(), iter, body),
157
0
            ExprKind::While { condition, body } => self.transpile_while(condition, body),
158
            ExprKind::IfLet {
159
0
                pattern,
160
0
                expr,
161
0
                then_branch,
162
0
                else_branch,
163
0
            } => self.transpile_if_let(pattern, expr, then_branch, else_branch.as_deref()),
164
            ExprKind::WhileLet {
165
0
                pattern,
166
0
                expr,
167
0
                body,
168
0
            } => self.transpile_while_let(pattern, expr, body),
169
0
            ExprKind::Loop { body } => self.transpile_loop(body),
170
0
            ExprKind::TryCatch { try_block, catch_clauses, finally_block } => {
171
0
                self.transpile_try_catch(try_block, catch_clauses, finally_block.as_deref())
172
            }
173
0
            _ => unreachable!(),
174
        }
175
0
    }
176
177
    /// Transpile function-related expressions
178
0
    pub(super) fn transpile_function_expr(&self, expr: &Expr) -> Result<TokenStream> {
179
0
        match &expr.kind {
180
            ExprKind::Function {
181
0
                name,
182
0
                type_params,
183
0
                params,
184
0
                body,
185
0
                is_async,
186
0
                return_type,
187
0
                is_pub,
188
0
            } => self.transpile_function(
189
0
                name,
190
0
                type_params,
191
0
                params,
192
0
                body,
193
0
                *is_async,
194
0
                return_type.as_ref(),
195
0
                *is_pub,
196
0
                &expr.attributes,
197
            ),
198
0
            ExprKind::Lambda { params, body } => self.transpile_lambda(params, body),
199
0
            ExprKind::Call { func, args } => self.transpile_call(func, args),
200
            ExprKind::MethodCall {
201
0
                receiver,
202
0
                method,
203
0
                args,
204
0
            } => self.transpile_method_call(receiver, method, args),
205
0
            ExprKind::Macro { name, args } => self.transpile_macro(name, args),
206
0
            _ => unreachable!("Non-function expression in transpile_function_expr"),
207
        }
208
0
    }
209
210
    /// Transpile macro expressions with clean dispatch pattern
211
    ///
212
    /// This function uses specialized handlers for different macro categories:
213
    /// - Print macros: `println!`, `print!`, `panic!` (string formatting)
214
    /// - Collection macros: `vec!` (simple element transpilation)
215
    /// - Assertion macros: `assert!`, `assert_eq!`, `assert_ne!` (validation + transpilation)
216
    ///
217
    /// # Example Usage
218
    /// This method dispatches to specific macro handlers based on the macro name.
219
    /// For example, `println` calls `transpile_println_macro`, `vec` calls `transpile_vec_macro`, etc.
220
0
    pub(super) fn transpile_macro(&self, name: &str, args: &[Expr]) -> Result<TokenStream> {
221
0
        match name {
222
            // Print macros (string formatting)
223
0
            "println" => self.transpile_println_macro(args),
224
0
            "print" => self.transpile_print_macro(args),
225
0
            "panic" => self.transpile_panic_macro(args),
226
            
227
            // Collection macros (simple transpilation)
228
0
            "vec" => self.transpile_vec_macro(args),
229
            
230
            // Assertion macros (validation + transpilation)
231
0
            "assert" => self.transpile_assert_macro(args),
232
0
            "assert_eq" => self.transpile_assert_eq_macro(args),
233
0
            "assert_ne" => self.transpile_assert_ne_macro(args),
234
            
235
0
            _ => bail!("Unknown macro: {}", name),
236
        }
237
0
    }
238
239
    /// Transpile structure-related expressions
240
0
    pub(super) fn transpile_struct_expr(&self, expr: &Expr) -> Result<TokenStream> {
241
0
        match &expr.kind {
242
            ExprKind::Struct {
243
0
                name,
244
0
                type_params,
245
0
                fields,
246
0
                is_pub,
247
0
            } => self.transpile_struct(name, type_params, fields, *is_pub),
248
0
            ExprKind::StructLiteral { name, fields } => self.transpile_struct_literal(name, fields),
249
0
            ExprKind::ObjectLiteral { fields } => self.transpile_object_literal(fields),
250
0
            ExprKind::FieldAccess { object, field } => self.transpile_field_access(object, field),
251
0
            ExprKind::IndexAccess { object, index } => self.transpile_index_access(object, index),
252
0
            ExprKind::Slice { object, start, end } => self.transpile_slice(object, start.as_deref(), end.as_deref()),
253
0
            _ => unreachable!("Non-struct expression in transpile_struct_expr"),
254
        }
255
0
    }
256
257
    /// Transpile data and error handling expressions (split for complexity)
258
0
    pub(super) fn transpile_data_error_expr(&self, expr: &Expr) -> Result<TokenStream> {
259
0
        match &expr.kind {
260
            ExprKind::DataFrame { .. }
261
            | ExprKind::DataFrameOperation { .. }
262
            | ExprKind::List(_)
263
            | ExprKind::Tuple(_)
264
            | ExprKind::ListComprehension { .. }
265
0
            | ExprKind::Range { .. } => self.transpile_data_only_expr(expr),
266
 ExprKind::Throw { .. }
267
            | ExprKind::Ok { .. }
268
            | ExprKind::Err { .. }
269
            | ExprKind::Some { .. }
270
            | ExprKind::None
271
0
            | ExprKind::Try { .. } => self.transpile_error_only_expr(expr),
272
0
            _ => unreachable!("Non-data/error expression in transpile_data_error_expr"),
273
        }
274
0
    }
275
276
0
    fn transpile_data_only_expr(&self, expr: &Expr) -> Result<TokenStream> {
277
0
        match &expr.kind {
278
0
            ExprKind::DataFrame { columns } => self.transpile_dataframe(columns),
279
0
            ExprKind::DataFrameOperation { source, operation } => {
280
0
                self.transpile_dataframe_operation(source, operation)
281
            }
282
0
            ExprKind::List(elements) => self.transpile_list(elements),
283
0
            ExprKind::Tuple(elements) => self.transpile_tuple(elements),
284
            ExprKind::ListComprehension {
285
0
                element,
286
0
                variable,
287
0
                iterable,
288
0
                condition,
289
            } => {
290
0
                self.transpile_list_comprehension(element, variable, iterable, condition.as_deref())
291
            }
292
            ExprKind::Range {
293
0
                start,
294
0
                end,
295
0
                inclusive,
296
0
            } => self.transpile_range(start, end, *inclusive),
297
0
            _ => unreachable!(),
298
        }
299
0
    }
300
301
0
    fn transpile_error_only_expr(&self, expr: &Expr) -> Result<TokenStream> {
302
0
        match &expr.kind {
303
0
            ExprKind::Throw { expr } => self.transpile_throw(expr),
304
0
            ExprKind::Ok { value } => self.transpile_result_ok(value),
305
0
            ExprKind::Err { error } => self.transpile_result_err(error),
306
0
            ExprKind::Some { value } => self.transpile_option_some(value),
307
0
            ExprKind::None => Ok(quote! { None }),
308
0
            ExprKind::Try { expr } => self.transpile_try_operator(expr),
309
0
            _ => unreachable!(),
310
        }
311
0
    }
312
313
0
    fn transpile_result_ok(&self, value: &Expr) -> Result<TokenStream> {
314
0
        let value_tokens = self.transpile_expr(value)?;
315
0
        Ok(quote! { Ok(#value_tokens) })
316
0
    }
317
318
0
    fn transpile_result_err(&self, error: &Expr) -> Result<TokenStream> {
319
0
        let error_tokens = self.transpile_expr(error)?;
320
        // If error is a string literal, add .to_string() for String error types
321
0
        let final_tokens = match &error.kind {
322
            ExprKind::Literal(crate::frontend::ast::Literal::String(_)) => {
323
0
                quote! { #error_tokens.to_string() }
324
            }
325
0
            _ => error_tokens
326
        };
327
0
        Ok(quote! { Err(#final_tokens) })
328
0
    }
329
    
330
0
    fn transpile_option_some(&self, value: &Expr) -> Result<TokenStream> {
331
0
        let value_tokens = self.transpile_expr(value)?;
332
0
        Ok(quote! { Some(#value_tokens) })
333
0
    }
334
    
335
0
    fn transpile_try_operator(&self, expr: &Expr) -> Result<TokenStream> {
336
0
        let expr_tokens = self.transpile_expr(expr)?;
337
0
        Ok(quote! { #expr_tokens? })
338
0
    }
339
340
    /// Transpile actor system expressions
341
0
    pub(super) fn transpile_actor_expr(&self, expr: &Expr) -> Result<TokenStream> {
342
0
        match &expr.kind {
343
            ExprKind::Actor {
344
0
                name,
345
0
                state,
346
0
                handlers,
347
0
            } => self.transpile_actor(name, state, handlers),
348
0
            ExprKind::Send { actor, message } | ExprKind::ActorSend { actor, message } => {
349
0
                self.transpile_send(actor, message)
350
            }
351
            ExprKind::Ask {
352
0
                actor,
353
0
                message,
354
0
                timeout,
355
0
            } => self.transpile_ask(actor, message, timeout.as_deref()),
356
0
            ExprKind::ActorQuery { actor, message } => {
357
                // Actor query is like Ask without timeout
358
0
                self.transpile_ask(actor, message, None)
359
            }
360
0
            ExprKind::Command { program, args, env, working_dir } => {
361
0
                self.transpile_command(program, args, env, working_dir)
362
            }
363
0
            _ => unreachable!("Non-actor expression in transpile_actor_expr"),
364
        }
365
0
    }
366
367
    /// Transpile miscellaneous expressions
368
0
    pub(super) fn transpile_misc_expr(&self, expr: &Expr) -> Result<TokenStream> {
369
0
        match &expr.kind {
370
            ExprKind::Let {
371
0
                name,
372
                type_annotation: _,
373
0
                value,
374
0
                body,
375
0
                is_mutable,
376
0
            } => self.transpile_let(name, value, body, *is_mutable),
377
            ExprKind::LetPattern {
378
0
                pattern,
379
                type_annotation: _,
380
0
                value,
381
0
                body,
382
                is_mutable: _,
383
0
            } => self.transpile_let_pattern(pattern, value, body),
384
0
            ExprKind::Block(exprs) => self.transpile_block(exprs),
385
0
            ExprKind::Pipeline { expr, stages } => self.transpile_pipeline(expr, stages),
386
0
            ExprKind::Import { path, items } => Ok(Self::transpile_import(path, items)),
387
0
            ExprKind::Module { name, body } => self.transpile_module(name, body),
388
            ExprKind::Trait { .. }
389
            | ExprKind::Impl { .. }
390
            | ExprKind::Extension { .. }
391
0
            | ExprKind::Enum { .. } => self.transpile_type_decl_expr(expr),
392
            ExprKind::Break { .. } | ExprKind::Continue { .. } | ExprKind::Return { .. } | ExprKind::Export { .. } => {
393
0
                Self::transpile_control_misc_expr(expr)
394
            }
395
0
            _ => bail!("Unsupported expression kind: {:?}", expr.kind),
396
        }
397
0
    }
398
399
0
    fn transpile_type_decl_expr(&self, expr: &Expr) -> Result<TokenStream> {
400
0
        match &expr.kind {
401
            ExprKind::Trait {
402
0
                name,
403
0
                type_params,
404
0
                methods,
405
0
                is_pub,
406
0
            } => self.transpile_trait(name, type_params, methods, *is_pub),
407
            ExprKind::Impl {
408
0
                type_params,
409
0
                trait_name,
410
0
                for_type,
411
0
                methods,
412
0
                is_pub,
413
0
            } => self.transpile_impl(for_type, type_params, trait_name.as_deref(), methods, *is_pub),
414
            ExprKind::Extension {
415
0
                target_type,
416
0
                methods,
417
0
            } => self.transpile_extend(target_type, methods),
418
            ExprKind::Enum {
419
0
                name,
420
0
                type_params,
421
0
                variants,
422
0
                is_pub,
423
0
            } => self.transpile_enum(name, type_params, variants, *is_pub),
424
0
            _ => unreachable!(),
425
        }
426
0
    }
427
428
    /// Transpile println! macro with string formatting support
429
    /// 
430
    /// Handles string literals, string interpolation, and format strings correctly.
431
    /// Complexity: <10 per Toyota Way requirement.
432
    /// 
433
    /// # Example Usage
434
    /// Transpiles arguments and wraps them in Rust's `println!` macro.
435
    /// Empty args produce `println!()`, otherwise `println!(arg1, arg2, ...)`
436
0
    fn transpile_println_macro(&self, args: &[Expr]) -> Result<TokenStream> {
437
0
        let arg_tokens = self.transpile_print_args(args)?;
438
0
        if arg_tokens.is_empty() {
439
0
            Ok(quote! { println!() })
440
        } else {
441
0
            Ok(quote! { println!(#(#arg_tokens),*) })
442
        }
443
0
    }
444
445
    /// Transpile print! macro with string formatting support
446
    /// 
447
    /// Handles string literals, string interpolation, and format strings correctly.
448
    /// Complexity: <10 per Toyota Way requirement.
449
    /// 
450
    /// # Example Usage
451
    /// Transpiles arguments and wraps them in Rust's `print!` macro.
452
    /// Empty args produce `print!()`, otherwise `print!(arg1, arg2, ...)`
453
0
    fn transpile_print_macro(&self, args: &[Expr]) -> Result<TokenStream> {
454
0
        let arg_tokens = self.transpile_print_args(args)?;
455
0
        if arg_tokens.is_empty() {
456
0
            Ok(quote! { print!() })
457
        } else {
458
0
            Ok(quote! { print!(#(#arg_tokens),*) })
459
        }
460
0
    }
461
462
    /// Transpile panic! macro with string formatting support
463
    /// 
464
    /// Handles string literals, string interpolation, and format strings correctly.
465
    /// Complexity: <10 per Toyota Way requirement.
466
    /// 
467
    /// # Example Usage
468
    /// Transpiles arguments and wraps them in Rust's `panic!` macro.
469
    /// Empty args produce `panic!()`, otherwise `panic!(arg1, arg2, ...)`
470
0
    fn transpile_panic_macro(&self, args: &[Expr]) -> Result<TokenStream> {
471
0
        let arg_tokens = self.transpile_print_args(args)?;
472
0
        if arg_tokens.is_empty() {
473
0
            Ok(quote! { panic!() })
474
        } else {
475
0
            Ok(quote! { panic!(#(#arg_tokens),*) })
476
        }
477
0
    }
478
479
    /// Common helper for transpiling print-style macro arguments
480
    /// 
481
    /// Handles string literals, string interpolation, and format strings.
482
    /// This eliminates code duplication between println!, print!, and panic!.
483
    /// Complexity: <10 per Toyota Way requirement.
484
0
    fn transpile_print_args(&self, args: &[Expr]) -> Result<Vec<TokenStream>> {
485
0
        if args.is_empty() {
486
0
            return Ok(vec![]);
487
0
        }
488
        
489
        // Check if first argument is a format string (contains {})
490
0
        let first_is_format_string = match &args[0].kind {
491
0
            ExprKind::Literal(Literal::String(s)) => s.contains("{}"),
492
0
            _ => false,
493
        };
494
        
495
0
        if first_is_format_string && args.len() > 1 {
496
            // First argument is format string, rest are values
497
0
            let format_str = match &args[0].kind {
498
0
                ExprKind::Literal(Literal::String(s)) => s,
499
0
                _ => unreachable!(),
500
            };
501
            
502
0
            let mut tokens = vec![quote! { #format_str }];
503
            
504
            // Add remaining arguments as values (without extra format strings)
505
0
            for arg in &args[1..] {
506
0
                let expr_tokens = self.transpile_expr(arg)?;
507
0
                tokens.push(expr_tokens);
508
            }
509
            
510
0
            Ok(tokens)
511
        } else {
512
            // Original behavior for non-format cases
513
0
            args.iter()
514
0
                .map(|arg| {
515
0
                    match &arg.kind {
516
0
                        ExprKind::Literal(Literal::String(s)) => {
517
0
                            Ok(quote! { #s })
518
                        }
519
0
                        ExprKind::StringInterpolation { parts } => {
520
0
                            self.transpile_string_interpolation_for_print(parts)
521
                        }
522
                        _ => {
523
                            // Use Display formatting ({}) for simple values, Debug formatting ({:?}) for complex types
524
0
                            let expr_tokens = self.transpile_expr(arg)?;
525
0
                            match &arg.kind {
526
                                // Simple types that have clean Display formatting
527
                                ExprKind::Literal(_) | ExprKind::Identifier(_) => {
528
0
                                    Ok(quote! { "{}", #expr_tokens })
529
                                }
530
                                // Complex types that need Debug formatting for safety
531
                                _ => {
532
0
                                    Ok(quote! { "{:?}", #expr_tokens })
533
                                }
534
                            }
535
                        }
536
                    }
537
0
                })
538
0
                .collect()
539
        }
540
0
    }
541
542
543
    /// Handle string interpolation for print-style macros
544
    /// 
545
    /// Detects if string interpolation has expressions or is just format text.
546
    /// Complexity: <10 per Toyota Way requirement.
547
0
    fn transpile_string_interpolation_for_print(&self, parts: &[crate::frontend::ast::StringPart]) -> Result<TokenStream> {
548
0
        let has_expressions = parts.iter().any(|part| matches!(part, 
549
            crate::frontend::ast::StringPart::Expr(_) | 
550
            crate::frontend::ast::StringPart::ExprWithFormat { .. }));
551
        
552
0
        if has_expressions {
553
            // This has actual interpolation - transpile normally
554
0
            self.transpile_string_interpolation(parts)
555
        } else {
556
            // This is a format string like "Hello {}" - treat as literal
557
0
            let format_string = parts.iter()
558
0
                .map(|part| match part {
559
0
                    crate::frontend::ast::StringPart::Text(s) => s.as_str(),
560
                    crate::frontend::ast::StringPart::Expr(_) | 
561
0
                    crate::frontend::ast::StringPart::ExprWithFormat { .. } => unreachable!()
562
0
                })
563
0
                .collect::<String>();
564
0
            Ok(quote! { #format_string })
565
        }
566
0
    }
567
568
    /// Transpile vec! macro
569
    /// 
570
    /// Simple element-by-element transpilation for collection creation.
571
    /// Complexity: <10 per Toyota Way requirement.
572
    /// 
573
    /// # Example Usage
574
    /// Transpiles list elements and wraps them in Rust's `vec!` macro.
575
    /// Produces `vec![elem1, elem2, ...]`
576
0
    fn transpile_vec_macro(&self, args: &[Expr]) -> Result<TokenStream> {
577
0
        let arg_tokens: Result<Vec<_>, _> = args
578
0
            .iter()
579
0
            .map(|arg| self.transpile_expr(arg))
580
0
            .collect();
581
0
        let arg_tokens = arg_tokens?;
582
583
0
        Ok(quote! { vec![#(#arg_tokens),*] })
584
0
    }
585
586
    /// Transpile assert! macro
587
    /// 
588
    /// Simple argument transpilation for basic assertions.
589
    /// Complexity: <10 per Toyota Way requirement.
590
    /// 
591
    /// # Example Usage
592
    /// Transpiles assertion condition and wraps it in Rust's `assert!` macro.
593
    /// Produces `assert!(condition, optional_message)`
594
0
    fn transpile_assert_macro(&self, args: &[Expr]) -> Result<TokenStream> {
595
0
        let arg_tokens: Result<Vec<_>, _> = args
596
0
            .iter()
597
0
            .map(|arg| self.transpile_expr(arg))
598
0
            .collect();
599
0
        let arg_tokens = arg_tokens?;
600
601
0
        if arg_tokens.is_empty() {
602
0
            Ok(quote! { assert!() })
603
        } else {
604
0
            Ok(quote! { assert!(#(#arg_tokens),*) })
605
        }
606
0
    }
607
608
    /// Transpile `assert_eq`! macro with validation
609
    /// 
610
    /// Validates argument count and transpiles for equality assertions.
611
    /// Complexity: <10 per Toyota Way requirement.
612
    /// 
613
    /// # Example Usage
614
    /// Validates at least 2 arguments and transpiles to Rust's `assert_eq!` macro.
615
    /// Produces `assert_eq!(left, right, optional_message)`
616
0
    fn transpile_assert_eq_macro(&self, args: &[Expr]) -> Result<TokenStream> {
617
0
        if args.len() < 2 {
618
0
            bail!("assert_eq! requires at least 2 arguments")
619
0
        }
620
        
621
0
        let arg_tokens: Result<Vec<_>, _> = args
622
0
            .iter()
623
0
            .map(|arg| self.transpile_expr(arg))
624
0
            .collect();
625
0
        let arg_tokens = arg_tokens?;
626
627
0
        Ok(quote! { assert_eq!(#(#arg_tokens),*) })
628
0
    }
629
630
    /// Transpile `assert_ne`! macro with validation
631
    /// 
632
    /// Validates argument count and transpiles for inequality assertions.
633
    /// Complexity: <10 per Toyota Way requirement.
634
    /// 
635
    /// # Example Usage
636
    /// Validates at least 2 arguments and transpiles to Rust's `assert_ne!` macro.
637
    /// Produces `assert_ne!(left, right, optional_message)`
638
0
    fn transpile_assert_ne_macro(&self, args: &[Expr]) -> Result<TokenStream> {
639
0
        if args.len() < 2 {
640
0
            bail!("assert_ne! requires at least 2 arguments")
641
0
        }
642
        
643
0
        let arg_tokens: Result<Vec<_>, _> = args
644
0
            .iter()
645
0
            .map(|arg| self.transpile_expr(arg))
646
0
            .collect();
647
0
        let arg_tokens = arg_tokens?;
648
649
0
        Ok(quote! { assert_ne!(#(#arg_tokens),*) })
650
0
    }
651
652
0
    fn transpile_control_misc_expr(expr: &Expr) -> Result<TokenStream> {
653
0
        match &expr.kind {
654
0
            ExprKind::Break { label } => Ok(Self::make_break_continue(true, label.as_ref())),
655
0
            ExprKind::Continue { label } => Ok(Self::make_break_continue(false, label.as_ref())),
656
0
            ExprKind::Return { value } => {
657
0
                if let Some(val) = value {
658
0
                    let transpiler = Transpiler::new();
659
0
                    let val_tokens = transpiler.transpile_expr(val)?;
660
0
                    Ok(quote! { return #val_tokens })
661
                } else {
662
0
                    Ok(quote! { return })
663
                }
664
            }
665
0
            ExprKind::Export { items } => {
666
0
                let item_idents: Vec<_> =
667
0
                    items.iter().map(|item| format_ident!("{}", item)).collect();
668
0
                Ok(quote! { pub use { #(#item_idents),* }; })
669
            }
670
0
            _ => unreachable!(),
671
        }
672
0
    }
673
674
0
    fn make_break_continue(is_break: bool, label: Option<&String>) -> TokenStream {
675
0
        let keyword = if is_break {
676
0
            quote! { break }
677
        } else {
678
0
            quote! { continue }
679
        };
680
0
        match label {
681
0
            Some(l) => {
682
0
                let label_ident = format_ident!("{}", l);
683
0
                quote! { #keyword #label_ident }
684
            }
685
0
            None => keyword,
686
        }
687
0
    }
688
689
}