Skip to main content

oxilean_codegen/rust_target_backend/
functions.rs

1//! Auto-generated module
2//!
3//! 🤖 Generated with [SplitRS](https://github.com/cool-japan/splitrs)
4
5use crate::lcnf::*;
6use std::collections::HashMap;
7
8use super::types::{
9    RustAnalysisCache, RustConstantFoldingHelper, RustDepGraph, RustDominatorTree, RustEnum,
10    RustExpr, RustFn, RustImpl, RustItem, RustLit, RustLivenessInfo, RustModule, RustPassConfig,
11    RustPassPhase, RustPassRegistry, RustPassStats, RustPattern, RustStmt, RustStruct,
12    RustStructFields, RustTargetBackend, RustType, RustVariant, RustVisibility, RustWorklist,
13};
14
15pub(super) fn emit_expr(expr: &RustExpr, indent: usize) -> std::string::String {
16    match expr {
17        RustExpr::Lit(lit) => lit.to_string(),
18        RustExpr::Var(name) => name.clone(),
19        RustExpr::BinOp { op, lhs, rhs } => {
20            format!(
21                "({} {} {})",
22                emit_expr(lhs, indent),
23                op,
24                emit_expr(rhs, indent)
25            )
26        }
27        RustExpr::UnaryOp { op, operand } => {
28            format!("({}{})", op, emit_expr(operand, indent))
29        }
30        RustExpr::Block(stmts, tail) => {
31            let pad = "    ".repeat(indent);
32            let inner_pad = "    ".repeat(indent + 1);
33            let mut out = "{\n".to_string();
34            for s in stmts {
35                out.push_str(&format!("{}{}\n", inner_pad, emit_stmt(s, indent + 1)));
36            }
37            if let Some(te) = tail {
38                out.push_str(&format!("{}{}\n", inner_pad, emit_expr(te, indent + 1)));
39            }
40            out.push_str(&format!("{}}}", pad));
41            out
42        }
43        RustExpr::If {
44            cond,
45            then_block,
46            else_block,
47        } => {
48            let pad = "    ".repeat(indent);
49            let inner_pad = "    ".repeat(indent + 1);
50            let mut out = format!("if {} {{\n", emit_expr(cond, indent));
51            for s in then_block {
52                out.push_str(&format!("{}{}\n", inner_pad, emit_stmt(s, indent + 1)));
53            }
54            out.push_str(&format!("{}}}", pad));
55            if let Some(eb) = else_block {
56                out.push_str(" else {\n");
57                for s in eb {
58                    out.push_str(&format!("{}{}\n", inner_pad, emit_stmt(s, indent + 1)));
59                }
60                out.push_str(&format!("{}}}", pad));
61            }
62            out
63        }
64        RustExpr::Match { scrutinee, arms } => {
65            let pad = "    ".repeat(indent);
66            let inner_pad = "    ".repeat(indent + 1);
67            let mut out = format!("match {} {{\n", emit_expr(scrutinee, indent));
68            for (pat, body) in arms {
69                out.push_str(&format!(
70                    "{}{} => {},\n",
71                    inner_pad,
72                    pat,
73                    emit_expr(body, indent + 1)
74                ));
75            }
76            out.push_str(&format!("{}}}", pad));
77            out
78        }
79        RustExpr::Loop(body) => {
80            let pad = "    ".repeat(indent);
81            let inner_pad = "    ".repeat(indent + 1);
82            let mut out = "loop {\n".to_string();
83            for s in body {
84                out.push_str(&format!("{}{}\n", inner_pad, emit_stmt(s, indent + 1)));
85            }
86            out.push_str(&format!("{}}}", pad));
87            out
88        }
89        RustExpr::For { pat, iter, body } => {
90            let pad = "    ".repeat(indent);
91            let inner_pad = "    ".repeat(indent + 1);
92            let mut out = format!("for {} in {} {{\n", pat, emit_expr(iter, indent));
93            for s in body {
94                out.push_str(&format!("{}{}\n", inner_pad, emit_stmt(s, indent + 1)));
95            }
96            out.push_str(&format!("{}}}", pad));
97            out
98        }
99        RustExpr::While { cond, body } => {
100            let pad = "    ".repeat(indent);
101            let inner_pad = "    ".repeat(indent + 1);
102            let mut out = format!("while {} {{\n", emit_expr(cond, indent));
103            for s in body {
104                out.push_str(&format!("{}{}\n", inner_pad, emit_stmt(s, indent + 1)));
105            }
106            out.push_str(&format!("{}}}", pad));
107            out
108        }
109        RustExpr::Return(expr) => match expr {
110            Some(e) => format!("return {}", emit_expr(e, indent)),
111            None => "return".to_string(),
112        },
113        RustExpr::Break(expr) => match expr {
114            Some(e) => format!("break {}", emit_expr(e, indent)),
115            None => "break".to_string(),
116        },
117        RustExpr::Continue => "continue".to_string(),
118        RustExpr::Closure {
119            params,
120            ret_ty,
121            body,
122            is_move,
123        } => {
124            let move_kw = if *is_move { "move " } else { "" };
125            let params_str = params
126                .iter()
127                .map(|(n, ty)| {
128                    if let Some(t) = ty {
129                        format!("{}: {}", n, t)
130                    } else {
131                        n.clone()
132                    }
133                })
134                .collect::<Vec<_>>()
135                .join(", ");
136            let ret_str = ret_ty
137                .as_ref()
138                .map(|t| format!(" -> {} ", t))
139                .unwrap_or_default();
140            format!(
141                "{}|{}|{}{}",
142                move_kw,
143                params_str,
144                ret_str,
145                emit_expr(body, indent)
146            )
147        }
148        RustExpr::Call(func, args) => {
149            let args_str = args
150                .iter()
151                .map(|a| emit_expr(a, indent))
152                .collect::<Vec<_>>()
153                .join(", ");
154            format!("{}({})", emit_expr(func, indent), args_str)
155        }
156        RustExpr::MethodCall {
157            receiver,
158            method,
159            args,
160        } => {
161            let args_str = args
162                .iter()
163                .map(|a| emit_expr(a, indent))
164                .collect::<Vec<_>>()
165                .join(", ");
166            format!("{}.{}({})", emit_expr(receiver, indent), method, args_str)
167        }
168        RustExpr::Field(obj, field) => format!("{}.{}", emit_expr(obj, indent), field),
169        RustExpr::Index(obj, idx) => {
170            format!("{}[{}]", emit_expr(obj, indent), emit_expr(idx, indent))
171        }
172        RustExpr::Ref(mutable, inner) => {
173            if *mutable {
174                format!("&mut {}", emit_expr(inner, indent))
175            } else {
176                format!("&{}", emit_expr(inner, indent))
177            }
178        }
179        RustExpr::Deref(inner) => format!("*{}", emit_expr(inner, indent)),
180        RustExpr::Struct(name, fields) => {
181            if fields.is_empty() {
182                name.clone()
183            } else {
184                let fstr = fields
185                    .iter()
186                    .map(|(n, e)| format!("{}: {}", n, emit_expr(e, indent)))
187                    .collect::<Vec<_>>()
188                    .join(", ");
189                format!("{} {{ {} }}", name, fstr)
190            }
191        }
192        RustExpr::Tuple(elems) => {
193            let es = elems
194                .iter()
195                .map(|e| emit_expr(e, indent))
196                .collect::<Vec<_>>()
197                .join(", ");
198            if elems.len() == 1 {
199                format!("({},)", es)
200            } else {
201                format!("({})", es)
202            }
203        }
204        RustExpr::Array(elems) => {
205            let es = elems
206                .iter()
207                .map(|e| emit_expr(e, indent))
208                .collect::<Vec<_>>()
209                .join(", ");
210            format!("[{}]", es)
211        }
212        RustExpr::Range(lo, hi, inclusive) => {
213            let lo_str = lo
214                .as_ref()
215                .map(|e| emit_expr(e, indent))
216                .unwrap_or_default();
217            let hi_str = hi
218                .as_ref()
219                .map(|e| emit_expr(e, indent))
220                .unwrap_or_default();
221            let sep = if *inclusive { "..=" } else { ".." };
222            format!("{}{}{}", lo_str, sep, hi_str)
223        }
224        RustExpr::Try(inner) => format!("{}?", emit_expr(inner, indent)),
225        RustExpr::Await(inner) => format!("{}.await", emit_expr(inner, indent)),
226        RustExpr::Path(segments) => segments.join("::"),
227        RustExpr::MacroCall(name, args) => format!("{}!({})", name, args),
228    }
229}
230pub(super) fn emit_stmt(stmt: &RustStmt, indent: usize) -> std::string::String {
231    match stmt {
232        RustStmt::Let { pat, ty, value } => {
233            let ty_str = ty.as_ref().map(|t| format!(": {}", t)).unwrap_or_default();
234            let val_str = value
235                .as_ref()
236                .map(|v| format!(" = {}", emit_expr(v, indent)))
237                .unwrap_or_default();
238            format!("let {}{}{};", pat, ty_str, val_str)
239        }
240        RustStmt::Expr(e) => format!("{};", emit_expr(e, indent)),
241        RustStmt::ExprNoSemi(e) => emit_expr(e, indent),
242        RustStmt::Return(e) => match e {
243            Some(expr) => format!("return {};", emit_expr(expr, indent)),
244            None => "return;".to_string(),
245        },
246        RustStmt::Break(e) => match e {
247            Some(expr) => format!("break {};", emit_expr(expr, indent)),
248            None => "break;".to_string(),
249        },
250        RustStmt::Continue => "continue;".to_string(),
251    }
252}
253/// Rust reserved keywords.
254pub const RUST_KEYWORDS: &[&str] = &[
255    "as", "async", "await", "break", "const", "continue", "crate", "dyn", "else", "enum", "extern",
256    "false", "fn", "for", "if", "impl", "in", "let", "loop", "match", "mod", "move", "mut", "pub",
257    "ref", "return", "self", "Self", "static", "struct", "super", "trait", "true", "type", "union",
258    "unsafe", "use", "where", "while",
259];
260#[cfg(test)]
261mod tests {
262    use super::*;
263    #[test]
264    pub(super) fn test_rust_type_primitives() {
265        assert_eq!(RustType::I32.to_string(), "i32");
266        assert_eq!(RustType::U64.to_string(), "u64");
267        assert_eq!(RustType::F64.to_string(), "f64");
268        assert_eq!(RustType::Bool.to_string(), "bool");
269        assert_eq!(RustType::Unit.to_string(), "()");
270        assert_eq!(RustType::Never.to_string(), "!");
271    }
272    #[test]
273    pub(super) fn test_rust_type_string() {
274        assert_eq!(RustType::RustString.to_string(), "String");
275    }
276    #[test]
277    pub(super) fn test_rust_type_vec() {
278        assert_eq!(
279            RustType::Vec(Box::new(RustType::I32)).to_string(),
280            "Vec<i32>"
281        );
282    }
283    #[test]
284    pub(super) fn test_rust_type_option() {
285        assert_eq!(
286            RustType::Option(Box::new(RustType::U64)).to_string(),
287            "Option<u64>"
288        );
289    }
290    #[test]
291    pub(super) fn test_rust_type_result() {
292        let r = RustType::Result(Box::new(RustType::I32), Box::new(RustType::RustString));
293        assert_eq!(r.to_string(), "Result<i32, String>");
294    }
295    #[test]
296    pub(super) fn test_rust_type_tuple() {
297        let t = RustType::Tuple(vec![RustType::I32, RustType::Bool]);
298        assert_eq!(t.to_string(), "(i32, bool)");
299    }
300    #[test]
301    pub(super) fn test_rust_type_tuple_single() {
302        let t = RustType::Tuple(vec![RustType::I32]);
303        assert_eq!(t.to_string(), "(i32,)");
304    }
305    #[test]
306    pub(super) fn test_rust_type_ref() {
307        assert_eq!(
308            RustType::Ref(false, Box::new(RustType::I32)).to_string(),
309            "&i32"
310        );
311        assert_eq!(
312            RustType::Ref(true, Box::new(RustType::I32)).to_string(),
313            "&mut i32"
314        );
315    }
316    #[test]
317    pub(super) fn test_rust_type_generic() {
318        let t = RustType::Generic(
319            "HashMap".to_string(),
320            vec![RustType::RustString, RustType::I32],
321        );
322        assert_eq!(t.to_string(), "HashMap<String, i32>");
323    }
324    #[test]
325    pub(super) fn test_rust_type_fn() {
326        let t = RustType::Fn(vec![RustType::I32, RustType::I32], Box::new(RustType::I32));
327        assert_eq!(t.to_string(), "impl Fn(i32, i32) -> i32");
328    }
329    #[test]
330    pub(super) fn test_rust_type_lifetime() {
331        assert_eq!(RustType::Lifetime("a".to_string()).to_string(), "'a");
332    }
333    #[test]
334    pub(super) fn test_rust_lit_int() {
335        assert_eq!(RustLit::Int(42).to_string(), "42");
336        assert_eq!(RustLit::Int(-7).to_string(), "-7");
337    }
338    #[test]
339    pub(super) fn test_rust_lit_uint() {
340        assert_eq!(RustLit::UInt(100).to_string(), "100");
341    }
342    #[test]
343    pub(super) fn test_rust_lit_float() {
344        assert_eq!(RustLit::Float(3.14).to_string(), "3.14");
345        assert_eq!(RustLit::Float(1.0).to_string(), "1.0");
346    }
347    #[test]
348    pub(super) fn test_rust_lit_bool() {
349        assert_eq!(RustLit::Bool(true).to_string(), "true");
350        assert_eq!(RustLit::Bool(false).to_string(), "false");
351    }
352    #[test]
353    pub(super) fn test_rust_lit_str_escape() {
354        let s = RustLit::Str("hello\nworld".to_string());
355        assert_eq!(s.to_string(), "\"hello\\nworld\"");
356    }
357    #[test]
358    pub(super) fn test_rust_lit_unit() {
359        assert_eq!(RustLit::Unit.to_string(), "()");
360    }
361    #[test]
362    pub(super) fn test_rust_pattern_wildcard() {
363        assert_eq!(RustPattern::Wildcard.to_string(), "_");
364    }
365    #[test]
366    pub(super) fn test_rust_pattern_var() {
367        assert_eq!(RustPattern::Var("x".to_string(), false).to_string(), "x");
368        assert_eq!(RustPattern::Var("x".to_string(), true).to_string(), "mut x");
369    }
370    #[test]
371    pub(super) fn test_rust_pattern_enum() {
372        let p = RustPattern::Enum(
373            "Some".to_string(),
374            vec![RustPattern::Var("v".to_string(), false)],
375        );
376        assert_eq!(p.to_string(), "Some(v)");
377    }
378    #[test]
379    pub(super) fn test_rust_pattern_tuple() {
380        let p = RustPattern::Tuple(vec![
381            RustPattern::Var("a".to_string(), false),
382            RustPattern::Var("b".to_string(), false),
383        ]);
384        assert_eq!(p.to_string(), "(a, b)");
385    }
386    #[test]
387    pub(super) fn test_rust_pattern_or() {
388        let p = RustPattern::Or(vec![
389            RustPattern::Lit(RustLit::Int(1)),
390            RustPattern::Lit(RustLit::Int(2)),
391        ]);
392        assert_eq!(p.to_string(), "1 | 2");
393    }
394    #[test]
395    pub(super) fn test_rust_expr_lit() {
396        assert_eq!(RustExpr::Lit(RustLit::Int(42)).to_string(), "42");
397    }
398    #[test]
399    pub(super) fn test_rust_expr_var() {
400        assert_eq!(RustExpr::Var("x".to_string()).to_string(), "x");
401    }
402    #[test]
403    pub(super) fn test_rust_expr_binop() {
404        let e = RustExpr::BinOp {
405            op: "+".to_string(),
406            lhs: Box::new(RustExpr::Var("a".to_string())),
407            rhs: Box::new(RustExpr::Lit(RustLit::Int(1))),
408        };
409        assert_eq!(e.to_string(), "(a + 1)");
410    }
411    #[test]
412    pub(super) fn test_rust_expr_unary() {
413        let e = RustExpr::UnaryOp {
414            op: "!".to_string(),
415            operand: Box::new(RustExpr::Var("x".to_string())),
416        };
417        assert_eq!(e.to_string(), "(!x)");
418    }
419    #[test]
420    pub(super) fn test_rust_expr_call() {
421        let e = RustExpr::Call(
422            Box::new(RustExpr::Var("foo".to_string())),
423            vec![
424                RustExpr::Lit(RustLit::Int(1)),
425                RustExpr::Lit(RustLit::Int(2)),
426            ],
427        );
428        assert_eq!(e.to_string(), "foo(1, 2)");
429    }
430    #[test]
431    pub(super) fn test_rust_expr_method_call() {
432        let e = RustExpr::MethodCall {
433            receiver: Box::new(RustExpr::Var("v".to_string())),
434            method: "push".to_string(),
435            args: vec![RustExpr::Lit(RustLit::Int(42))],
436        };
437        assert_eq!(e.to_string(), "v.push(42)");
438    }
439    #[test]
440    pub(super) fn test_rust_expr_field() {
441        let e = RustExpr::Field(Box::new(RustExpr::Var("s".to_string())), "name".to_string());
442        assert_eq!(e.to_string(), "s.name");
443    }
444    #[test]
445    pub(super) fn test_rust_expr_closure() {
446        let e = RustExpr::Closure {
447            params: vec![("x".to_string(), Some(RustType::I32))],
448            ret_ty: Some(RustType::I32),
449            body: Box::new(RustExpr::Var("x".to_string())),
450            is_move: false,
451        };
452        let s = e.to_string();
453        assert!(s.contains("|x: i32|"), "Got: {}", s);
454        assert!(s.contains("-> i32"), "Got: {}", s);
455    }
456    #[test]
457    pub(super) fn test_rust_expr_macro_call() {
458        let e = RustExpr::MacroCall("println".to_string(), "\"hello\"".to_string());
459        assert_eq!(e.to_string(), "println!(\"hello\")");
460    }
461    #[test]
462    pub(super) fn test_rust_expr_range() {
463        let e = RustExpr::Range(
464            Some(Box::new(RustExpr::Lit(RustLit::Int(0)))),
465            Some(Box::new(RustExpr::Lit(RustLit::Int(10)))),
466            false,
467        );
468        assert_eq!(e.to_string(), "0..10");
469    }
470    #[test]
471    pub(super) fn test_rust_expr_range_inclusive() {
472        let e = RustExpr::Range(
473            Some(Box::new(RustExpr::Lit(RustLit::Int(1)))),
474            Some(Box::new(RustExpr::Lit(RustLit::Int(5)))),
475            true,
476        );
477        assert_eq!(e.to_string(), "1..=5");
478    }
479    #[test]
480    pub(super) fn test_rust_expr_try() {
481        let e = RustExpr::Try(Box::new(RustExpr::Call(
482            Box::new(RustExpr::Var("do_thing".to_string())),
483            vec![],
484        )));
485        assert_eq!(e.to_string(), "do_thing()?");
486    }
487    #[test]
488    pub(super) fn test_rust_expr_path() {
489        let e = RustExpr::Path(vec![
490            "std".to_string(),
491            "collections".to_string(),
492            "HashMap".to_string(),
493        ]);
494        assert_eq!(e.to_string(), "std::collections::HashMap");
495    }
496    #[test]
497    pub(super) fn test_rust_stmt_let() {
498        let s = RustStmt::Let {
499            pat: RustPattern::Var("x".to_string(), false),
500            ty: Some(RustType::I32),
501            value: Some(RustExpr::Lit(RustLit::Int(5))),
502        };
503        assert_eq!(s.to_string(), "let x: i32 = 5;");
504    }
505    #[test]
506    pub(super) fn test_rust_stmt_expr() {
507        let s = RustStmt::Expr(RustExpr::MacroCall(
508            "println".to_string(),
509            "\"hi\"".to_string(),
510        ));
511        assert_eq!(s.to_string(), "println!(\"hi\");");
512    }
513    #[test]
514    pub(super) fn test_rust_fn_emit_simple() {
515        let func = RustFn::new(
516            "add",
517            vec![
518                ("a".to_string(), RustType::I32, false),
519                ("b".to_string(), RustType::I32, false),
520            ],
521            Some(RustType::I32),
522            vec![RustStmt::ExprNoSemi(RustExpr::BinOp {
523                op: "+".to_string(),
524                lhs: Box::new(RustExpr::Var("a".to_string())),
525                rhs: Box::new(RustExpr::Var("b".to_string())),
526            })],
527        );
528        let s = func.emit();
529        assert!(s.contains("fn add(a: i32, b: i32) -> i32"), "Got: {}", s);
530        assert!(s.contains("(a + b)"), "Got: {}", s);
531    }
532    #[test]
533    pub(super) fn test_rust_fn_async_unsafe() {
534        let func = RustFn {
535            name: "dangerous".to_string(),
536            generics: vec![],
537            params: vec![],
538            return_type: Some(RustType::Unit),
539            body: vec![],
540            attrs: vec![],
541            visibility: RustVisibility::Pub,
542            is_async: true,
543            is_unsafe: true,
544        };
545        let s = func.emit();
546        assert!(s.contains("async unsafe fn dangerous()"), "Got: {}", s);
547    }
548    #[test]
549    pub(super) fn test_rust_fn_with_generics() {
550        let func = RustFn {
551            name: "identity".to_string(),
552            generics: vec![("T".to_string(), vec!["Clone".to_string()])],
553            params: vec![("x".to_string(), RustType::Custom("T".to_string()), false)],
554            return_type: Some(RustType::Custom("T".to_string())),
555            body: vec![RustStmt::ExprNoSemi(RustExpr::Var("x".to_string()))],
556            attrs: vec![],
557            visibility: RustVisibility::Pub,
558            is_async: false,
559            is_unsafe: false,
560        };
561        let s = func.emit();
562        assert!(s.contains("fn identity<T: Clone>(x: T) -> T"), "Got: {}", s);
563    }
564    #[test]
565    pub(super) fn test_rust_struct_named_fields() {
566        let s = RustStruct {
567            name: "Point".to_string(),
568            generics: vec![],
569            fields: RustStructFields::Named(vec![
570                ("x".to_string(), RustType::F64, RustVisibility::Pub),
571                ("y".to_string(), RustType::F64, RustVisibility::Pub),
572            ]),
573            attrs: vec![],
574            derives: vec!["Debug".to_string(), "Clone".to_string()],
575            visibility: RustVisibility::Pub,
576        };
577        let out = s.emit();
578        assert!(out.contains("#[derive(Debug, Clone)]"), "Got: {}", out);
579        assert!(out.contains("pub struct Point {"), "Got: {}", out);
580        assert!(out.contains("x:f64"), "Got: {}", out);
581    }
582    #[test]
583    pub(super) fn test_rust_struct_unit() {
584        let s = RustStruct {
585            name: "Sentinel".to_string(),
586            generics: vec![],
587            fields: RustStructFields::Unit,
588            attrs: vec![],
589            derives: vec![],
590            visibility: RustVisibility::Pub,
591        };
592        let out = s.emit();
593        assert_eq!(out, "pub struct Sentinel;");
594    }
595    #[test]
596    pub(super) fn test_rust_enum_emit() {
597        let e = RustEnum {
598            name: "Shape".to_string(),
599            generics: vec![],
600            variants: vec![
601                RustVariant::Unit("Circle".to_string()),
602                RustVariant::Tuple("Rect".to_string(), vec![RustType::F64, RustType::F64]),
603            ],
604            attrs: vec![],
605            derives: vec!["Debug".to_string()],
606            visibility: RustVisibility::Pub,
607        };
608        let out = e.emit();
609        assert!(out.contains("#[derive(Debug)]"), "Got: {}", out);
610        assert!(out.contains("pub enum Shape {"), "Got: {}", out);
611        assert!(out.contains("Circle,"), "Got: {}", out);
612        assert!(out.contains("Rect(f64, f64),"), "Got: {}", out);
613    }
614    #[test]
615    pub(super) fn test_rust_impl_emit() {
616        let f = RustFn::new(
617            "area",
618            vec![(
619                "self".to_string(),
620                RustType::Custom("Self".to_string()),
621                false,
622            )],
623            Some(RustType::F64),
624            vec![],
625        );
626        let imp = RustImpl {
627            for_type: "Circle".to_string(),
628            trait_impl: None,
629            generics: vec![],
630            methods: vec![f],
631            associated_types: vec![],
632        };
633        let out = imp.emit();
634        assert!(out.contains("impl Circle {"), "Got: {}", out);
635        assert!(out.contains("fn area"), "Got: {}", out);
636    }
637    #[test]
638    pub(super) fn test_rust_impl_trait() {
639        let imp = RustImpl {
640            for_type: "MyType".to_string(),
641            trait_impl: Some("Display".to_string()),
642            generics: vec![],
643            methods: vec![],
644            associated_types: vec![],
645        };
646        let out = imp.emit();
647        assert!(out.contains("impl Display for MyType {"), "Got: {}", out);
648    }
649    #[test]
650    pub(super) fn test_rust_module_emit_use() {
651        let mut m = RustModule::new("my_module");
652        m.items.push(RustItem::Use {
653            path: "std::collections::HashMap".to_string(),
654            visibility: RustVisibility::Private,
655        });
656        let out = m.emit();
657        assert!(
658            out.contains("use std::collections::HashMap;"),
659            "Got: {}",
660            out
661        );
662    }
663    #[test]
664    pub(super) fn test_rust_module_const() {
665        let mut m = RustModule::new("consts");
666        m.items.push(RustItem::Const {
667            name: "MAX".to_string(),
668            ty: RustType::U64,
669            value: RustExpr::Lit(RustLit::UInt(1000)),
670            visibility: RustVisibility::Pub,
671        });
672        let out = m.emit();
673        assert!(out.contains("pub const MAX: u64 = 1000;"), "Got: {}", out);
674    }
675    #[test]
676    pub(super) fn test_mangle_name_keyword() {
677        let mut b = RustTargetBackend::new();
678        assert_eq!(b.mangle_name("type"), "type_");
679        assert_eq!(b.mangle_name("fn"), "fn_");
680    }
681    #[test]
682    pub(super) fn test_mangle_name_dot() {
683        let mut b = RustTargetBackend::new();
684        assert_eq!(b.mangle_name("Nat.add"), "Nat_add");
685    }
686    #[test]
687    pub(super) fn test_mangle_name_empty() {
688        let mut b = RustTargetBackend::new();
689        assert_eq!(b.mangle_name(""), "_anon");
690    }
691    #[test]
692    pub(super) fn test_fresh_var() {
693        let mut b = RustTargetBackend::new();
694        assert_eq!(b.fresh_var(), "_t0");
695        assert_eq!(b.fresh_var(), "_t1");
696    }
697    #[test]
698    pub(super) fn test_compile_decl_simple() {
699        let decl = LcnfFunDecl {
700            name: "answer".to_string(),
701            original_name: None,
702            params: vec![],
703            ret_type: LcnfType::Nat,
704            body: LcnfExpr::Return(LcnfArg::Lit(LcnfLit::Nat(42))),
705            is_recursive: false,
706            is_lifted: false,
707            inline_cost: 0,
708        };
709        let mut b = RustTargetBackend::new();
710        let func = b
711            .compile_decl(&decl)
712            .expect("func compilation should succeed");
713        assert_eq!(func.name, "answer");
714        let s = func.emit();
715        assert!(s.contains("fn answer()"), "Got: {}", s);
716        assert!(s.contains("-> u64"), "Got: {}", s);
717        assert!(s.contains("42"), "Got: {}", s);
718    }
719    #[test]
720    pub(super) fn test_compile_decl_with_param() {
721        let x_id = LcnfVarId(0);
722        let decl = LcnfFunDecl {
723            name: "identity".to_string(),
724            original_name: None,
725            params: vec![LcnfParam {
726                id: x_id,
727                name: "x".to_string(),
728                ty: LcnfType::Nat,
729                erased: false,
730                borrowed: false,
731            }],
732            ret_type: LcnfType::Nat,
733            body: LcnfExpr::Return(LcnfArg::Var(x_id)),
734            is_recursive: false,
735            is_lifted: false,
736            inline_cost: 0,
737        };
738        let mut b = RustTargetBackend::new();
739        let func = b
740            .compile_decl(&decl)
741            .expect("func compilation should succeed");
742        let s = func.emit();
743        assert!(s.contains("fn identity("), "Got: {}", s);
744        assert!(s.contains(": u64"), "Got: {}", s);
745    }
746    #[test]
747    pub(super) fn test_emit_module_multiple_decls() {
748        let decl1 = LcnfFunDecl {
749            name: "one".to_string(),
750            original_name: None,
751            params: vec![],
752            ret_type: LcnfType::Nat,
753            body: LcnfExpr::Return(LcnfArg::Lit(LcnfLit::Nat(1))),
754            is_recursive: false,
755            is_lifted: false,
756            inline_cost: 0,
757        };
758        let decl2 = LcnfFunDecl {
759            name: "two".to_string(),
760            original_name: None,
761            params: vec![],
762            ret_type: LcnfType::Nat,
763            body: LcnfExpr::Return(LcnfArg::Lit(LcnfLit::Nat(2))),
764            is_recursive: false,
765            is_lifted: false,
766            inline_cost: 0,
767        };
768        let mut b = RustTargetBackend::new();
769        let module = b.emit_module("test_mod", &[decl1, decl2]);
770        assert_eq!(module.items.len(), 2);
771        let s = module.emit();
772        assert!(s.contains("fn one()"), "Got: {}", s);
773        assert!(s.contains("fn two()"), "Got: {}", s);
774    }
775    #[test]
776    pub(super) fn test_rust_item_mod() {
777        let inner_use = RustItem::Use {
778            path: "super::*".to_string(),
779            visibility: RustVisibility::Private,
780        };
781        let m = RustItem::Mod {
782            name: "inner".to_string(),
783            items: vec![inner_use],
784            visibility: RustVisibility::Pub,
785        };
786        let out = m.emit();
787        assert!(out.contains("pub mod inner {"), "Got: {}", out);
788        assert!(out.contains("use super::*;"), "Got: {}", out);
789    }
790    #[test]
791    pub(super) fn test_rust_item_type_alias() {
792        let item = RustItem::TypeAlias {
793            name: "Bytes".to_string(),
794            generics: vec![],
795            ty: RustType::Vec(Box::new(RustType::U8)),
796            visibility: RustVisibility::Pub,
797        };
798        assert_eq!(item.emit(), "pub type Bytes = Vec<u8>;");
799    }
800    #[test]
801    pub(super) fn test_rust_item_static() {
802        let item = RustItem::Static {
803            name: "COUNTER".to_string(),
804            ty: RustType::U64,
805            value: RustExpr::Lit(RustLit::UInt(0)),
806            mutable: true,
807            visibility: RustVisibility::Private,
808        };
809        assert_eq!(item.emit(), "static mut COUNTER: u64 = 0;");
810    }
811    #[test]
812    pub(super) fn test_rust_visibility_display() {
813        assert_eq!(RustVisibility::Private.to_string(), "");
814        assert_eq!(RustVisibility::Pub.to_string(), "pub ");
815        assert_eq!(RustVisibility::PubCrate.to_string(), "pub(crate) ");
816    }
817}
818#[cfg(test)]
819mod Rust_infra_tests {
820    use super::*;
821    #[test]
822    pub(super) fn test_pass_config() {
823        let config = RustPassConfig::new("test_pass", RustPassPhase::Transformation);
824        assert!(config.enabled);
825        assert!(config.phase.is_modifying());
826        assert_eq!(config.phase.name(), "transformation");
827    }
828    #[test]
829    pub(super) fn test_pass_stats() {
830        let mut stats = RustPassStats::new();
831        stats.record_run(10, 100, 3);
832        stats.record_run(20, 200, 5);
833        assert_eq!(stats.total_runs, 2);
834        assert!((stats.average_changes_per_run() - 15.0).abs() < 0.01);
835        assert!((stats.success_rate() - 1.0).abs() < 0.01);
836        let s = stats.format_summary();
837        assert!(s.contains("Runs: 2/2"));
838    }
839    #[test]
840    pub(super) fn test_pass_registry() {
841        let mut reg = RustPassRegistry::new();
842        reg.register(RustPassConfig::new("pass_a", RustPassPhase::Analysis));
843        reg.register(RustPassConfig::new("pass_b", RustPassPhase::Transformation).disabled());
844        assert_eq!(reg.total_passes(), 2);
845        assert_eq!(reg.enabled_count(), 1);
846        reg.update_stats("pass_a", 5, 50, 2);
847        let stats = reg.get_stats("pass_a").expect("stats should exist");
848        assert_eq!(stats.total_changes, 5);
849    }
850    #[test]
851    pub(super) fn test_analysis_cache() {
852        let mut cache = RustAnalysisCache::new(10);
853        cache.insert("key1".to_string(), vec![1, 2, 3]);
854        assert!(cache.get("key1").is_some());
855        assert!(cache.get("key2").is_none());
856        assert!((cache.hit_rate() - 0.5).abs() < 0.01);
857        cache.invalidate("key1");
858        assert!(!cache.entries["key1"].valid);
859        assert_eq!(cache.size(), 1);
860    }
861    #[test]
862    pub(super) fn test_worklist() {
863        let mut wl = RustWorklist::new();
864        assert!(wl.push(1));
865        assert!(wl.push(2));
866        assert!(!wl.push(1));
867        assert_eq!(wl.len(), 2);
868        assert_eq!(wl.pop(), Some(1));
869        assert!(!wl.contains(1));
870        assert!(wl.contains(2));
871    }
872    #[test]
873    pub(super) fn test_dominator_tree() {
874        let mut dt = RustDominatorTree::new(5);
875        dt.set_idom(1, 0);
876        dt.set_idom(2, 0);
877        dt.set_idom(3, 1);
878        assert!(dt.dominates(0, 3));
879        assert!(dt.dominates(1, 3));
880        assert!(!dt.dominates(2, 3));
881        assert!(dt.dominates(3, 3));
882    }
883    #[test]
884    pub(super) fn test_liveness() {
885        let mut liveness = RustLivenessInfo::new(3);
886        liveness.add_def(0, 1);
887        liveness.add_use(1, 1);
888        assert!(liveness.defs[0].contains(&1));
889        assert!(liveness.uses[1].contains(&1));
890    }
891    #[test]
892    pub(super) fn test_constant_folding() {
893        assert_eq!(RustConstantFoldingHelper::fold_add_i64(3, 4), Some(7));
894        assert_eq!(RustConstantFoldingHelper::fold_div_i64(10, 0), None);
895        assert_eq!(RustConstantFoldingHelper::fold_div_i64(10, 2), Some(5));
896        assert_eq!(
897            RustConstantFoldingHelper::fold_bitand_i64(0b1100, 0b1010),
898            0b1000
899        );
900        assert_eq!(RustConstantFoldingHelper::fold_bitnot_i64(0), -1);
901    }
902    #[test]
903    pub(super) fn test_dep_graph() {
904        let mut g = RustDepGraph::new();
905        g.add_dep(1, 2);
906        g.add_dep(2, 3);
907        g.add_dep(1, 3);
908        assert_eq!(g.dependencies_of(2), vec![1]);
909        let topo = g.topological_sort();
910        assert_eq!(topo.len(), 3);
911        assert!(!g.has_cycle());
912        let pos: std::collections::HashMap<u32, usize> =
913            topo.iter().enumerate().map(|(i, &n)| (n, i)).collect();
914        assert!(pos[&1] < pos[&2]);
915        assert!(pos[&1] < pos[&3]);
916        assert!(pos[&2] < pos[&3]);
917    }
918}