## 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/type_conversion_refactored.rs

    Line
    Count
    Source
    1
    //! Refactored type conversion with reduced complexity
    2
    //! Original complexity: 62, Target: <20 per function
    3
    4
    use crate::backend::Transpiler;
    5
    use crate::frontend::ast::{Expr, ExprKind, Literal, StringPart};
    6
    use anyhow::{bail, Result};
    7
    use proc_macro2::TokenStream;
    8
    use quote::quote;
    9
    10
    impl Transpiler {
    11
        /// Main dispatcher for type conversion (complexity: ~8)
    12
    0
        pub fn try_transpile_type_conversion_refactored(
    13
    0
            &self,
    14
    0
            base_name: &str,
    15
    0
            args: &[Expr]
    16
    0
        ) -> Result<Option<TokenStream>> {
    17
            // Only check known type conversion functions
    18
    0
            match base_name {
    19
    0
                "str" | "int" | "float" | "bool" | "list" | "set" | "dict" => {
    20
                    // These functions require exactly 1 argument
    21
    0
                    if args.len() != 1 {
    22
    0
                        bail!("{base_name}() expects exactly 1 argument");
    23
    0
                    }
    24
                }
    25
    0
                _ => return Ok(None), // Not a type conversion, don't validate
    26
            }
    27
    28
    0
            match base_name {
    29
    0
                "str" => self.convert_to_string(&args[0]),
    30
    0
                "int" => self.convert_to_int(&args[0]),
    31
    0
                "float" => self.convert_to_float(&args[0]),
    32
    0
                "bool" => self.convert_to_bool(&args[0]),
    33
    0
                "list" => self.convert_to_list(&args[0]),
    34
    0
                "set" => self.convert_to_set(&args[0]),
    35
    0
                "dict" => self.convert_to_dict(&args[0]),
    36
    0
                _ => Ok(None), // Not a type conversion
    37
            }
    38
    0
        }
    39
    40
        /// Convert to string (complexity: 3)
    41
    0
        fn convert_to_string(&self, arg: &Expr) -> Result<Option<TokenStream>> {
    42
    0
            let value = self.transpile_expr(arg)?;
    43
    0
            Ok(Some(quote! { format!("{}", #value) }))
    44
    0
        }
    45
    46
        /// Convert to integer (complexity: 12)
    47
    0
        fn convert_to_int(&self, arg: &Expr) -> Result<Option<TokenStream>> {
    48
    0
            match &arg.kind {
    49
                // String literal -> parse
    50
                ExprKind::Literal(Literal::String(_)) => {
    51
    0
                    let value = self.transpile_expr(arg)?;
    52
    0
                    Ok(Some(quote! { #value.parse::<i64>().expect("Failed to parse integer") }))
    53
                }
    54
                // String interpolation with single text part -> parse
    55
    0
                ExprKind::StringInterpolation { parts } if is_single_text_part(parts) => {
    56
    0
                    let value = self.transpile_expr(arg)?;
    57
    0
                    Ok(Some(quote! { #value.parse::<i64>().expect("Failed to parse integer") }))
    58
                }
    59
                // Float literal -> cast
    60
                ExprKind::Literal(Literal::Float(_)) => {
    61
    0
                    let value = self.transpile_expr(arg)?;
    62
    0
                    Ok(Some(quote! { (#value as i64) }))
    63
                }
    64
                // Bool literal -> 0 or 1
    65
                ExprKind::Literal(Literal::Bool(_)) => {
    66
    0
                    let value = self.transpile_expr(arg)?;
    67
    0
                    Ok(Some(quote! { if #value { 1i64 } else { 0i64 } }))
    68
                }
    69
                // Default: runtime cast
    70
                _ => {
    71
    0
                    let value = self.transpile_expr(arg)?;
    72
    0
                    Ok(Some(quote! { (#value as i64) }))
    73
                }
    74
            }
    75
    0
        }
    76
    77
        /// Convert to float (complexity: 10)
    78
    0
        fn convert_to_float(&self, arg: &Expr) -> Result<Option<TokenStream>> {
    79
    0
            match &arg.kind {
    80
                // String literal -> parse
    81
                ExprKind::Literal(Literal::String(_)) => {
    82
    0
                    let value = self.transpile_expr(arg)?;
    83
    0
                    Ok(Some(quote! { #value.parse::<f64>().expect("Failed to parse float") }))
    84
                }
    85
                // String interpolation with single text part -> parse
    86
    0
                ExprKind::StringInterpolation { parts } if is_single_text_part(parts) => {
    87
    0
                    let value = self.transpile_expr(arg)?;
    88
    0
                    Ok(Some(quote! { #value.parse::<f64>().expect("Failed to parse float") }))
    89
                }
    90
                // Integer literal -> cast
    91
                ExprKind::Literal(Literal::Integer(_)) => {
    92
    0
                    let value = self.transpile_expr(arg)?;
    93
    0
                    Ok(Some(quote! { (#value as f64) }))
    94
                }
    95
                // Default: runtime cast
    96
                _ => {
    97
    0
                    let value = self.transpile_expr(arg)?;
    98
    0
                    Ok(Some(quote! { (#value as f64) }))
    99
                }
    100
            }
    101
    0
        }
    102
    103
        /// Convert to bool (complexity: ~10)
    104
    0
        fn convert_to_bool(&self, arg: &Expr) -> Result<Option<TokenStream>> {
    105
            // Delegate to specific bool conversion based on literal type
    106
    0
            match &arg.kind {
    107
    0
                ExprKind::Literal(lit) => self.convert_literal_to_bool(lit, arg),
    108
    0
                ExprKind::StringInterpolation { .. } => self.convert_string_to_bool(arg),
    109
    0
                ExprKind::List(_) => self.convert_collection_to_bool(arg),
    110
    0
                ExprKind::None => Ok(Some(quote! { false })),
    111
    0
                _ => self.convert_generic_to_bool(arg),
    112
            }
    113
    0
        }
    114
    115
        /// Convert literal to bool (complexity: ~8)
    116
    0
        fn convert_literal_to_bool(&self, lit: &Literal, arg: &Expr) -> Result<Option<TokenStream>> {
    117
    0
            match lit {
    118
                Literal::Integer(_) => {
    119
    0
                    let value = self.transpile_expr(arg)?;
    120
    0
                    Ok(Some(quote! { (#value != 0) }))
    121
                }
    122
                Literal::String(_) => {
    123
    0
                    let value = self.transpile_expr(arg)?;
    124
    0
                    Ok(Some(quote! { !#value.is_empty() }))
    125
                }
    126
                Literal::Bool(_) => {
    127
    0
                    let value = self.transpile_expr(arg)?;
    128
    0
                    Ok(Some(value))
    129
                }
    130
    0
                _ => self.convert_generic_to_bool(arg),
    131
            }
    132
    0
        }
    133
    134
        /// Convert string to bool (complexity: 3)
    135
    0
        fn convert_string_to_bool(&self, arg: &Expr) -> Result<Option<TokenStream>> {
    136
    0
            let value = self.transpile_expr(arg)?;
    137
    0
            Ok(Some(quote! { !#value.is_empty() }))
    138
    0
        }
    139
    140
        /// Convert collection to bool (complexity: 3)
    141
    0
        fn convert_collection_to_bool(&self, arg: &Expr) -> Result<Option<TokenStream>> {
    142
    0
            let value = self.transpile_expr(arg)?;
    143
    0
            Ok(Some(quote! { !#value.is_empty() }))
    144
    0
        }
    145
    146
        /// Generic truthiness check (complexity: 3)
    147
    0
        fn convert_generic_to_bool(&self, arg: &Expr) -> Result<Option<TokenStream>> {
    148
    0
            let value = self.transpile_expr(arg)?;
    149
    0
            Ok(Some(quote! {
    150
    0
                {
    151
    0
                    // Generic truthiness check
    152
    0
                    match &#value {
    153
    0
                        0 => false,
    154
    0
                        _ => true,
    155
    0
                    }
    156
    0
                }
    157
    0
            }))
    158
    0
        }
    159
    160
        /// Convert to list (complexity: 8)
    161
    0
        fn convert_to_list(&self, arg: &Expr) -> Result<Option<TokenStream>> {
    162
    0
            match &arg.kind {
    163
                // String -> chars as list
    164
                ExprKind::Literal(Literal::String(_)) => {
    165
    0
                    let value = self.transpile_expr(arg)?;
    166
    0
                    Ok(Some(quote! { #value.chars().map(|c| c.to_string()).collect::<Vec<_>>() }))
    167
                }
    168
                // Range -> collect to vec
    169
                ExprKind::Range { .. } => {
    170
    0
                    let value = self.transpile_expr(arg)?;
    171
    0
                    Ok(Some(quote! { #value.collect::<Vec<_>>() }))
    172
                }
    173
                // Tuple -> convert to vec
    174
                ExprKind::Tuple(_) => {
    175
    0
                    let value = self.transpile_expr(arg)?;
    176
    0
                    Ok(Some(quote! { vec![#value] }))
    177
                }
    178
                // Default: wrap in vec
    179
                _ => {
    180
    0
                    let value = self.transpile_expr(arg)?;
    181
    0
                    Ok(Some(quote! { vec![#value] }))
    182
                }
    183
            }
    184
    0
        }
    185
    186
        /// Convert to set (complexity: 8)
    187
    0
        fn convert_to_set(&self, arg: &Expr) -> Result<Option<TokenStream>> {
    188
    0
            match &arg.kind {
    189
                // List -> convert to HashSet
    190
                ExprKind::List(_) => {
    191
    0
                    let value = self.transpile_expr(arg)?;
    192
    0
                    Ok(Some(quote! {
    193
    0
                        #value.into_iter().collect::<std::collections::HashSet<_>>()
    194
    0
                    }))
    195
                }
    196
                // String -> chars as set
    197
                ExprKind::Literal(Literal::String(_)) => {
    198
    0
                    let value = self.transpile_expr(arg)?;
    199
    0
                    Ok(Some(quote! {
    200
    0
                        #value.chars().map(|c| c.to_string())
    201
    0
                            .collect::<std::collections::HashSet<_>>()
    202
    0
                    }))
    203
                }
    204
                // Default: single element set
    205
                _ => {
    206
    0
                    let value = self.transpile_expr(arg)?;
    207
    0
                    Ok(Some(quote! {
    208
    0
                        {
    209
    0
                            let mut set = std::collections::HashSet::new();
    210
    0
                            set.insert(#value);
    211
    0
                            set
    212
    0
                        }
    213
    0
                    }))
    214
                }
    215
            }
    216
    0
        }
    217
    218
        /// Convert to dict (complexity: 6)
    219
    0
        fn convert_to_dict(&self, arg: &Expr) -> Result<Option<TokenStream>> {
    220
    0
            match &arg.kind {
    221
                // List of tuples -> dict
    222
    0
                ExprKind::List(items) if items.iter().all(is_tuple_expr) => {
    223
    0
                    let value = self.transpile_expr(arg)?;
    224
    0
                    Ok(Some(quote! {
    225
    0
                        #value.into_iter()
    226
    0
                            .map(|(k, v)| (k, v))
    227
    0
                            .collect::<std::collections::HashMap<_, _>>()
    228
    0
                    }))
    229
                }
    230
                // ObjectLiteral -> convert to HashMap
    231
                ExprKind::ObjectLiteral { .. } => {
    232
    0
                    let value = self.transpile_expr(arg)?;
    233
    0
                    Ok(Some(quote! {
    234
    0
                        #value.into_iter().collect::<std::collections::HashMap<_, _>>()
    235
    0
                    }))
    236
                }
    237
                // Default: empty dict
    238
                _ => {
    239
    0
                    Ok(Some(quote! { std::collections::HashMap::new() }))
    240
                }
    241
            }
    242
    0
        }
    243
    }
    244
    245
    // Helper functions (complexity: 1-3 each)
    246
    247
    0
    fn is_single_text_part(parts: &[StringPart]) -> bool {
    248
    0
        parts.len() == 1 && matches!(&parts[0], StringPart::Text(_))
    249
    0
    }
    250
    251
    0
    fn is_tuple_expr(expr: &Expr) -> bool {
    252
    0
        matches!(&expr.kind, ExprKind::Tuple(items) if items.len() == 2)
    253
    0
    }
    254
    255
    #[cfg(test)]
    256
    #[path = "type_conversion_refactored_tests.rs"]
    257
    mod tests;