Skip to main content

oxilean_codegen/
lib.rs

1#![allow(dead_code)]
2#![allow(unused_imports)]
3#![allow(unused_mut)]
4#![allow(clippy::new_without_default)]
5#![allow(non_snake_case)]
6#![allow(clippy::collapsible_if)]
7#![allow(clippy::collapsible_match)]
8#![allow(clippy::approx_constant)]
9#![allow(clippy::should_implement_trait)]
10#![allow(clippy::single_match)]
11#![allow(clippy::field_reassign_with_default)]
12#![allow(clippy::len_without_is_empty)]
13#![allow(clippy::useless_format)]
14#![allow(clippy::type_complexity)]
15#![allow(clippy::items_after_test_module)]
16#![allow(clippy::too_many_arguments)]
17#![allow(clippy::result_large_err)]
18#![allow(clippy::vec_init_then_push)]
19#![allow(clippy::comparison_chain)]
20#![allow(clippy::write_with_newline)]
21#![allow(clippy::absurd_extreme_comparisons)]
22#![allow(clippy::unnecessary_map_or)]
23#![allow(clippy::derivable_impls)]
24#![allow(clippy::if_same_then_else)]
25#![allow(clippy::only_used_in_recursion)]
26#![allow(clippy::module_inception)]
27#![allow(clippy::needless_range_loop)]
28#![allow(clippy::manual_map)]
29#![allow(clippy::ptr_arg)]
30#![allow(clippy::while_let_loop)]
31#![allow(clippy::unnecessary_map_on_constructor)]
32#![allow(clippy::iter_kv_map)]
33#![allow(clippy::collapsible_str_replace)]
34#![allow(clippy::default_constructed_unit_structs)]
35#![allow(clippy::needless_lifetimes)]
36#![allow(clippy::needless_borrow)]
37#![allow(clippy::redundant_closure)]
38#![allow(clippy::len_zero)]
39#![allow(clippy::get_first)]
40#![allow(clippy::manual_find)]
41#![allow(clippy::float_cmp)]
42#![allow(clippy::excessive_precision)]
43#![allow(clippy::inconsistent_digit_grouping)]
44#![allow(clippy::needless_ifs)]
45#![allow(clippy::needless_borrows_for_generic_args)]
46#![allow(clippy::doc_lazy_continuation)]
47#![allow(clippy::unnecessary_unwrap)]
48#![allow(clippy::for_kv_map)]
49#![allow(unused_comparisons)]
50#![allow(private_interfaces)]
51#![allow(clippy::incompatible_msrv)]
52
53//! Code Generation Backend for Oxilean
54//!
55//! This crate provides compilation from Oxilean kernel expressions
56
57pub mod c_backend;
58pub mod closure_convert;
59pub mod ffi_bridge;
60pub mod glsl_backend;
61pub mod js_backend;
62pub mod lcnf;
63pub mod llvm_backend;
64pub mod native_backend;
65pub mod opt_dce;
66pub mod opt_join;
67pub mod opt_passes;
68pub mod opt_reuse;
69pub mod opt_specialize;
70pub mod pgo;
71pub mod pipeline;
72pub mod runtime_codegen;
73pub mod to_lcnf;
74pub mod wasm_backend;
75pub mod wgsl_backend;
76pub mod zig_backend;
77// to various target languages: Rust, C, LLVM IR, and interpretation.
78//
79// The pipeline consists of:
80// 1. Expression to Intermediate Representation (ExprToIr)
81// 2. IR optimization (Optimizer)
82// 3. Backend-specific code emission (IrToRust, IrToC)
83
84use std::collections::{HashMap, HashSet, VecDeque};
85use std::fmt;
86
87use oxilean_kernel::expr::{Expr, Literal};
88
89// ============================================================================
90// Type Definitions and Enumerations
91// ============================================================================
92
93/// Target code generation language
94#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
95pub enum CodegenTarget {
96    Rust,
97    C,
98    LlvmIr,
99    Interpreter,
100}
101
102impl fmt::Display for CodegenTarget {
103    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104        match self {
105            CodegenTarget::Rust => write!(f, "Rust"),
106            CodegenTarget::C => write!(f, "C"),
107            CodegenTarget::LlvmIr => write!(f, "LLVM IR"),
108            CodegenTarget::Interpreter => write!(f, "Interpreter"),
109        }
110    }
111}
112
113/// Code generation configuration options
114#[derive(Debug, Clone)]
115pub struct CodegenConfig {
116    pub target: CodegenTarget,
117    pub optimize: bool,
118    pub debug_info: bool,
119    pub emit_comments: bool,
120    pub inline_threshold: usize,
121}
122
123impl Default for CodegenConfig {
124    fn default() -> Self {
125        CodegenConfig {
126            target: CodegenTarget::Rust,
127            optimize: true,
128            debug_info: false,
129            emit_comments: true,
130            inline_threshold: 50,
131        }
132    }
133}
134
135// ============================================================================
136// Intermediate Representation (IR) Types
137// ============================================================================
138
139/// Intermediate representation type for values
140#[derive(Debug, Clone, PartialEq, Eq, Hash)]
141pub enum IrType {
142    Unit,
143    Bool,
144    Nat,
145    Int,
146    String,
147    Var(String),
148    Function {
149        params: Vec<IrType>,
150        ret: Box<IrType>,
151    },
152    Struct {
153        name: String,
154        fields: Vec<(String, IrType)>,
155    },
156    Array {
157        elem: Box<IrType>,
158        len: usize,
159    },
160    Pointer(Box<IrType>),
161    Unknown,
162}
163
164impl fmt::Display for IrType {
165    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
166        match self {
167            IrType::Unit => write!(f, "()"),
168            IrType::Bool => write!(f, "bool"),
169            IrType::Nat => write!(f, "nat"),
170            IrType::Int => write!(f, "i64"),
171            IrType::String => write!(f, "string"),
172            IrType::Var(name) => write!(f, "{}", name),
173            IrType::Function { params, ret } => {
174                write!(f, "fn(")?;
175                for (i, p) in params.iter().enumerate() {
176                    if i > 0 {
177                        write!(f, ", ")?;
178                    }
179                    write!(f, "{}", p)?;
180                }
181                write!(f, ") -> {}", ret)
182            }
183            IrType::Struct { name, fields } => {
184                write!(f, "struct {} {{ ", name)?;
185                for (i, (fname, ftype)) in fields.iter().enumerate() {
186                    if i > 0 {
187                        write!(f, ", ")?;
188                    }
189                    write!(f, "{}: {}", fname, ftype)?;
190                }
191                write!(f, " }}")
192            }
193            IrType::Array { elem, len } => write!(f, "[{}; {}]", elem, len),
194            IrType::Pointer(ty) => write!(f, "*{}", ty),
195            IrType::Unknown => write!(f, "unknown"),
196        }
197    }
198}
199
200/// Intermediate representation literal values
201#[derive(Debug, Clone, PartialEq)]
202pub enum IrLit {
203    Unit,
204    Bool(bool),
205    Nat(u64),
206    Int(i64),
207    String(String),
208}
209
210impl fmt::Display for IrLit {
211    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
212        match self {
213            IrLit::Unit => write!(f, "()"),
214            IrLit::Bool(b) => write!(f, "{}", b),
215            IrLit::Nat(n) => write!(f, "{}", n),
216            IrLit::Int(i) => write!(f, "{}", i),
217            IrLit::String(s) => write!(f, "\"{}\"", s),
218        }
219    }
220}
221
222/// Pattern for match expressions
223#[derive(Debug, Clone, PartialEq, Eq, Hash)]
224pub enum IrPattern {
225    Wildcard,
226    Literal(String),
227    Constructor { name: String, args: Vec<String> },
228    Tuple(Vec<String>),
229    Or(Box<IrPattern>, Box<IrPattern>),
230}
231
232/// Match arm: pattern and body
233#[derive(Debug, Clone, PartialEq)]
234pub struct IrMatchArm {
235    pub pattern: IrPattern,
236    pub body: Box<IrExpr>,
237}
238
239/// Core intermediate representation expression
240#[derive(Debug, Clone, PartialEq)]
241pub enum IrExpr {
242    /// Variable reference
243    Var(String),
244
245    /// Literal value
246    Lit(IrLit),
247
248    /// Function application
249    App {
250        func: Box<IrExpr>,
251        args: Vec<IrExpr>,
252    },
253
254    /// Let binding
255    Let {
256        name: String,
257        ty: IrType,
258        value: Box<IrExpr>,
259        body: Box<IrExpr>,
260    },
261
262    /// Lambda abstraction (after closure conversion, becomes function reference)
263    Lambda {
264        params: Vec<(String, IrType)>,
265        body: Box<IrExpr>,
266        captured: Vec<String>,
267    },
268
269    /// Conditional expression
270    If {
271        cond: Box<IrExpr>,
272        then_branch: Box<IrExpr>,
273        else_branch: Box<IrExpr>,
274    },
275
276    /// Pattern match
277    Match {
278        scrutinee: Box<IrExpr>,
279        arms: Vec<IrMatchArm>,
280    },
281
282    /// Struct construction
283    Struct {
284        name: String,
285        fields: Vec<(String, IrExpr)>,
286    },
287
288    /// Field access
289    Field { object: Box<IrExpr>, field: String },
290
291    /// Memory allocation
292    Alloc(Box<IrExpr>),
293
294    /// Memory dereference
295    Deref(Box<IrExpr>),
296
297    /// Sequence of expressions
298    Seq(Vec<IrExpr>),
299}
300
301// ============================================================================
302// CSE Helper: Expression Key for HashMap lookup
303// ============================================================================
304
305/// A wrapper around a canonical string representation of an IrExpr used as a
306/// HashMap key in the CSE pass.  The second field holds the original expression
307/// so it can be reconstructed when building let-bindings.
308#[derive(Debug, Clone, PartialEq, Eq, Hash)]
309struct IrExprKey(String, Box<IrExprOwned>);
310
311/// Owned, hashable copy of an IrExpr (mirrors IrExpr but derives Hash/Eq).
312#[derive(Debug, Clone, PartialEq, Eq, Hash)]
313enum IrExprOwned {
314    Var(String),
315    Lit(String),
316    App(Box<IrExprOwned>, Vec<IrExprOwned>),
317    Other(String),
318}
319
320impl IrExprKey {
321    /// Build a key from an IrExpr by computing its canonical display string.
322    fn from(expr: &IrExpr) -> Self {
323        let repr = Self::repr(expr);
324        let owned = Self::to_owned(expr);
325        IrExprKey(repr, Box::new(owned))
326    }
327
328    /// True for trivial expressions (Var / Lit) that should not be hoisted.
329    fn is_trivial(&self) -> bool {
330        matches!(*self.1, IrExprOwned::Var(_) | IrExprOwned::Lit(_))
331    }
332
333    /// Compute a canonical string for an expression.
334    fn repr(expr: &IrExpr) -> String {
335        match expr {
336            IrExpr::Var(n) => format!("var:{}", n),
337            IrExpr::Lit(l) => format!("lit:{}", l),
338            IrExpr::App { func, args } => {
339                let args_repr: Vec<_> = args.iter().map(Self::repr).collect();
340                format!("app:{}({})", Self::repr(func), args_repr.join(","))
341            }
342            IrExpr::Let {
343                name, value, body, ..
344            } => {
345                format!("let:{}={};{}", name, Self::repr(value), Self::repr(body))
346            }
347            IrExpr::Lambda { params, body, .. } => {
348                let ps: Vec<_> = params.iter().map(|(n, _)| n.as_str()).collect();
349                format!("lam:{}:{}", ps.join(","), Self::repr(body))
350            }
351            IrExpr::If {
352                cond,
353                then_branch,
354                else_branch,
355            } => {
356                format!(
357                    "if:{}?{}:{}",
358                    Self::repr(cond),
359                    Self::repr(then_branch),
360                    Self::repr(else_branch)
361                )
362            }
363            IrExpr::Field { object, field } => {
364                format!("field:{}.{}", Self::repr(object), field)
365            }
366            IrExpr::Struct { name, fields } => {
367                let fs: Vec<_> = fields
368                    .iter()
369                    .map(|(k, v)| format!("{}={}", k, Self::repr(v)))
370                    .collect();
371                format!("struct:{}{{{}}}", name, fs.join(","))
372            }
373            IrExpr::Alloc(e) => format!("alloc:{}", Self::repr(e)),
374            IrExpr::Deref(e) => format!("deref:{}", Self::repr(e)),
375            IrExpr::Match { scrutinee, .. } => format!("match:{}", Self::repr(scrutinee)),
376            IrExpr::Seq(es) => {
377                let rs: Vec<_> = es.iter().map(Self::repr).collect();
378                format!("seq:[{}]", rs.join(","))
379            }
380        }
381    }
382
383    fn to_owned(expr: &IrExpr) -> IrExprOwned {
384        match expr {
385            IrExpr::Var(n) => IrExprOwned::Var(n.clone()),
386            IrExpr::Lit(l) => IrExprOwned::Lit(format!("{}", l)),
387            IrExpr::App { func, args } => IrExprOwned::App(
388                Box::new(Self::to_owned(func)),
389                args.iter().map(Self::to_owned).collect(),
390            ),
391            _ => IrExprOwned::Other(Self::repr(expr)),
392        }
393    }
394}
395
396// Reconstruct IrExpr from IrExprKey (used in CSE let-binding construction)
397impl IrExprKey {
398    /// Reconstruct the original IrExpr.  Since IrExprKey is only used for non-trivial
399    /// sub-expressions in the CSE pass, and `replace_subexprs` is called before
400    /// building let-bindings, we just need the key's representative expression
401    /// which is stored directly in the Optimizer's CSE pass via the original expr.
402    fn as_ir_expr(&self) -> IrExpr {
403        // The key stores a repr string; reconstruct as Var placeholder.
404        // Actual reconstruction happens via replace_subexprs called on the original.
405        IrExpr::Var(self.0.clone())
406    }
407}
408
409// ============================================================================
410// Code Generation Errors
411// ============================================================================
412
413/// Code generation errors
414#[derive(Debug, Clone)]
415pub enum CodegenError {
416    UnsupportedExpression(String),
417    UnsupportedType(String),
418    UnboundVariable(String),
419    TypeMismatch { expected: String, found: String },
420    InvalidPattern(String),
421    StructNotFound(String),
422    FieldNotFound { struct_name: String, field: String },
423    InternalError(String),
424}
425
426impl fmt::Display for CodegenError {
427    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
428        match self {
429            CodegenError::UnsupportedExpression(msg) => {
430                write!(f, "Unsupported expression: {}", msg)
431            }
432            CodegenError::UnsupportedType(msg) => {
433                write!(f, "Unsupported type: {}", msg)
434            }
435            CodegenError::UnboundVariable(name) => {
436                write!(f, "Unbound variable: {}", name)
437            }
438            CodegenError::TypeMismatch { expected, found } => {
439                write!(f, "Type mismatch: expected {}, found {}", expected, found)
440            }
441            CodegenError::InvalidPattern(msg) => {
442                write!(f, "Invalid pattern: {}", msg)
443            }
444            CodegenError::StructNotFound(name) => {
445                write!(f, "Struct not found: {}", name)
446            }
447            CodegenError::FieldNotFound { struct_name, field } => {
448                write!(f, "Field {} not found in struct {}", field, struct_name)
449            }
450            CodegenError::InternalError(msg) => {
451                write!(f, "Internal code generation error: {}", msg)
452            }
453        }
454    }
455}
456
457impl std::error::Error for CodegenError {}
458
459pub type CodegenResult<T> = Result<T, CodegenError>;
460
461// ============================================================================
462// Symbol Management and Renaming
463// ============================================================================
464
465/// Symbol manager for name mangling and closure conversion
466struct SymbolManager {
467    counter: usize,
468    scopes: VecDeque<HashSet<String>>,
469}
470
471impl SymbolManager {
472    fn new() -> Self {
473        SymbolManager {
474            counter: 0,
475            scopes: VecDeque::new(),
476        }
477    }
478
479    fn fresh_name(&mut self, base: &str) -> String {
480        let name = format!("{}_{}", base, self.counter);
481        self.counter += 1;
482        name
483    }
484
485    fn push_scope(&mut self) {
486        self.scopes.push_back(HashSet::new());
487    }
488
489    fn pop_scope(&mut self) {
490        self.scopes.pop_back();
491    }
492
493    fn bind(&mut self, name: String) {
494        if let Some(scope) = self.scopes.back_mut() {
495            scope.insert(name);
496        }
497    }
498
499    fn is_bound(&self, name: &str) -> bool {
500        self.scopes.iter().any(|scope| scope.contains(name))
501    }
502}
503
504// ============================================================================
505// Expression to IR Compiler
506// ============================================================================
507
508/// Compiles kernel expressions to intermediate representation
509pub struct ExprToIr {
510    symbol_manager: SymbolManager,
511    closure_vars: HashMap<String, Vec<String>>,
512}
513
514impl ExprToIr {
515    pub fn new() -> Self {
516        ExprToIr {
517            symbol_manager: SymbolManager::new(),
518            closure_vars: HashMap::new(),
519        }
520    }
521
522    /// Compile a kernel expression to IR
523    pub fn compile(&mut self, expr: &Expr) -> CodegenResult<IrExpr> {
524        match expr {
525            Expr::Const(name, _levels) => Ok(IrExpr::Var(name.to_string())),
526            Expr::FVar(id) => Ok(IrExpr::Var(format!("_fv{}", id.0))),
527            Expr::BVar(i) => Ok(IrExpr::Var(format!("_bv{}", i))),
528            Expr::App(f, arg) => {
529                let compiled_f = self.compile(f)?;
530                let compiled_arg = self.compile(arg)?;
531                // Flatten nested App(func, args) into multi-arg App
532                match compiled_f {
533                    IrExpr::App { func, mut args } => {
534                        args.push(compiled_arg);
535                        Ok(IrExpr::App { func, args })
536                    }
537                    func_ir => Ok(IrExpr::App {
538                        func: Box::new(func_ir),
539                        args: vec![compiled_arg],
540                    }),
541                }
542            }
543            Expr::Lam(_binder_info, name, _ty, body) => {
544                let param_name = name.to_string();
545                let compiled_body = self.compile(body)?;
546                Ok(IrExpr::Lambda {
547                    params: vec![(param_name, IrType::Unknown)],
548                    body: Box::new(compiled_body),
549                    captured: vec![],
550                })
551            }
552            Expr::Let(name, _ty, val, body) => {
553                let compiled_val = self.compile(val)?;
554                let compiled_body = self.compile(body)?;
555                Ok(IrExpr::Let {
556                    name: name.to_string(),
557                    ty: IrType::Unknown,
558                    value: Box::new(compiled_val),
559                    body: Box::new(compiled_body),
560                })
561            }
562            Expr::Lit(Literal::Nat(n)) => Ok(IrExpr::Lit(IrLit::Nat(*n))),
563            Expr::Lit(Literal::Str(s)) => Ok(IrExpr::Lit(IrLit::String(s.clone()))),
564            Expr::Sort(_) | Expr::Pi(_, _, _, _) => Ok(IrExpr::Var("Type".to_string())),
565            Expr::Proj(_name, idx, inner) => {
566                let compiled_inner = self.compile(inner)?;
567                let field = match idx {
568                    0 => "_fst".to_string(),
569                    1 => "_snd".to_string(),
570                    n => format!("_{}", n),
571                };
572                Ok(IrExpr::Field {
573                    object: Box::new(compiled_inner),
574                    field,
575                })
576            }
577        }
578    }
579
580    /// Perform lambda lifting transformation
581    fn lambda_lift(&mut self, expr: &IrExpr) -> IrExpr {
582        match expr {
583            IrExpr::Lambda {
584                params: _,
585                body: _,
586                captured,
587            } => {
588                let lifted_name = self.symbol_manager.fresh_name("lifted");
589                self.closure_vars
590                    .insert(lifted_name.clone(), captured.clone());
591                IrExpr::Var(lifted_name)
592            }
593            IrExpr::Let {
594                name,
595                ty,
596                value,
597                body,
598            } => IrExpr::Let {
599                name: name.clone(),
600                ty: ty.clone(),
601                value: Box::new(self.lambda_lift(value)),
602                body: Box::new(self.lambda_lift(body)),
603            },
604            IrExpr::App { func, args } => IrExpr::App {
605                func: Box::new(self.lambda_lift(func)),
606                args: args.iter().map(|a| self.lambda_lift(a)).collect(),
607            },
608            IrExpr::If {
609                cond,
610                then_branch,
611                else_branch,
612            } => IrExpr::If {
613                cond: Box::new(self.lambda_lift(cond)),
614                then_branch: Box::new(self.lambda_lift(then_branch)),
615                else_branch: Box::new(self.lambda_lift(else_branch)),
616            },
617            _ => expr.clone(),
618        }
619    }
620
621    /// Perform closure conversion
622    fn closure_convert(&mut self, expr: &IrExpr) -> IrExpr {
623        match expr {
624            IrExpr::Lambda {
625                params: _,
626                body,
627                captured,
628            } => {
629                let closure_name = self.symbol_manager.fresh_name("closure");
630                let _converted_body = self.closure_convert(body);
631
632                IrExpr::Struct {
633                    name: format!("Closure_{}", closure_name),
634                    fields: captured
635                        .iter()
636                        .map(|v| (v.clone(), IrExpr::Var(v.clone())))
637                        .collect(),
638                }
639            }
640            IrExpr::Let {
641                name,
642                ty,
643                value,
644                body,
645            } => IrExpr::Let {
646                name: name.clone(),
647                ty: ty.clone(),
648                value: Box::new(self.closure_convert(value)),
649                body: Box::new(self.closure_convert(body)),
650            },
651            _ => expr.clone(),
652        }
653    }
654}
655
656impl Default for ExprToIr {
657    fn default() -> Self {
658        Self::new()
659    }
660}
661
662// ============================================================================
663// Rust Code Emitter
664// ============================================================================
665
666/// Helper struct for emitting Rust code
667struct RustEmitter {
668    output: String,
669    indent_level: usize,
670}
671
672impl RustEmitter {
673    fn new() -> Self {
674        RustEmitter {
675            output: String::new(),
676            indent_level: 0,
677        }
678    }
679
680    fn indent(&mut self) {
681        self.indent_level += 1;
682    }
683
684    fn dedent(&mut self) {
685        if self.indent_level > 0 {
686            self.indent_level -= 1;
687        }
688    }
689
690    fn emit(&mut self, line: &str) {
691        for _ in 0..self.indent_level {
692            self.output.push_str("    ");
693        }
694        self.output.push_str(line);
695        self.output.push('\n');
696    }
697
698    fn emit_inline(&mut self, text: &str) {
699        self.output.push_str(text);
700    }
701
702    fn result(&self) -> String {
703        self.output.clone()
704    }
705}
706
707/// IR to Rust code generator
708pub struct IrToRust {
709    config: CodegenConfig,
710}
711
712impl IrToRust {
713    pub fn new(config: CodegenConfig) -> Self {
714        IrToRust { config }
715    }
716
717    /// Emit complete Rust code for an IR expression
718    pub fn emit(&self, expr: &IrExpr) -> CodegenResult<String> {
719        let mut emitter = RustEmitter::new();
720        self.emit_expr(&mut emitter, expr)?;
721        Ok(emitter.result())
722    }
723
724    fn emit_expr(&self, emitter: &mut RustEmitter, expr: &IrExpr) -> CodegenResult<()> {
725        match expr {
726            IrExpr::Var(name) => {
727                emitter.emit_inline(name);
728            }
729            IrExpr::Lit(lit) => {
730                emitter.emit_inline(&lit.to_string());
731            }
732            IrExpr::App { func, args } => {
733                self.emit_expr(emitter, func)?;
734                emitter.emit_inline("(");
735                for (i, arg) in args.iter().enumerate() {
736                    if i > 0 {
737                        emitter.emit_inline(", ");
738                    }
739                    self.emit_expr(emitter, arg)?;
740                }
741                emitter.emit_inline(")");
742            }
743            IrExpr::Let {
744                name,
745                ty,
746                value,
747                body,
748            } => {
749                emitter.emit(&format!("let {} : {} = ", name, self.emit_type(ty)?));
750                self.emit_expr(emitter, value)?;
751                emitter.emit_inline(";");
752                self.emit_expr(emitter, body)?;
753            }
754            IrExpr::Lambda {
755                params,
756                body,
757                captured: _,
758            } => {
759                emitter.emit_inline("|");
760                for (i, (pname, ptype)) in params.iter().enumerate() {
761                    if i > 0 {
762                        emitter.emit_inline(", ");
763                    }
764                    emitter.emit_inline(&format!("{}: {}", pname, self.emit_type(ptype)?));
765                }
766                emitter.emit_inline("| {");
767                self.emit_expr(emitter, body)?;
768                emitter.emit_inline("}");
769            }
770            IrExpr::If {
771                cond,
772                then_branch,
773                else_branch,
774            } => {
775                emitter.emit_inline("if ");
776                self.emit_expr(emitter, cond)?;
777                emitter.emit_inline(" { ");
778                self.emit_expr(emitter, then_branch)?;
779                emitter.emit_inline(" } else { ");
780                self.emit_expr(emitter, else_branch)?;
781                emitter.emit_inline(" }");
782            }
783            IrExpr::Match { scrutinee, arms } => {
784                emitter.emit_inline("match ");
785                self.emit_expr(emitter, scrutinee)?;
786                emitter.emit_inline(" {");
787                for arm in arms {
788                    emitter.emit(&format!("    {} => {{", self.emit_pattern(&arm.pattern)?));
789                    self.emit_expr(emitter, &arm.body)?;
790                    emitter.emit("}");
791                }
792                emitter.emit("}");
793            }
794            IrExpr::Struct { name, fields } => {
795                emitter.emit_inline(&format!("{} {{ ", name));
796                for (i, (fname, fvalue)) in fields.iter().enumerate() {
797                    if i > 0 {
798                        emitter.emit_inline(", ");
799                    }
800                    emitter.emit_inline(&format!("{}: ", fname));
801                    self.emit_expr(emitter, fvalue)?;
802                }
803                emitter.emit_inline(" }");
804            }
805            IrExpr::Field { object, field } => {
806                self.emit_expr(emitter, object)?;
807                emitter.emit_inline(&format!(".{}", field));
808            }
809            IrExpr::Alloc(expr) => {
810                emitter.emit_inline("Box::new(");
811                self.emit_expr(emitter, expr)?;
812                emitter.emit_inline(")");
813            }
814            IrExpr::Deref(expr) => {
815                emitter.emit_inline("*");
816                self.emit_expr(emitter, expr)?;
817            }
818            IrExpr::Seq(exprs) => {
819                emitter.emit_inline("{ ");
820                for expr in exprs {
821                    self.emit_expr(emitter, expr)?;
822                    emitter.emit_inline("; ");
823                }
824                emitter.emit_inline("}");
825            }
826        }
827        Ok(())
828    }
829
830    fn emit_type(&self, ty: &IrType) -> CodegenResult<String> {
831        Ok(match ty {
832            IrType::Unit => "()".to_string(),
833            IrType::Bool => "bool".to_string(),
834            IrType::Nat => "u64".to_string(),
835            IrType::Int => "i64".to_string(),
836            IrType::String => "String".to_string(),
837            IrType::Var(name) => name.clone(),
838            IrType::Function { params, ret } => {
839                let param_strs: CodegenResult<Vec<_>> =
840                    params.iter().map(|p| self.emit_type(p)).collect();
841                let ret_str = self.emit_type(ret)?;
842                format!("fn({}) -> {}", param_strs?.join(", "), ret_str)
843            }
844            IrType::Array { elem, len } => {
845                let elem_str = self.emit_type(elem)?;
846                format!("[{}; {}]", elem_str, len)
847            }
848            IrType::Pointer(ty) => {
849                let ty_str = self.emit_type(ty)?;
850                format!("*{}", ty_str)
851            }
852            _ => "unknown".to_string(),
853        })
854    }
855
856    fn emit_pattern(&self, pattern: &IrPattern) -> CodegenResult<String> {
857        Ok(match pattern {
858            IrPattern::Wildcard => "_".to_string(),
859            IrPattern::Literal(lit) => lit.clone(),
860            IrPattern::Constructor { name, args } => {
861                format!("{}({})", name, args.join(", "))
862            }
863            IrPattern::Tuple(vars) => format!("({})", vars.join(", ")),
864            IrPattern::Or(p1, p2) => {
865                format!("{} | {}", self.emit_pattern(p1)?, self.emit_pattern(p2)?)
866            }
867        })
868    }
869
870    pub fn emit_function(
871        &self,
872        name: &str,
873        params: &[(String, IrType)],
874        ret_type: &IrType,
875        body: &IrExpr,
876    ) -> CodegenResult<String> {
877        let mut emitter = RustEmitter::new();
878        emitter.emit(&format!("fn {}(", name));
879        for (i, (pname, ptype)) in params.iter().enumerate() {
880            if i > 0 {
881                emitter.emit_inline(", ");
882            }
883            emitter.emit_inline(&format!("{}: {}", pname, self.emit_type(ptype)?));
884        }
885        emitter.emit_inline(&format!(") -> {} {{", self.emit_type(ret_type)?));
886        emitter.indent();
887        self.emit_expr(&mut emitter, body)?;
888        emitter.dedent();
889        emitter.emit("}");
890        Ok(emitter.result())
891    }
892
893    pub fn emit_struct(&self, name: &str, fields: &[(String, IrType)]) -> CodegenResult<String> {
894        let mut emitter = RustEmitter::new();
895        emitter.emit(&format!("struct {} {{", name));
896        emitter.indent();
897        for (fname, ftype) in fields {
898            emitter.emit(&format!("{}: {},", fname, self.emit_type(ftype)?));
899        }
900        emitter.dedent();
901        emitter.emit("}");
902        Ok(emitter.result())
903    }
904
905    pub fn emit_match(&self, scrutinee: &IrExpr, arms: &[IrMatchArm]) -> CodegenResult<String> {
906        let mut emitter = RustEmitter::new();
907        emitter.emit_inline("match ");
908        self.emit_expr(&mut emitter, scrutinee)?;
909        emitter.emit_inline(" {");
910        emitter.indent();
911        for arm in arms {
912            emitter.emit(&format!("{} => {{", self.emit_pattern(&arm.pattern)?));
913            emitter.indent();
914            self.emit_expr(&mut emitter, &arm.body)?;
915            emitter.dedent();
916            emitter.emit("}");
917        }
918        emitter.dedent();
919        emitter.emit("}");
920        Ok(emitter.result())
921    }
922}
923
924// ============================================================================
925// C Code Emitter
926// ============================================================================
927
928/// IR to C code generator with reference counting
929pub struct IrToC {
930    config: CodegenConfig,
931}
932
933impl IrToC {
934    pub fn new(config: CodegenConfig) -> Self {
935        IrToC { config }
936    }
937
938    /// Emit C code for an IR expression
939    pub fn emit(&self, expr: &IrExpr) -> CodegenResult<String> {
940        let mut code = String::new();
941        self.emit_expr(&mut code, expr)?;
942        Ok(code)
943    }
944
945    fn emit_expr(&self, code: &mut String, expr: &IrExpr) -> CodegenResult<()> {
946        match expr {
947            IrExpr::Var(name) => {
948                code.push_str(name);
949            }
950            IrExpr::Lit(lit) => {
951                code.push_str(&lit.to_string());
952            }
953            IrExpr::App { func, args } => {
954                self.emit_expr(code, func)?;
955                code.push('(');
956                for (i, arg) in args.iter().enumerate() {
957                    if i > 0 {
958                        code.push_str(", ");
959                    }
960                    self.emit_expr(code, arg)?;
961                }
962                code.push(')');
963            }
964            IrExpr::Field { object, field } => {
965                self.emit_expr(code, object)?;
966                code.push_str(&format!("->{}", field));
967            }
968            _ => {
969                return Err(CodegenError::UnsupportedExpression(format!("{:?}", expr)));
970            }
971        }
972        Ok(())
973    }
974
975    pub fn emit_c_type(&self, ty: &IrType) -> CodegenResult<String> {
976        Ok(match ty {
977            IrType::Unit => "void".to_string(),
978            IrType::Bool => "bool".to_string(),
979            IrType::Nat => "uint64_t".to_string(),
980            IrType::Int => "int64_t".to_string(),
981            IrType::String => "char*".to_string(),
982            IrType::Pointer(inner) => {
983                format!("{}*", self.emit_c_type(inner)?)
984            }
985            _ => return Err(CodegenError::UnsupportedType(ty.to_string())),
986        })
987    }
988}
989
990// ============================================================================
991// IR Optimizer
992// ============================================================================
993
994/// Intermediate representation optimizer
995pub struct Optimizer {
996    config: CodegenConfig,
997}
998
999impl Optimizer {
1000    pub fn new(config: CodegenConfig) -> Self {
1001        Optimizer { config }
1002    }
1003
1004    /// Optimize an IR expression
1005    pub fn optimize(&self, expr: &IrExpr) -> CodegenResult<IrExpr> {
1006        let expr = self.constant_fold(expr)?;
1007        let expr = self.dead_code_eliminate(&expr)?;
1008        let expr = self.inline(&expr)?;
1009        self.common_subexpr_eliminate(&expr)
1010    }
1011
1012    /// Constant folding optimization
1013    fn constant_fold(&self, expr: &IrExpr) -> CodegenResult<IrExpr> {
1014        match expr {
1015            IrExpr::Let {
1016                name,
1017                ty,
1018                value,
1019                body,
1020            } => {
1021                let folded_value = self.constant_fold(value)?;
1022                let folded_body = self.constant_fold(body)?;
1023                Ok(IrExpr::Let {
1024                    name: name.clone(),
1025                    ty: ty.clone(),
1026                    value: Box::new(folded_value),
1027                    body: Box::new(folded_body),
1028                })
1029            }
1030            IrExpr::If {
1031                cond,
1032                then_branch,
1033                else_branch,
1034            } => {
1035                if let IrExpr::Lit(IrLit::Bool(b)) = **cond {
1036                    let folded = if b {
1037                        self.constant_fold(then_branch)?
1038                    } else {
1039                        self.constant_fold(else_branch)?
1040                    };
1041                    Ok(folded)
1042                } else {
1043                    let cond_folded = self.constant_fold(cond)?;
1044                    let then_folded = self.constant_fold(then_branch)?;
1045                    let else_folded = self.constant_fold(else_branch)?;
1046                    Ok(IrExpr::If {
1047                        cond: Box::new(cond_folded),
1048                        then_branch: Box::new(then_folded),
1049                        else_branch: Box::new(else_folded),
1050                    })
1051                }
1052            }
1053            _ => Ok(expr.clone()),
1054        }
1055    }
1056
1057    /// Dead code elimination
1058    fn dead_code_eliminate(&self, expr: &IrExpr) -> CodegenResult<IrExpr> {
1059        match expr {
1060            IrExpr::Let {
1061                name,
1062                ty,
1063                value,
1064                body,
1065            } => {
1066                let used = self.is_var_used(name, body);
1067                if used {
1068                    let value_opt = self.dead_code_eliminate(value)?;
1069                    let body_opt = self.dead_code_eliminate(body)?;
1070                    Ok(IrExpr::Let {
1071                        name: name.clone(),
1072                        ty: ty.clone(),
1073                        value: Box::new(value_opt),
1074                        body: Box::new(body_opt),
1075                    })
1076                } else {
1077                    self.dead_code_eliminate(body)
1078                }
1079            }
1080            _ => Ok(expr.clone()),
1081        }
1082    }
1083
1084    /// Check if a variable is used in an expression
1085    fn is_var_used(&self, name: &str, expr: &IrExpr) -> bool {
1086        match expr {
1087            IrExpr::Var(n) => n == name,
1088            IrExpr::Let { value, body, .. } => {
1089                self.is_var_used(name, value) || self.is_var_used(name, body)
1090            }
1091            IrExpr::App { func, args } => {
1092                self.is_var_used(name, func) || args.iter().any(|a| self.is_var_used(name, a))
1093            }
1094            IrExpr::If {
1095                cond,
1096                then_branch,
1097                else_branch,
1098            } => {
1099                self.is_var_used(name, cond)
1100                    || self.is_var_used(name, then_branch)
1101                    || self.is_var_used(name, else_branch)
1102            }
1103            _ => false,
1104        }
1105    }
1106
1107    /// Function inlining optimization
1108    ///
1109    /// Performs beta reduction: `(fun x -> body) arg` is substituted inline
1110    /// when the argument size is within `inline_threshold`.
1111    fn inline(&self, expr: &IrExpr) -> CodegenResult<IrExpr> {
1112        match expr {
1113            IrExpr::App { func, args } => {
1114                let inlined_func = self.inline(func)?;
1115                let inlined_args: CodegenResult<Vec<IrExpr>> =
1116                    args.iter().map(|a| self.inline(a)).collect();
1117                let inlined_args = inlined_args?;
1118
1119                // Beta reduction: (fun (x, ...) -> body) applied to args
1120                if let IrExpr::Lambda { params, body, .. } = &inlined_func {
1121                    let arg_size = self.expr_size(&IrExpr::App {
1122                        func: Box::new(inlined_func.clone()),
1123                        args: inlined_args.clone(),
1124                    });
1125                    if arg_size <= self.config.inline_threshold
1126                        && params.len() == inlined_args.len()
1127                    {
1128                        // Substitute each argument for its parameter (innermost first)
1129                        let mut result = *body.clone();
1130                        for ((_param_name, _param_ty), arg) in
1131                            params.iter().zip(inlined_args.iter())
1132                        {
1133                            result = self.subst_var(&result, &_param_name.clone(), arg);
1134                        }
1135                        return self.inline(&result);
1136                    }
1137                }
1138
1139                Ok(IrExpr::App {
1140                    func: Box::new(inlined_func),
1141                    args: inlined_args,
1142                })
1143            }
1144            IrExpr::Let {
1145                name,
1146                ty,
1147                value,
1148                body,
1149            } => {
1150                let inlined_value = self.inline(value)?;
1151                let inlined_body = self.inline(body)?;
1152                Ok(IrExpr::Let {
1153                    name: name.clone(),
1154                    ty: ty.clone(),
1155                    value: Box::new(inlined_value),
1156                    body: Box::new(inlined_body),
1157                })
1158            }
1159            IrExpr::Lambda {
1160                params,
1161                body,
1162                captured,
1163            } => {
1164                let inlined_body = self.inline(body)?;
1165                Ok(IrExpr::Lambda {
1166                    params: params.clone(),
1167                    body: Box::new(inlined_body),
1168                    captured: captured.clone(),
1169                })
1170            }
1171            IrExpr::If {
1172                cond,
1173                then_branch,
1174                else_branch,
1175            } => Ok(IrExpr::If {
1176                cond: Box::new(self.inline(cond)?),
1177                then_branch: Box::new(self.inline(then_branch)?),
1178                else_branch: Box::new(self.inline(else_branch)?),
1179            }),
1180            _ => Ok(expr.clone()),
1181        }
1182    }
1183
1184    /// Substitute occurrences of `var_name` with `replacement` in `expr`.
1185    fn subst_var(&self, expr: &IrExpr, var_name: &str, replacement: &IrExpr) -> IrExpr {
1186        match expr {
1187            IrExpr::Var(n) if n == var_name => replacement.clone(),
1188            IrExpr::App { func, args } => IrExpr::App {
1189                func: Box::new(self.subst_var(func, var_name, replacement)),
1190                args: args
1191                    .iter()
1192                    .map(|a| self.subst_var(a, var_name, replacement))
1193                    .collect(),
1194            },
1195            IrExpr::Let {
1196                name,
1197                ty,
1198                value,
1199                body,
1200            } => {
1201                let new_value = self.subst_var(value, var_name, replacement);
1202                // Do not substitute inside body if the let binding shadows var_name
1203                let new_body = if name == var_name {
1204                    *body.clone()
1205                } else {
1206                    self.subst_var(body, var_name, replacement)
1207                };
1208                IrExpr::Let {
1209                    name: name.clone(),
1210                    ty: ty.clone(),
1211                    value: Box::new(new_value),
1212                    body: Box::new(new_body),
1213                }
1214            }
1215            IrExpr::Lambda {
1216                params,
1217                body,
1218                captured,
1219            } => {
1220                // Do not substitute if param shadows the variable
1221                if params.iter().any(|(p, _)| p == var_name) {
1222                    expr.clone()
1223                } else {
1224                    IrExpr::Lambda {
1225                        params: params.clone(),
1226                        body: Box::new(self.subst_var(body, var_name, replacement)),
1227                        captured: captured.clone(),
1228                    }
1229                }
1230            }
1231            IrExpr::If {
1232                cond,
1233                then_branch,
1234                else_branch,
1235            } => IrExpr::If {
1236                cond: Box::new(self.subst_var(cond, var_name, replacement)),
1237                then_branch: Box::new(self.subst_var(then_branch, var_name, replacement)),
1238                else_branch: Box::new(self.subst_var(else_branch, var_name, replacement)),
1239            },
1240            IrExpr::Field { object, field } => IrExpr::Field {
1241                object: Box::new(self.subst_var(object, var_name, replacement)),
1242                field: field.clone(),
1243            },
1244            IrExpr::Alloc(inner) => {
1245                IrExpr::Alloc(Box::new(self.subst_var(inner, var_name, replacement)))
1246            }
1247            IrExpr::Deref(inner) => {
1248                IrExpr::Deref(Box::new(self.subst_var(inner, var_name, replacement)))
1249            }
1250            IrExpr::Seq(exprs) => IrExpr::Seq(
1251                exprs
1252                    .iter()
1253                    .map(|e| self.subst_var(e, var_name, replacement))
1254                    .collect(),
1255            ),
1256            _ => expr.clone(),
1257        }
1258    }
1259
1260    /// Estimate the size of an IR expression (used for inline threshold).
1261    fn expr_size(&self, expr: &IrExpr) -> usize {
1262        match expr {
1263            IrExpr::Var(_) | IrExpr::Lit(_) => 1,
1264            IrExpr::App { func, args } => {
1265                1 + self.expr_size(func) + args.iter().map(|a| self.expr_size(a)).sum::<usize>()
1266            }
1267            IrExpr::Let { value, body, .. } => 1 + self.expr_size(value) + self.expr_size(body),
1268            IrExpr::Lambda { body, .. } => 1 + self.expr_size(body),
1269            IrExpr::If {
1270                cond,
1271                then_branch,
1272                else_branch,
1273            } => {
1274                1 + self.expr_size(cond) + self.expr_size(then_branch) + self.expr_size(else_branch)
1275            }
1276            IrExpr::Match { scrutinee, arms } => {
1277                1 + self.expr_size(scrutinee)
1278                    + arms.iter().map(|a| self.expr_size(&a.body)).sum::<usize>()
1279            }
1280            IrExpr::Struct { fields, .. } => {
1281                1 + fields.iter().map(|(_, e)| self.expr_size(e)).sum::<usize>()
1282            }
1283            IrExpr::Field { object, .. } => 1 + self.expr_size(object),
1284            IrExpr::Alloc(e) | IrExpr::Deref(e) => 1 + self.expr_size(e),
1285            IrExpr::Seq(es) => es.iter().map(|e| self.expr_size(e)).sum(),
1286        }
1287    }
1288
1289    /// Common subexpression elimination
1290    ///
1291    /// Collects subexpressions that appear more than once and hoists them
1292    /// to let-bindings at the top of the expression, replacing duplicates
1293    /// with variable references.
1294    fn common_subexpr_eliminate(&self, expr: &IrExpr) -> CodegenResult<IrExpr> {
1295        // Step 1: count occurrences of each sub-expression
1296        let mut counts: HashMap<IrExprKey, usize> = HashMap::new();
1297        self.count_subexprs(expr, &mut counts);
1298
1299        // Step 2: collect subexpressions that appear >1 time and are non-trivial
1300        let mut to_hoist: Vec<IrExprKey> = counts
1301            .iter()
1302            .filter(|(key, &count)| count > 1 && !key.is_trivial())
1303            .map(|(key, _)| key.clone())
1304            .collect();
1305        // Deterministic ordering: sort by string representation
1306        to_hoist.sort_by_key(|k| k.0.clone());
1307
1308        if to_hoist.is_empty() {
1309            return Ok(expr.clone());
1310        }
1311
1312        // Step 3: assign fresh names and build substitution map
1313        let mut subst: HashMap<IrExprKey, String> = HashMap::new();
1314        for (counter, key) in to_hoist.iter().enumerate() {
1315            let name = format!("_cse{}", counter);
1316            subst.insert(key.clone(), name);
1317        }
1318
1319        // Step 4: rewrite expression replacing duplicates with vars
1320        let rewritten = self.replace_subexprs(expr, &subst);
1321
1322        // Step 5: wrap with let-bindings (innermost first means last hoist is outermost)
1323        let mut result = rewritten;
1324        for key in to_hoist.iter().rev() {
1325            let var_name = subst[key].clone();
1326            // Reconstruct the original subexpression from its key
1327            let key_ir = key.as_ir_expr();
1328            let value_expr = self.replace_subexprs(&key_ir, &subst);
1329            result = IrExpr::Let {
1330                name: var_name,
1331                ty: IrType::Unknown,
1332                value: Box::new(value_expr),
1333                body: Box::new(result),
1334            };
1335        }
1336
1337        Ok(result)
1338    }
1339
1340    /// Count occurrences of each sub-expression in the tree.
1341    fn count_subexprs(&self, expr: &IrExpr, counts: &mut HashMap<IrExprKey, usize>) {
1342        let key = IrExprKey::from(expr);
1343        *counts.entry(key).or_insert(0) += 1;
1344        match expr {
1345            IrExpr::App { func, args } => {
1346                self.count_subexprs(func, counts);
1347                for a in args {
1348                    self.count_subexprs(a, counts);
1349                }
1350            }
1351            IrExpr::Let { value, body, .. } => {
1352                self.count_subexprs(value, counts);
1353                self.count_subexprs(body, counts);
1354            }
1355            IrExpr::Lambda { body, .. } => self.count_subexprs(body, counts),
1356            IrExpr::If {
1357                cond,
1358                then_branch,
1359                else_branch,
1360            } => {
1361                self.count_subexprs(cond, counts);
1362                self.count_subexprs(then_branch, counts);
1363                self.count_subexprs(else_branch, counts);
1364            }
1365            IrExpr::Match { scrutinee, arms } => {
1366                self.count_subexprs(scrutinee, counts);
1367                for arm in arms {
1368                    self.count_subexprs(&arm.body, counts);
1369                }
1370            }
1371            IrExpr::Struct { fields, .. } => {
1372                for (_, e) in fields {
1373                    self.count_subexprs(e, counts);
1374                }
1375            }
1376            IrExpr::Field { object, .. } => self.count_subexprs(object, counts),
1377            IrExpr::Alloc(e) | IrExpr::Deref(e) => self.count_subexprs(e, counts),
1378            IrExpr::Seq(es) => {
1379                for e in es {
1380                    self.count_subexprs(e, counts);
1381                }
1382            }
1383            IrExpr::Var(_) | IrExpr::Lit(_) => {}
1384        }
1385    }
1386
1387    /// Replace subexpressions in `expr` according to the substitution map.
1388    fn replace_subexprs(&self, expr: &IrExpr, subst: &HashMap<IrExprKey, String>) -> IrExpr {
1389        let key = IrExprKey::from(expr);
1390        if let Some(var_name) = subst.get(&key) {
1391            return IrExpr::Var(var_name.clone());
1392        }
1393        match expr {
1394            IrExpr::App { func, args } => IrExpr::App {
1395                func: Box::new(self.replace_subexprs(func, subst)),
1396                args: args
1397                    .iter()
1398                    .map(|a| self.replace_subexprs(a, subst))
1399                    .collect(),
1400            },
1401            IrExpr::Let {
1402                name,
1403                ty,
1404                value,
1405                body,
1406            } => IrExpr::Let {
1407                name: name.clone(),
1408                ty: ty.clone(),
1409                value: Box::new(self.replace_subexprs(value, subst)),
1410                body: Box::new(self.replace_subexprs(body, subst)),
1411            },
1412            IrExpr::Lambda {
1413                params,
1414                body,
1415                captured,
1416            } => IrExpr::Lambda {
1417                params: params.clone(),
1418                body: Box::new(self.replace_subexprs(body, subst)),
1419                captured: captured.clone(),
1420            },
1421            IrExpr::If {
1422                cond,
1423                then_branch,
1424                else_branch,
1425            } => IrExpr::If {
1426                cond: Box::new(self.replace_subexprs(cond, subst)),
1427                then_branch: Box::new(self.replace_subexprs(then_branch, subst)),
1428                else_branch: Box::new(self.replace_subexprs(else_branch, subst)),
1429            },
1430            IrExpr::Match { scrutinee, arms } => IrExpr::Match {
1431                scrutinee: Box::new(self.replace_subexprs(scrutinee, subst)),
1432                arms: arms
1433                    .iter()
1434                    .map(|a| IrMatchArm {
1435                        pattern: a.pattern.clone(),
1436                        body: Box::new(self.replace_subexprs(&a.body, subst)),
1437                    })
1438                    .collect(),
1439            },
1440            IrExpr::Struct { name, fields } => IrExpr::Struct {
1441                name: name.clone(),
1442                fields: fields
1443                    .iter()
1444                    .map(|(k, v)| (k.clone(), self.replace_subexprs(v, subst)))
1445                    .collect(),
1446            },
1447            IrExpr::Field { object, field } => IrExpr::Field {
1448                object: Box::new(self.replace_subexprs(object, subst)),
1449                field: field.clone(),
1450            },
1451            IrExpr::Alloc(e) => IrExpr::Alloc(Box::new(self.replace_subexprs(e, subst))),
1452            IrExpr::Deref(e) => IrExpr::Deref(Box::new(self.replace_subexprs(e, subst))),
1453            IrExpr::Seq(es) => {
1454                IrExpr::Seq(es.iter().map(|e| self.replace_subexprs(e, subst)).collect())
1455            }
1456            IrExpr::Var(_) | IrExpr::Lit(_) => expr.clone(),
1457        }
1458    }
1459}
1460
1461// ============================================================================
1462// Code Generation Pipeline
1463// ============================================================================
1464
1465/// Main code generation pipeline
1466pub struct CodegenPipeline {
1467    config: CodegenConfig,
1468    expr_compiler: ExprToIr,
1469    optimizer: Optimizer,
1470}
1471
1472impl CodegenPipeline {
1473    pub fn new(config: CodegenConfig) -> Self {
1474        let optimizer = Optimizer::new(config.clone());
1475        CodegenPipeline {
1476            config,
1477            expr_compiler: ExprToIr::new(),
1478            optimizer,
1479        }
1480    }
1481
1482    /// Compile a kernel declaration to target code
1483    pub fn compile_declaration(&mut self, expr: &Expr) -> CodegenResult<String> {
1484        let ir = self.expr_compiler.compile(expr)?;
1485
1486        let ir = if self.config.optimize {
1487            self.optimizer.optimize(&ir)?
1488        } else {
1489            ir
1490        };
1491
1492        match self.config.target {
1493            CodegenTarget::Rust => {
1494                let rust_gen = IrToRust::new(self.config.clone());
1495                rust_gen.emit(&ir)
1496            }
1497            CodegenTarget::C => {
1498                let c_gen = IrToC::new(self.config.clone());
1499                c_gen.emit(&ir)
1500            }
1501            CodegenTarget::LlvmIr => {
1502                self.emit_llvm_ir(&ir)
1503            }
1504            CodegenTarget::Interpreter => {
1505                Err(CodegenError::UnsupportedExpression(
1506                    "Interpreter target does not support single-expression compilation; use compile_module instead".to_string()
1507                ))
1508            }
1509        }
1510    }
1511
1512    /// Emit LLVM IR text for an IR expression.
1513    fn emit_llvm_ir(&self, expr: &IrExpr) -> CodegenResult<String> {
1514        let mut out = String::new();
1515        out.push_str("; LLVM IR generated by Oxilean codegen\n");
1516        out.push_str("define i64 @oxilean_expr() {\n");
1517        out.push_str("entry:\n");
1518        self.emit_llvm_expr(&mut out, expr, 0)?;
1519        out.push_str("  ret i64 %result\n");
1520        out.push_str("}\n");
1521        Ok(out)
1522    }
1523
1524    /// Recursively emit LLVM IR for an IR expression (simplified).
1525    fn emit_llvm_expr(
1526        &self,
1527        out: &mut String,
1528        expr: &IrExpr,
1529        depth: usize,
1530    ) -> CodegenResult<String> {
1531        let _ = depth;
1532        match expr {
1533            IrExpr::Lit(IrLit::Nat(n)) => {
1534                out.push_str(&format!("  %result = add i64 0, {}\n", n));
1535                Ok("%result".to_string())
1536            }
1537            IrExpr::Lit(IrLit::Int(n)) => {
1538                out.push_str(&format!("  %result = add i64 0, {}\n", n));
1539                Ok("%result".to_string())
1540            }
1541            IrExpr::Lit(IrLit::Bool(b)) => {
1542                let v: u8 = if *b { 1 } else { 0 };
1543                out.push_str(&format!("  %result = add i1 0, {}\n", v));
1544                Ok("%result".to_string())
1545            }
1546            IrExpr::Lit(IrLit::Unit) => Ok("void".to_string()),
1547            IrExpr::Var(name) => Ok(format!("%{}", name)),
1548            IrExpr::App { func, args: _ } => {
1549                let fname = self.emit_llvm_expr(out, func, depth + 1)?;
1550                out.push_str(&format!("  %result = call i64 {}()\n", fname));
1551                Ok("%result".to_string())
1552            }
1553            _ => {
1554                out.push_str("  %result = add i64 0, 0 ; unsupported expr\n");
1555                Ok("%result".to_string())
1556            }
1557        }
1558    }
1559
1560    /// Compile a module (collection of declarations)
1561    pub fn compile_module(&mut self, exprs: Vec<&Expr>) -> CodegenResult<String> {
1562        if exprs.is_empty() {
1563            return Ok(match self.config.target {
1564                CodegenTarget::Rust => "// Empty module\n".to_string(),
1565                CodegenTarget::C => "/* Empty module */\n".to_string(),
1566                CodegenTarget::LlvmIr => "; Empty LLVM IR module\n".to_string(),
1567                CodegenTarget::Interpreter => "[]\n".to_string(),
1568            });
1569        }
1570
1571        let mut parts: Vec<String> = Vec::new();
1572        for (i, expr) in exprs.iter().enumerate() {
1573            match self.compile_declaration(expr) {
1574                Ok(code) => parts.push(code),
1575                Err(e) => {
1576                    return Err(CodegenError::InternalError(format!(
1577                        "Failed to compile declaration {}: {}",
1578                        i, e
1579                    )));
1580                }
1581            }
1582        }
1583
1584        let separator = match self.config.target {
1585            CodegenTarget::Rust => "\n\n",
1586            CodegenTarget::C => "\n\n",
1587            CodegenTarget::LlvmIr => "\n",
1588            CodegenTarget::Interpreter => "\n",
1589        };
1590
1591        let mut output = parts.join(separator);
1592        if self.config.target == CodegenTarget::LlvmIr {
1593            output = format!(
1594                "; LLVM IR module ({} declarations)\n{}",
1595                parts.len(),
1596                output
1597            );
1598        }
1599        Ok(output)
1600    }
1601}
1602
1603// ============================================================================
1604// Tests
1605// ============================================================================
1606
1607#[cfg(test)]
1608mod tests {
1609    use super::*;
1610
1611    #[test]
1612    fn test_ir_type_display() {
1613        assert_eq!(IrType::Unit.to_string(), "()");
1614        assert_eq!(IrType::Bool.to_string(), "bool");
1615        assert_eq!(IrType::Int.to_string(), "i64");
1616        assert_eq!(IrType::Nat.to_string(), "nat");
1617    }
1618
1619    #[test]
1620    fn test_ir_literal_display() {
1621        assert_eq!(IrLit::Unit.to_string(), "()");
1622        assert_eq!(IrLit::Bool(true).to_string(), "true");
1623        assert_eq!(IrLit::Bool(false).to_string(), "false");
1624        assert_eq!(IrLit::Nat(42).to_string(), "42");
1625        assert_eq!(IrLit::Int(-42).to_string(), "-42");
1626    }
1627
1628    #[test]
1629    fn test_ir_var_expression() {
1630        let expr = IrExpr::Var("x".to_string());
1631        match expr {
1632            IrExpr::Var(name) => assert_eq!(name, "x"),
1633            _ => panic!("Expected Var"),
1634        }
1635    }
1636
1637    #[test]
1638    fn test_ir_lit_expression() {
1639        let expr = IrExpr::Lit(IrLit::Int(42));
1640        match expr {
1641            IrExpr::Lit(IrLit::Int(n)) => assert_eq!(n, 42),
1642            _ => panic!("Expected Lit"),
1643        }
1644    }
1645
1646    #[test]
1647    fn test_ir_app_expression() {
1648        let func = Box::new(IrExpr::Var("f".to_string()));
1649        let arg = IrExpr::Lit(IrLit::Int(1));
1650        let expr = IrExpr::App {
1651            func,
1652            args: vec![arg],
1653        };
1654        match expr {
1655            IrExpr::App { args, .. } => assert_eq!(args.len(), 1),
1656            _ => panic!("Expected App"),
1657        }
1658    }
1659
1660    #[test]
1661    fn test_ir_let_expression() {
1662        let expr = IrExpr::Let {
1663            name: "x".to_string(),
1664            ty: IrType::Int,
1665            value: Box::new(IrExpr::Lit(IrLit::Int(5))),
1666            body: Box::new(IrExpr::Var("x".to_string())),
1667        };
1668        match expr {
1669            IrExpr::Let { name, .. } => assert_eq!(name, "x"),
1670            _ => panic!("Expected Let"),
1671        }
1672    }
1673
1674    #[test]
1675    fn test_ir_lambda_expression() {
1676        let expr = IrExpr::Lambda {
1677            params: vec![("x".to_string(), IrType::Int)],
1678            body: Box::new(IrExpr::Var("x".to_string())),
1679            captured: vec![],
1680        };
1681        match expr {
1682            IrExpr::Lambda { params, .. } => assert_eq!(params.len(), 1),
1683            _ => panic!("Expected Lambda"),
1684        }
1685    }
1686
1687    #[test]
1688    fn test_ir_if_expression() {
1689        let expr = IrExpr::If {
1690            cond: Box::new(IrExpr::Lit(IrLit::Bool(true))),
1691            then_branch: Box::new(IrExpr::Lit(IrLit::Int(1))),
1692            else_branch: Box::new(IrExpr::Lit(IrLit::Int(0))),
1693        };
1694        match expr {
1695            IrExpr::If { .. } => {}
1696            _ => panic!("Expected If"),
1697        }
1698    }
1699
1700    #[test]
1701    fn test_ir_match_expression() {
1702        let arms = vec![IrMatchArm {
1703            pattern: IrPattern::Literal("true".to_string()),
1704            body: Box::new(IrExpr::Lit(IrLit::Int(1))),
1705        }];
1706        let expr = IrExpr::Match {
1707            scrutinee: Box::new(IrExpr::Lit(IrLit::Bool(true))),
1708            arms,
1709        };
1710        match expr {
1711            IrExpr::Match { arms, .. } => assert_eq!(arms.len(), 1),
1712            _ => panic!("Expected Match"),
1713        }
1714    }
1715
1716    #[test]
1717    fn test_ir_struct_expression() {
1718        let expr = IrExpr::Struct {
1719            name: "Point".to_string(),
1720            fields: vec![("x".to_string(), IrExpr::Lit(IrLit::Int(1)))],
1721        };
1722        match expr {
1723            IrExpr::Struct { name, .. } => assert_eq!(name, "Point"),
1724            _ => panic!("Expected Struct"),
1725        }
1726    }
1727
1728    #[test]
1729    fn test_ir_field_expression() {
1730        let expr = IrExpr::Field {
1731            object: Box::new(IrExpr::Var("point".to_string())),
1732            field: "x".to_string(),
1733        };
1734        match expr {
1735            IrExpr::Field { field, .. } => assert_eq!(field, "x"),
1736            _ => panic!("Expected Field"),
1737        }
1738    }
1739
1740    #[test]
1741    fn test_ir_alloc_expression() {
1742        let expr = IrExpr::Alloc(Box::new(IrExpr::Lit(IrLit::Int(42))));
1743        match expr {
1744            IrExpr::Alloc(_) => {}
1745            _ => panic!("Expected Alloc"),
1746        }
1747    }
1748
1749    #[test]
1750    fn test_ir_deref_expression() {
1751        let expr = IrExpr::Deref(Box::new(IrExpr::Var("ptr".to_string())));
1752        match expr {
1753            IrExpr::Deref(_) => {}
1754            _ => panic!("Expected Deref"),
1755        }
1756    }
1757
1758    #[test]
1759    fn test_ir_seq_expression() {
1760        let expr = IrExpr::Seq(vec![IrExpr::Lit(IrLit::Int(1)), IrExpr::Lit(IrLit::Int(2))]);
1761        match expr {
1762            IrExpr::Seq(exprs) => assert_eq!(exprs.len(), 2),
1763            _ => panic!("Expected Seq"),
1764        }
1765    }
1766
1767    #[test]
1768    fn test_codegen_config_default() {
1769        let config = CodegenConfig::default();
1770        assert_eq!(config.target, CodegenTarget::Rust);
1771        assert!(config.optimize);
1772        assert!(!config.debug_info);
1773        assert!(config.emit_comments);
1774        assert_eq!(config.inline_threshold, 50);
1775    }
1776
1777    #[test]
1778    fn test_codegen_target_display() {
1779        assert_eq!(CodegenTarget::Rust.to_string(), "Rust");
1780        assert_eq!(CodegenTarget::C.to_string(), "C");
1781        assert_eq!(CodegenTarget::LlvmIr.to_string(), "LLVM IR");
1782        assert_eq!(CodegenTarget::Interpreter.to_string(), "Interpreter");
1783    }
1784
1785    #[test]
1786    fn test_codegen_error_display() {
1787        let err = CodegenError::UnboundVariable("x".to_string());
1788        assert_eq!(err.to_string(), "Unbound variable: x");
1789
1790        let err = CodegenError::UnsupportedExpression("foo".to_string());
1791        assert_eq!(err.to_string(), "Unsupported expression: foo");
1792
1793        let err = CodegenError::TypeMismatch {
1794            expected: "Int".to_string(),
1795            found: "Bool".to_string(),
1796        };
1797        assert_eq!(err.to_string(), "Type mismatch: expected Int, found Bool");
1798    }
1799
1800    #[test]
1801    fn test_symbol_manager_fresh_names() {
1802        let mut mgr = SymbolManager::new();
1803        let name1 = mgr.fresh_name("var");
1804        let name2 = mgr.fresh_name("var");
1805        assert_ne!(name1, name2);
1806        assert!(name1.starts_with("var_"));
1807        assert!(name2.starts_with("var_"));
1808    }
1809
1810    #[test]
1811    fn test_symbol_manager_scopes() {
1812        let mut mgr = SymbolManager::new();
1813        mgr.push_scope();
1814        mgr.bind("x".to_string());
1815        assert!(mgr.is_bound("x"));
1816        mgr.pop_scope();
1817        assert!(!mgr.is_bound("x"));
1818    }
1819
1820    #[test]
1821    fn test_expr_to_ir_new() {
1822        let compiler = ExprToIr::new();
1823        assert_eq!(compiler.closure_vars.len(), 0);
1824    }
1825
1826    #[test]
1827    fn test_rust_emitter_indent() {
1828        let mut emitter = RustEmitter::new();
1829        assert_eq!(emitter.indent_level, 0);
1830        emitter.indent();
1831        assert_eq!(emitter.indent_level, 1);
1832        emitter.dedent();
1833        assert_eq!(emitter.indent_level, 0);
1834    }
1835
1836    #[test]
1837    fn test_rust_emitter_emit_simple() {
1838        let mut emitter = RustEmitter::new();
1839        emitter.emit("let x = 5;");
1840        let output = emitter.result();
1841        assert!(output.contains("let x = 5;"));
1842    }
1843
1844    #[test]
1845    fn test_ir_to_rust_emit_var() -> CodegenResult<()> {
1846        let config = CodegenConfig::default();
1847        let gen = IrToRust::new(config);
1848        let expr = IrExpr::Var("x".to_string());
1849        let output = gen.emit(&expr)?;
1850        assert!(output.contains("x"));
1851        Ok(())
1852    }
1853
1854    #[test]
1855    fn test_ir_to_rust_emit_literal() -> CodegenResult<()> {
1856        let config = CodegenConfig::default();
1857        let gen = IrToRust::new(config);
1858        let expr = IrExpr::Lit(IrLit::Int(42));
1859        let output = gen.emit(&expr)?;
1860        assert!(output.contains("42"));
1861        Ok(())
1862    }
1863
1864    #[test]
1865    fn test_ir_to_rust_emit_if() -> CodegenResult<()> {
1866        let config = CodegenConfig::default();
1867        let gen = IrToRust::new(config);
1868        let expr = IrExpr::If {
1869            cond: Box::new(IrExpr::Lit(IrLit::Bool(true))),
1870            then_branch: Box::new(IrExpr::Lit(IrLit::Int(1))),
1871            else_branch: Box::new(IrExpr::Lit(IrLit::Int(0))),
1872        };
1873        let output = gen.emit(&expr)?;
1874        assert!(output.contains("if"));
1875        assert!(output.contains("else"));
1876        Ok(())
1877    }
1878
1879    #[test]
1880    fn test_ir_to_rust_emit_struct() -> CodegenResult<()> {
1881        let config = CodegenConfig::default();
1882        let gen = IrToRust::new(config);
1883        let fields = vec![("x".to_string(), IrType::Int)];
1884        let output = gen.emit_struct("Point", &fields)?;
1885        assert!(output.contains("struct Point"));
1886        assert!(output.contains("x: i64"));
1887        Ok(())
1888    }
1889
1890    #[test]
1891    fn test_ir_to_rust_emit_function() -> CodegenResult<()> {
1892        let config = CodegenConfig::default();
1893        let gen = IrToRust::new(config);
1894        let params = vec![("x".to_string(), IrType::Int)];
1895        let body = IrExpr::Var("x".to_string());
1896        let output = gen.emit_function("identity", &params, &IrType::Int, &body)?;
1897        assert!(output.contains("fn identity"));
1898        assert!(output.contains("x: i64"));
1899        Ok(())
1900    }
1901
1902    #[test]
1903    fn test_optimizer_constant_fold_if_true() -> CodegenResult<()> {
1904        let config = CodegenConfig::default();
1905        let opt = Optimizer::new(config);
1906        let expr = IrExpr::If {
1907            cond: Box::new(IrExpr::Lit(IrLit::Bool(true))),
1908            then_branch: Box::new(IrExpr::Lit(IrLit::Int(1))),
1909            else_branch: Box::new(IrExpr::Lit(IrLit::Int(0))),
1910        };
1911        let result = opt.constant_fold(&expr)?;
1912        match result {
1913            IrExpr::Lit(IrLit::Int(n)) => assert_eq!(n, 1),
1914            _ => panic!("Expected constant 1"),
1915        }
1916        Ok(())
1917    }
1918
1919    #[test]
1920    fn test_optimizer_constant_fold_if_false() -> CodegenResult<()> {
1921        let config = CodegenConfig::default();
1922        let opt = Optimizer::new(config);
1923        let expr = IrExpr::If {
1924            cond: Box::new(IrExpr::Lit(IrLit::Bool(false))),
1925            then_branch: Box::new(IrExpr::Lit(IrLit::Int(1))),
1926            else_branch: Box::new(IrExpr::Lit(IrLit::Int(0))),
1927        };
1928        let result = opt.constant_fold(&expr)?;
1929        match result {
1930            IrExpr::Lit(IrLit::Int(n)) => assert_eq!(n, 0),
1931            _ => panic!("Expected constant 0"),
1932        }
1933        Ok(())
1934    }
1935
1936    #[test]
1937    fn test_optimizer_dead_code_elimination() -> CodegenResult<()> {
1938        let config = CodegenConfig::default();
1939        let opt = Optimizer::new(config);
1940        let expr = IrExpr::Let {
1941            name: "unused".to_string(),
1942            ty: IrType::Int,
1943            value: Box::new(IrExpr::Lit(IrLit::Int(42))),
1944            body: Box::new(IrExpr::Lit(IrLit::Int(0))),
1945        };
1946        let result = opt.dead_code_eliminate(&expr)?;
1947        match result {
1948            IrExpr::Lit(IrLit::Int(n)) => assert_eq!(n, 0),
1949            _ => panic!("Expected dead code removed"),
1950        }
1951        Ok(())
1952    }
1953
1954    #[test]
1955    fn test_ir_type_function() {
1956        let ty = IrType::Function {
1957            params: vec![IrType::Int, IrType::Bool],
1958            ret: Box::new(IrType::String),
1959        };
1960        let output = ty.to_string();
1961        assert!(output.contains("fn("));
1962        assert!(output.contains("i64"));
1963        assert!(output.contains("bool"));
1964    }
1965
1966    #[test]
1967    fn test_ir_type_struct() {
1968        let ty = IrType::Struct {
1969            name: "Point".to_string(),
1970            fields: vec![
1971                ("x".to_string(), IrType::Int),
1972                ("y".to_string(), IrType::Int),
1973            ],
1974        };
1975        let output = ty.to_string();
1976        assert!(output.contains("struct Point"));
1977        assert!(output.contains("x: i64"));
1978        assert!(output.contains("y: i64"));
1979    }
1980
1981    #[test]
1982    fn test_ir_type_array() {
1983        let ty = IrType::Array {
1984            elem: Box::new(IrType::Int),
1985            len: 10,
1986        };
1987        let output = ty.to_string();
1988        assert!(output.contains("[i64; 10]"));
1989    }
1990
1991    #[test]
1992    fn test_ir_pattern_wildcard() {
1993        let pattern = IrPattern::Wildcard;
1994        match pattern {
1995            IrPattern::Wildcard => {}
1996            _ => panic!("Expected Wildcard"),
1997        }
1998    }
1999
2000    #[test]
2001    fn test_ir_pattern_literal() {
2002        let pattern = IrPattern::Literal("true".to_string());
2003        match pattern {
2004            IrPattern::Literal(lit) => assert_eq!(lit, "true"),
2005            _ => panic!("Expected Literal"),
2006        }
2007    }
2008
2009    #[test]
2010    fn test_ir_pattern_constructor() {
2011        let pattern = IrPattern::Constructor {
2012            name: "Some".to_string(),
2013            args: vec!["x".to_string()],
2014        };
2015        match pattern {
2016            IrPattern::Constructor { name, args } => {
2017                assert_eq!(name, "Some");
2018                assert_eq!(args.len(), 1);
2019            }
2020            _ => panic!("Expected Constructor"),
2021        }
2022    }
2023
2024    #[test]
2025    fn test_ir_pattern_tuple() {
2026        let pattern = IrPattern::Tuple(vec!["x".to_string(), "y".to_string()]);
2027        match pattern {
2028            IrPattern::Tuple(vars) => assert_eq!(vars.len(), 2),
2029            _ => panic!("Expected Tuple"),
2030        }
2031    }
2032
2033    #[test]
2034    fn test_codegen_pipeline_new() {
2035        let config = CodegenConfig::default();
2036        let _pipeline = CodegenPipeline::new(config);
2037    }
2038
2039    #[test]
2040    fn test_ir_to_c_emit_var() -> CodegenResult<()> {
2041        let config = CodegenConfig::default();
2042        let gen = IrToC::new(config);
2043        let expr = IrExpr::Var("x".to_string());
2044        let output = gen.emit(&expr)?;
2045        assert!(output.contains("x"));
2046        Ok(())
2047    }
2048
2049    #[test]
2050    fn test_ir_to_c_emit_literal() -> CodegenResult<()> {
2051        let config = CodegenConfig::default();
2052        let gen = IrToC::new(config);
2053        let expr = IrExpr::Lit(IrLit::Int(42));
2054        let output = gen.emit(&expr)?;
2055        assert!(output.contains("42"));
2056        Ok(())
2057    }
2058
2059    #[test]
2060    fn test_ir_to_c_emit_app() -> CodegenResult<()> {
2061        let config = CodegenConfig::default();
2062        let gen = IrToC::new(config);
2063        let expr = IrExpr::App {
2064            func: Box::new(IrExpr::Var("f".to_string())),
2065            args: vec![IrExpr::Lit(IrLit::Int(1))],
2066        };
2067        let output = gen.emit(&expr)?;
2068        assert!(output.contains("f("));
2069        assert!(output.contains("1"));
2070        Ok(())
2071    }
2072
2073    #[test]
2074    fn test_ir_to_c_emit_field() -> CodegenResult<()> {
2075        let config = CodegenConfig::default();
2076        let gen = IrToC::new(config);
2077        let expr = IrExpr::Field {
2078            object: Box::new(IrExpr::Var("point".to_string())),
2079            field: "x".to_string(),
2080        };
2081        let output = gen.emit(&expr)?;
2082        assert!(output.contains("point"));
2083        assert!(output.contains("->x"));
2084        Ok(())
2085    }
2086
2087    #[test]
2088    fn test_ir_to_c_unsupported_let() -> CodegenResult<()> {
2089        let config = CodegenConfig::default();
2090        let gen = IrToC::new(config);
2091        let expr = IrExpr::Let {
2092            name: "x".to_string(),
2093            ty: IrType::Int,
2094            value: Box::new(IrExpr::Lit(IrLit::Int(5))),
2095            body: Box::new(IrExpr::Var("x".to_string())),
2096        };
2097        let result = gen.emit(&expr);
2098        assert!(result.is_err());
2099        Ok(())
2100    }
2101
2102    #[test]
2103    fn test_ir_match_arm() {
2104        let arm = IrMatchArm {
2105            pattern: IrPattern::Literal("true".to_string()),
2106            body: Box::new(IrExpr::Lit(IrLit::Int(1))),
2107        };
2108        assert_eq!(arm.pattern, IrPattern::Literal("true".to_string()));
2109    }
2110
2111    #[test]
2112    fn test_ir_to_rust_type_conversion() -> CodegenResult<()> {
2113        let config = CodegenConfig::default();
2114        let gen = IrToRust::new(config);
2115        assert_eq!(gen.emit_type(&IrType::Bool)?, "bool");
2116        assert_eq!(gen.emit_type(&IrType::Int)?, "i64");
2117        assert_eq!(gen.emit_type(&IrType::Nat)?, "u64");
2118        Ok(())
2119    }
2120
2121    #[test]
2122    fn test_optimizer_is_var_used() {
2123        let config = CodegenConfig::default();
2124        let opt = Optimizer::new(config);
2125        let expr = IrExpr::Var("x".to_string());
2126        assert!(opt.is_var_used("x", &expr));
2127        assert!(!opt.is_var_used("y", &expr));
2128    }
2129
2130    #[test]
2131    fn test_optimizer_inline() -> CodegenResult<()> {
2132        let config = CodegenConfig::default();
2133        let opt = Optimizer::new(config);
2134        let expr = IrExpr::Lit(IrLit::Int(42));
2135        let result = opt.inline(&expr)?;
2136        assert_eq!(result, expr);
2137        Ok(())
2138    }
2139
2140    #[test]
2141    fn test_optimizer_cse() -> CodegenResult<()> {
2142        let config = CodegenConfig::default();
2143        let opt = Optimizer::new(config);
2144        let expr = IrExpr::Lit(IrLit::Int(42));
2145        let result = opt.common_subexpr_eliminate(&expr)?;
2146        assert_eq!(result, expr);
2147        Ok(())
2148    }
2149
2150    #[test]
2151    fn test_closure_vars_tracking() {
2152        let compiler = ExprToIr::new();
2153        assert!(compiler.closure_vars.is_empty());
2154    }
2155
2156    #[test]
2157    fn test_ir_string_literal() {
2158        let lit = IrLit::String("hello".to_string());
2159        assert_eq!(lit.to_string(), "\"hello\"");
2160    }
2161
2162    #[test]
2163    fn test_ir_to_rust_emit_lambda() -> CodegenResult<()> {
2164        let config = CodegenConfig::default();
2165        let gen = IrToRust::new(config);
2166        let expr = IrExpr::Lambda {
2167            params: vec![("x".to_string(), IrType::Int)],
2168            body: Box::new(IrExpr::Var("x".to_string())),
2169            captured: vec![],
2170        };
2171        let output = gen.emit(&expr)?;
2172        assert!(output.contains("|"));
2173        Ok(())
2174    }
2175
2176    #[test]
2177    fn test_ir_to_rust_emit_match() -> CodegenResult<()> {
2178        let config = CodegenConfig::default();
2179        let gen = IrToRust::new(config);
2180        let arms = vec![IrMatchArm {
2181            pattern: IrPattern::Literal("true".to_string()),
2182            body: Box::new(IrExpr::Lit(IrLit::Int(1))),
2183        }];
2184        let output = gen.emit_match(&IrExpr::Lit(IrLit::Bool(true)), &arms)?;
2185        assert!(output.contains("match"));
2186        Ok(())
2187    }
2188
2189    #[test]
2190    fn test_ir_to_rust_emit_struct_expr() -> CodegenResult<()> {
2191        let config = CodegenConfig::default();
2192        let gen = IrToRust::new(config);
2193        let expr = IrExpr::Struct {
2194            name: "Point".to_string(),
2195            fields: vec![("x".to_string(), IrExpr::Lit(IrLit::Int(1)))],
2196        };
2197        let output = gen.emit(&expr)?;
2198        assert!(output.contains("Point"));
2199        assert!(output.contains("x"));
2200        Ok(())
2201    }
2202}
2203pub mod agda_backend;
2204pub mod beam_backend;
2205pub mod chapel_backend;
2206pub mod cil_backend;
2207pub mod coq_backend;
2208pub mod cranelift_backend;
2209pub mod csharp_backend;
2210pub mod cuda_backend;
2211pub mod dart_backend;
2212pub mod dhall_backend;
2213pub mod elixir_backend;
2214pub mod evm_backend;
2215pub mod fortran_backend;
2216pub mod fsharp_backend;
2217pub mod futhark_backend;
2218pub mod go_backend;
2219pub mod graphql_backend;
2220pub mod haskell_backend;
2221pub mod idris_backend;
2222pub mod java_backend;
2223pub mod julia_backend;
2224pub mod jvm_backend;
2225pub mod kotlin_backend;
2226pub mod lean4_backend;
2227pub mod llvm_ir_text;
2228pub mod lua_backend;
2229pub mod matlab_backend;
2230pub mod metal_backend;
2231pub mod mlir_backend;
2232pub mod nix_backend;
2233pub mod ocaml_backend;
2234pub mod opt_alias;
2235pub mod opt_beta_eta;
2236pub mod opt_cache;
2237pub mod opt_copy_prop;
2238pub mod opt_cse;
2239pub mod opt_ctfe;
2240pub mod opt_dead_branch;
2241pub mod opt_dse;
2242pub mod opt_escape;
2243pub mod opt_gvn;
2244pub mod opt_inline;
2245pub mod opt_licm;
2246pub mod opt_loop_unroll;
2247pub mod opt_mem2reg;
2248pub mod opt_parallel;
2249pub mod opt_partial_eval;
2250pub mod opt_regalloc;
2251pub mod opt_specialize_types;
2252pub mod opt_strength;
2253pub mod opt_tail_recursion;
2254pub mod opt_vectorize;
2255pub mod prolog_backend;
2256pub mod python_backend;
2257pub mod r_backend;
2258pub mod riscv_backend;
2259pub mod ruby_backend;
2260pub mod rust_target_backend;
2261pub mod scala_backend;
2262pub mod spirv_backend;
2263pub mod sql_backend;
2264pub mod swift_backend;
2265pub mod typescript_backend;
2266pub mod wasm_component_backend;
2267pub mod x86_64_backend;
2268
2269pub mod chisel_backend;
2270pub mod verilog_backend;
2271
2272pub mod bash_backend;
2273pub mod php_backend;
2274pub mod solidity_backend;
2275pub mod vyper_backend;
2276
2277// ============================================================
2278// Library - Extended Infrastructure
2279// ============================================================
2280
2281#[allow(dead_code)]
2282#[derive(Debug, Clone, PartialEq)]
2283pub enum LibPassPhase {
2284    Analysis,
2285    Transformation,
2286    Verification,
2287    Cleanup,
2288}
2289
2290impl LibPassPhase {
2291    #[allow(dead_code)]
2292    pub fn name(&self) -> &str {
2293        match self {
2294            LibPassPhase::Analysis => "analysis",
2295            LibPassPhase::Transformation => "transformation",
2296            LibPassPhase::Verification => "verification",
2297            LibPassPhase::Cleanup => "cleanup",
2298        }
2299    }
2300
2301    #[allow(dead_code)]
2302    pub fn is_modifying(&self) -> bool {
2303        matches!(self, LibPassPhase::Transformation | LibPassPhase::Cleanup)
2304    }
2305}
2306
2307#[allow(dead_code)]
2308#[derive(Debug, Clone)]
2309pub struct LibPassConfig {
2310    pub phase: LibPassPhase,
2311    pub enabled: bool,
2312    pub max_iterations: u32,
2313    pub debug_output: bool,
2314    pub pass_name: String,
2315}
2316
2317impl LibPassConfig {
2318    #[allow(dead_code)]
2319    pub fn new(name: impl Into<String>, phase: LibPassPhase) -> Self {
2320        LibPassConfig {
2321            phase,
2322            enabled: true,
2323            max_iterations: 10,
2324            debug_output: false,
2325            pass_name: name.into(),
2326        }
2327    }
2328
2329    #[allow(dead_code)]
2330    pub fn disabled(mut self) -> Self {
2331        self.enabled = false;
2332        self
2333    }
2334
2335    #[allow(dead_code)]
2336    pub fn with_debug(mut self) -> Self {
2337        self.debug_output = true;
2338        self
2339    }
2340
2341    #[allow(dead_code)]
2342    pub fn max_iter(mut self, n: u32) -> Self {
2343        self.max_iterations = n;
2344        self
2345    }
2346}
2347
2348#[allow(dead_code)]
2349#[derive(Debug, Clone, Default)]
2350pub struct LibPassStats {
2351    pub total_runs: u32,
2352    pub successful_runs: u32,
2353    pub total_changes: u64,
2354    pub time_ms: u64,
2355    pub iterations_used: u32,
2356}
2357
2358impl LibPassStats {
2359    #[allow(dead_code)]
2360    pub fn new() -> Self {
2361        Self::default()
2362    }
2363
2364    #[allow(dead_code)]
2365    pub fn record_run(&mut self, changes: u64, time_ms: u64, iterations: u32) {
2366        self.total_runs += 1;
2367        self.successful_runs += 1;
2368        self.total_changes += changes;
2369        self.time_ms += time_ms;
2370        self.iterations_used = iterations;
2371    }
2372
2373    #[allow(dead_code)]
2374    pub fn average_changes_per_run(&self) -> f64 {
2375        if self.total_runs == 0 {
2376            return 0.0;
2377        }
2378        self.total_changes as f64 / self.total_runs as f64
2379    }
2380
2381    #[allow(dead_code)]
2382    pub fn success_rate(&self) -> f64 {
2383        if self.total_runs == 0 {
2384            return 0.0;
2385        }
2386        self.successful_runs as f64 / self.total_runs as f64
2387    }
2388
2389    #[allow(dead_code)]
2390    pub fn format_summary(&self) -> String {
2391        format!(
2392            "Runs: {}/{}, Changes: {}, Time: {}ms",
2393            self.successful_runs, self.total_runs, self.total_changes, self.time_ms
2394        )
2395    }
2396}
2397
2398#[allow(dead_code)]
2399pub struct LibPassRegistry {
2400    configs: Vec<LibPassConfig>,
2401    stats: std::collections::HashMap<String, LibPassStats>,
2402}
2403
2404impl LibPassRegistry {
2405    #[allow(dead_code)]
2406    pub fn new() -> Self {
2407        LibPassRegistry {
2408            configs: Vec::new(),
2409            stats: std::collections::HashMap::new(),
2410        }
2411    }
2412
2413    #[allow(dead_code)]
2414    pub fn register(&mut self, config: LibPassConfig) {
2415        self.stats
2416            .insert(config.pass_name.clone(), LibPassStats::new());
2417        self.configs.push(config);
2418    }
2419
2420    #[allow(dead_code)]
2421    pub fn enabled_passes(&self) -> Vec<&LibPassConfig> {
2422        self.configs.iter().filter(|c| c.enabled).collect()
2423    }
2424
2425    #[allow(dead_code)]
2426    pub fn get_stats(&self, name: &str) -> Option<&LibPassStats> {
2427        self.stats.get(name)
2428    }
2429
2430    #[allow(dead_code)]
2431    pub fn total_passes(&self) -> usize {
2432        self.configs.len()
2433    }
2434
2435    #[allow(dead_code)]
2436    pub fn enabled_count(&self) -> usize {
2437        self.enabled_passes().len()
2438    }
2439
2440    #[allow(dead_code)]
2441    pub fn update_stats(&mut self, name: &str, changes: u64, time_ms: u64, iter: u32) {
2442        if let Some(stats) = self.stats.get_mut(name) {
2443            stats.record_run(changes, time_ms, iter);
2444        }
2445    }
2446}
2447
2448#[allow(dead_code)]
2449#[derive(Debug, Clone)]
2450pub struct LibAnalysisCache {
2451    entries: std::collections::HashMap<String, LibCacheEntry>,
2452    max_size: usize,
2453    hits: u64,
2454    misses: u64,
2455}
2456
2457#[allow(dead_code)]
2458#[derive(Debug, Clone)]
2459pub struct LibCacheEntry {
2460    pub key: String,
2461    pub data: Vec<u8>,
2462    pub timestamp: u64,
2463    pub valid: bool,
2464}
2465
2466impl LibAnalysisCache {
2467    #[allow(dead_code)]
2468    pub fn new(max_size: usize) -> Self {
2469        LibAnalysisCache {
2470            entries: std::collections::HashMap::new(),
2471            max_size,
2472            hits: 0,
2473            misses: 0,
2474        }
2475    }
2476
2477    #[allow(dead_code)]
2478    pub fn get(&mut self, key: &str) -> Option<&LibCacheEntry> {
2479        if self.entries.contains_key(key) {
2480            self.hits += 1;
2481            self.entries.get(key)
2482        } else {
2483            self.misses += 1;
2484            None
2485        }
2486    }
2487
2488    #[allow(dead_code)]
2489    pub fn insert(&mut self, key: String, data: Vec<u8>) {
2490        if self.entries.len() >= self.max_size {
2491            // Evict oldest (simplified)
2492            if let Some(oldest) = self.entries.keys().next().cloned() {
2493                self.entries.remove(&oldest);
2494            }
2495        }
2496        self.entries.insert(
2497            key.clone(),
2498            LibCacheEntry {
2499                key,
2500                data,
2501                timestamp: 0,
2502                valid: true,
2503            },
2504        );
2505    }
2506
2507    #[allow(dead_code)]
2508    pub fn invalidate(&mut self, key: &str) {
2509        if let Some(entry) = self.entries.get_mut(key) {
2510            entry.valid = false;
2511        }
2512    }
2513
2514    #[allow(dead_code)]
2515    pub fn clear(&mut self) {
2516        self.entries.clear();
2517    }
2518
2519    #[allow(dead_code)]
2520    pub fn hit_rate(&self) -> f64 {
2521        let total = self.hits + self.misses;
2522        if total == 0 {
2523            return 0.0;
2524        }
2525        self.hits as f64 / total as f64
2526    }
2527
2528    #[allow(dead_code)]
2529    pub fn size(&self) -> usize {
2530        self.entries.len()
2531    }
2532}
2533
2534#[allow(dead_code)]
2535#[derive(Debug, Clone)]
2536pub struct LibWorklist {
2537    items: std::collections::VecDeque<u32>,
2538    in_worklist: std::collections::HashSet<u32>,
2539}
2540
2541impl LibWorklist {
2542    #[allow(dead_code)]
2543    pub fn new() -> Self {
2544        LibWorklist {
2545            items: std::collections::VecDeque::new(),
2546            in_worklist: std::collections::HashSet::new(),
2547        }
2548    }
2549
2550    #[allow(dead_code)]
2551    pub fn push(&mut self, item: u32) -> bool {
2552        if self.in_worklist.insert(item) {
2553            self.items.push_back(item);
2554            true
2555        } else {
2556            false
2557        }
2558    }
2559
2560    #[allow(dead_code)]
2561    pub fn pop(&mut self) -> Option<u32> {
2562        let item = self.items.pop_front()?;
2563        self.in_worklist.remove(&item);
2564        Some(item)
2565    }
2566
2567    #[allow(dead_code)]
2568    pub fn is_empty(&self) -> bool {
2569        self.items.is_empty()
2570    }
2571
2572    #[allow(dead_code)]
2573    pub fn len(&self) -> usize {
2574        self.items.len()
2575    }
2576
2577    #[allow(dead_code)]
2578    pub fn contains(&self, item: u32) -> bool {
2579        self.in_worklist.contains(&item)
2580    }
2581}
2582
2583#[allow(dead_code)]
2584#[derive(Debug, Clone)]
2585pub struct LibDominatorTree {
2586    pub idom: Vec<Option<u32>>,
2587    pub dom_children: Vec<Vec<u32>>,
2588    pub dom_depth: Vec<u32>,
2589}
2590
2591impl LibDominatorTree {
2592    #[allow(dead_code)]
2593    pub fn new(size: usize) -> Self {
2594        LibDominatorTree {
2595            idom: vec![None; size],
2596            dom_children: vec![Vec::new(); size],
2597            dom_depth: vec![0; size],
2598        }
2599    }
2600
2601    #[allow(dead_code)]
2602    pub fn set_idom(&mut self, node: usize, idom: u32) {
2603        self.idom[node] = Some(idom);
2604    }
2605
2606    #[allow(dead_code)]
2607    pub fn dominates(&self, a: usize, b: usize) -> bool {
2608        if a == b {
2609            return true;
2610        }
2611        let mut cur = b;
2612        loop {
2613            match self.idom[cur] {
2614                Some(parent) if parent as usize == a => return true,
2615                Some(parent) if parent as usize == cur => return false,
2616                Some(parent) => cur = parent as usize,
2617                None => return false,
2618            }
2619        }
2620    }
2621
2622    #[allow(dead_code)]
2623    pub fn depth(&self, node: usize) -> u32 {
2624        self.dom_depth.get(node).copied().unwrap_or(0)
2625    }
2626}
2627
2628#[allow(dead_code)]
2629#[derive(Debug, Clone)]
2630pub struct LibLivenessInfo {
2631    pub live_in: Vec<std::collections::HashSet<u32>>,
2632    pub live_out: Vec<std::collections::HashSet<u32>>,
2633    pub defs: Vec<std::collections::HashSet<u32>>,
2634    pub uses: Vec<std::collections::HashSet<u32>>,
2635}
2636
2637impl LibLivenessInfo {
2638    #[allow(dead_code)]
2639    pub fn new(block_count: usize) -> Self {
2640        LibLivenessInfo {
2641            live_in: vec![std::collections::HashSet::new(); block_count],
2642            live_out: vec![std::collections::HashSet::new(); block_count],
2643            defs: vec![std::collections::HashSet::new(); block_count],
2644            uses: vec![std::collections::HashSet::new(); block_count],
2645        }
2646    }
2647
2648    #[allow(dead_code)]
2649    pub fn add_def(&mut self, block: usize, var: u32) {
2650        if block < self.defs.len() {
2651            self.defs[block].insert(var);
2652        }
2653    }
2654
2655    #[allow(dead_code)]
2656    pub fn add_use(&mut self, block: usize, var: u32) {
2657        if block < self.uses.len() {
2658            self.uses[block].insert(var);
2659        }
2660    }
2661
2662    #[allow(dead_code)]
2663    pub fn is_live_in(&self, block: usize, var: u32) -> bool {
2664        self.live_in
2665            .get(block)
2666            .map(|s| s.contains(&var))
2667            .unwrap_or(false)
2668    }
2669
2670    #[allow(dead_code)]
2671    pub fn is_live_out(&self, block: usize, var: u32) -> bool {
2672        self.live_out
2673            .get(block)
2674            .map(|s| s.contains(&var))
2675            .unwrap_or(false)
2676    }
2677}
2678
2679#[allow(dead_code)]
2680pub struct LibConstantFoldingHelper;
2681
2682impl LibConstantFoldingHelper {
2683    #[allow(dead_code)]
2684    pub fn fold_add_i64(a: i64, b: i64) -> Option<i64> {
2685        a.checked_add(b)
2686    }
2687
2688    #[allow(dead_code)]
2689    pub fn fold_sub_i64(a: i64, b: i64) -> Option<i64> {
2690        a.checked_sub(b)
2691    }
2692
2693    #[allow(dead_code)]
2694    pub fn fold_mul_i64(a: i64, b: i64) -> Option<i64> {
2695        a.checked_mul(b)
2696    }
2697
2698    #[allow(dead_code)]
2699    pub fn fold_div_i64(a: i64, b: i64) -> Option<i64> {
2700        if b == 0 {
2701            None
2702        } else {
2703            a.checked_div(b)
2704        }
2705    }
2706
2707    #[allow(dead_code)]
2708    pub fn fold_add_f64(a: f64, b: f64) -> f64 {
2709        a + b
2710    }
2711
2712    #[allow(dead_code)]
2713    pub fn fold_mul_f64(a: f64, b: f64) -> f64 {
2714        a * b
2715    }
2716
2717    #[allow(dead_code)]
2718    pub fn fold_neg_i64(a: i64) -> Option<i64> {
2719        a.checked_neg()
2720    }
2721
2722    #[allow(dead_code)]
2723    pub fn fold_not_bool(a: bool) -> bool {
2724        !a
2725    }
2726
2727    #[allow(dead_code)]
2728    pub fn fold_and_bool(a: bool, b: bool) -> bool {
2729        a && b
2730    }
2731
2732    #[allow(dead_code)]
2733    pub fn fold_or_bool(a: bool, b: bool) -> bool {
2734        a || b
2735    }
2736
2737    #[allow(dead_code)]
2738    pub fn fold_shl_i64(a: i64, b: u32) -> Option<i64> {
2739        a.checked_shl(b)
2740    }
2741
2742    #[allow(dead_code)]
2743    pub fn fold_shr_i64(a: i64, b: u32) -> Option<i64> {
2744        a.checked_shr(b)
2745    }
2746
2747    #[allow(dead_code)]
2748    pub fn fold_rem_i64(a: i64, b: i64) -> Option<i64> {
2749        if b == 0 {
2750            None
2751        } else {
2752            Some(a % b)
2753        }
2754    }
2755
2756    #[allow(dead_code)]
2757    pub fn fold_bitand_i64(a: i64, b: i64) -> i64 {
2758        a & b
2759    }
2760
2761    #[allow(dead_code)]
2762    pub fn fold_bitor_i64(a: i64, b: i64) -> i64 {
2763        a | b
2764    }
2765
2766    #[allow(dead_code)]
2767    pub fn fold_bitxor_i64(a: i64, b: i64) -> i64 {
2768        a ^ b
2769    }
2770
2771    #[allow(dead_code)]
2772    pub fn fold_bitnot_i64(a: i64) -> i64 {
2773        !a
2774    }
2775}
2776
2777#[allow(dead_code)]
2778#[derive(Debug, Clone)]
2779pub struct LibDepGraph {
2780    nodes: Vec<u32>,
2781    edges: Vec<(u32, u32)>, // (dependency, dependent)
2782}
2783
2784impl LibDepGraph {
2785    #[allow(dead_code)]
2786    pub fn new() -> Self {
2787        LibDepGraph {
2788            nodes: Vec::new(),
2789            edges: Vec::new(),
2790        }
2791    }
2792
2793    #[allow(dead_code)]
2794    pub fn add_node(&mut self, id: u32) {
2795        if !self.nodes.contains(&id) {
2796            self.nodes.push(id);
2797        }
2798    }
2799
2800    #[allow(dead_code)]
2801    pub fn add_dep(&mut self, dep: u32, dependent: u32) {
2802        self.add_node(dep);
2803        self.add_node(dependent);
2804        self.edges.push((dep, dependent));
2805    }
2806
2807    #[allow(dead_code)]
2808    pub fn dependents_of(&self, node: u32) -> Vec<u32> {
2809        self.edges
2810            .iter()
2811            .filter(|(d, _)| *d == node)
2812            .map(|(_, dep)| *dep)
2813            .collect()
2814    }
2815
2816    #[allow(dead_code)]
2817    pub fn dependencies_of(&self, node: u32) -> Vec<u32> {
2818        self.edges
2819            .iter()
2820            .filter(|(_, dep)| *dep == node)
2821            .map(|(d, _)| *d)
2822            .collect()
2823    }
2824
2825    #[allow(dead_code)]
2826    pub fn topological_sort(&self) -> Vec<u32> {
2827        let mut in_degree: std::collections::HashMap<u32, u32> = std::collections::HashMap::new();
2828        for &n in &self.nodes {
2829            in_degree.insert(n, 0);
2830        }
2831        for (_, dep) in &self.edges {
2832            *in_degree.entry(*dep).or_insert(0) += 1;
2833        }
2834        let mut queue: std::collections::VecDeque<u32> = self
2835            .nodes
2836            .iter()
2837            .filter(|&&n| in_degree[&n] == 0)
2838            .copied()
2839            .collect();
2840        let mut result = Vec::new();
2841        while let Some(node) = queue.pop_front() {
2842            result.push(node);
2843            for dep in self.dependents_of(node) {
2844                let cnt = in_degree.entry(dep).or_insert(0);
2845                *cnt = cnt.saturating_sub(1);
2846                if *cnt == 0 {
2847                    queue.push_back(dep);
2848                }
2849            }
2850        }
2851        result
2852    }
2853
2854    #[allow(dead_code)]
2855    pub fn has_cycle(&self) -> bool {
2856        self.topological_sort().len() < self.nodes.len()
2857    }
2858}
2859
2860#[cfg(test)]
2861mod Lib_infra_tests {
2862    use super::*;
2863
2864    #[test]
2865    fn test_pass_config() {
2866        let config = LibPassConfig::new("test_pass", LibPassPhase::Transformation);
2867        assert!(config.enabled);
2868        assert!(config.phase.is_modifying());
2869        assert_eq!(config.phase.name(), "transformation");
2870    }
2871
2872    #[test]
2873    fn test_pass_stats() {
2874        let mut stats = LibPassStats::new();
2875        stats.record_run(10, 100, 3);
2876        stats.record_run(20, 200, 5);
2877        assert_eq!(stats.total_runs, 2);
2878        assert!((stats.average_changes_per_run() - 15.0).abs() < 0.01);
2879        assert!((stats.success_rate() - 1.0).abs() < 0.01);
2880        let s = stats.format_summary();
2881        assert!(s.contains("Runs: 2/2"));
2882    }
2883
2884    #[test]
2885    fn test_pass_registry() {
2886        let mut reg = LibPassRegistry::new();
2887        reg.register(LibPassConfig::new("pass_a", LibPassPhase::Analysis));
2888        reg.register(LibPassConfig::new("pass_b", LibPassPhase::Transformation).disabled());
2889        assert_eq!(reg.total_passes(), 2);
2890        assert_eq!(reg.enabled_count(), 1);
2891        reg.update_stats("pass_a", 5, 50, 2);
2892        let stats = reg.get_stats("pass_a").expect("stats should exist");
2893        assert_eq!(stats.total_changes, 5);
2894    }
2895
2896    #[test]
2897    fn test_analysis_cache() {
2898        let mut cache = LibAnalysisCache::new(10);
2899        cache.insert("key1".to_string(), vec![1, 2, 3]);
2900        assert!(cache.get("key1").is_some());
2901        assert!(cache.get("key2").is_none());
2902        assert!((cache.hit_rate() - 0.5).abs() < 0.01);
2903        cache.invalidate("key1");
2904        assert!(!cache.entries["key1"].valid);
2905        assert_eq!(cache.size(), 1);
2906    }
2907
2908    #[test]
2909    fn test_worklist() {
2910        let mut wl = LibWorklist::new();
2911        assert!(wl.push(1));
2912        assert!(wl.push(2));
2913        assert!(!wl.push(1)); // already in worklist
2914        assert_eq!(wl.len(), 2);
2915        assert_eq!(wl.pop(), Some(1));
2916        assert!(!wl.contains(1));
2917        assert!(wl.contains(2));
2918    }
2919
2920    #[test]
2921    fn test_dominator_tree() {
2922        let mut dt = LibDominatorTree::new(5);
2923        dt.set_idom(1, 0);
2924        dt.set_idom(2, 0);
2925        dt.set_idom(3, 1);
2926        assert!(dt.dominates(0, 3));
2927        assert!(dt.dominates(1, 3));
2928        assert!(!dt.dominates(2, 3));
2929        assert!(dt.dominates(3, 3));
2930    }
2931
2932    #[test]
2933    fn test_liveness() {
2934        let mut liveness = LibLivenessInfo::new(3);
2935        liveness.add_def(0, 1);
2936        liveness.add_use(1, 1);
2937        assert!(liveness.defs[0].contains(&1));
2938        assert!(liveness.uses[1].contains(&1));
2939    }
2940
2941    #[test]
2942    fn test_constant_folding() {
2943        assert_eq!(LibConstantFoldingHelper::fold_add_i64(3, 4), Some(7));
2944        assert_eq!(LibConstantFoldingHelper::fold_div_i64(10, 0), None);
2945        assert_eq!(LibConstantFoldingHelper::fold_div_i64(10, 2), Some(5));
2946        assert_eq!(
2947            LibConstantFoldingHelper::fold_bitand_i64(0b1100, 0b1010),
2948            0b1000
2949        );
2950        assert_eq!(LibConstantFoldingHelper::fold_bitnot_i64(0), -1);
2951    }
2952
2953    #[test]
2954    fn test_dep_graph() {
2955        let mut g = LibDepGraph::new();
2956        g.add_dep(1, 2);
2957        g.add_dep(2, 3);
2958        g.add_dep(1, 3);
2959        assert_eq!(g.dependencies_of(2), vec![1]);
2960        let topo = g.topological_sort();
2961        assert_eq!(topo.len(), 3);
2962        assert!(!g.has_cycle());
2963        // Check order: 1 before 2, 1 before 3, 2 before 3
2964        let pos: std::collections::HashMap<u32, usize> =
2965            topo.iter().enumerate().map(|(i, &n)| (n, i)).collect();
2966        assert!(pos[&1] < pos[&2]);
2967        assert!(pos[&1] < pos[&3]);
2968        assert!(pos[&2] < pos[&3]);
2969    }
2970}