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
53pub 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;
77use std::collections::{HashMap, HashSet, VecDeque};
85use std::fmt;
86
87use oxilean_kernel::expr::{Expr, Literal};
88
89#[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#[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#[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#[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#[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#[derive(Debug, Clone, PartialEq)]
234pub struct IrMatchArm {
235 pub pattern: IrPattern,
236 pub body: Box<IrExpr>,
237}
238
239#[derive(Debug, Clone, PartialEq)]
241pub enum IrExpr {
242 Var(String),
244
245 Lit(IrLit),
247
248 App {
250 func: Box<IrExpr>,
251 args: Vec<IrExpr>,
252 },
253
254 Let {
256 name: String,
257 ty: IrType,
258 value: Box<IrExpr>,
259 body: Box<IrExpr>,
260 },
261
262 Lambda {
264 params: Vec<(String, IrType)>,
265 body: Box<IrExpr>,
266 captured: Vec<String>,
267 },
268
269 If {
271 cond: Box<IrExpr>,
272 then_branch: Box<IrExpr>,
273 else_branch: Box<IrExpr>,
274 },
275
276 Match {
278 scrutinee: Box<IrExpr>,
279 arms: Vec<IrMatchArm>,
280 },
281
282 Struct {
284 name: String,
285 fields: Vec<(String, IrExpr)>,
286 },
287
288 Field { object: Box<IrExpr>, field: String },
290
291 Alloc(Box<IrExpr>),
293
294 Deref(Box<IrExpr>),
296
297 Seq(Vec<IrExpr>),
299}
300
301#[derive(Debug, Clone, PartialEq, Eq, Hash)]
309struct IrExprKey(String, Box<IrExprOwned>);
310
311#[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 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 fn is_trivial(&self) -> bool {
330 matches!(*self.1, IrExprOwned::Var(_) | IrExprOwned::Lit(_))
331 }
332
333 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
396impl IrExprKey {
398 fn as_ir_expr(&self) -> IrExpr {
403 IrExpr::Var(self.0.clone())
406 }
407}
408
409#[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
461struct 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
504pub 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 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 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 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 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
662struct 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
707pub struct IrToRust {
709 config: CodegenConfig,
710}
711
712impl IrToRust {
713 pub fn new(config: CodegenConfig) -> Self {
714 IrToRust { config }
715 }
716
717 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
924pub struct IrToC {
930 config: CodegenConfig,
931}
932
933impl IrToC {
934 pub fn new(config: CodegenConfig) -> Self {
935 IrToC { config }
936 }
937
938 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
990pub struct Optimizer {
996 config: CodegenConfig,
997}
998
999impl Optimizer {
1000 pub fn new(config: CodegenConfig) -> Self {
1001 Optimizer { config }
1002 }
1003
1004 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 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 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 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 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 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 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 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 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 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 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 fn common_subexpr_eliminate(&self, expr: &IrExpr) -> CodegenResult<IrExpr> {
1295 let mut counts: HashMap<IrExprKey, usize> = HashMap::new();
1297 self.count_subexprs(expr, &mut counts);
1298
1299 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 to_hoist.sort_by_key(|k| k.0.clone());
1307
1308 if to_hoist.is_empty() {
1309 return Ok(expr.clone());
1310 }
1311
1312 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 let rewritten = self.replace_subexprs(expr, &subst);
1321
1322 let mut result = rewritten;
1324 for key in to_hoist.iter().rev() {
1325 let var_name = subst[key].clone();
1326 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 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 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
1461pub 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 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 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 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 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#[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", ¶ms, &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#[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 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)>, }
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)); 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 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}