Coverage Report

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