espforge_lib/resolver/
ruchy_bridge.rs1use anyhow::{Result, anyhow};
2use ruchy::backend::Transpiler;
3use ruchy::frontend::Parser;
4use ruchy::frontend::ast::ExprKind;
5
6pub struct RuchyOutput {
7 pub setup: String,
8 pub loop_body: String,
9 pub variables: Vec<String>,
10}
11
12pub fn compile_ruchy_script(raw_source: &str) -> Result<RuchyOutput> {
13 let source = raw_source.replace("\r\n", "\n");
16
17 let mut parser = Parser::new(&source);
19 let ast = parser
20 .parse()
21 .map_err(|e| anyhow!("Failed to parse Ruchy code: {:?}", e))?;
22
23 let mut transpiler = Transpiler::new();
25
26 let mut setup_body = String::new();
27 let mut loop_body = String::new();
28 let mut variables = Vec::new();
29
30 if let ExprKind::Block(exprs) = ast.kind {
31 for expr in exprs {
32 match expr.kind {
33 ExprKind::Function { name, body, .. } => {
34 if let ExprKind::Block(ref stmts) = body.kind {
36 transpiler.analyze_mutability(stmts);
37 } else {
38 transpiler.analyze_mutability(&[body.as_ref().clone()]);
39 }
40
41 let token_stream = transpiler.transpile_expr(&body)?;
43 let raw_code = token_stream.to_string();
44
45 match name.as_str() {
47 "setup" => {
48 setup_body = format_rust_code(&raw_code, 1);
50 }
51 "forever" => {
52 loop_body = format_rust_code(&raw_code, 2);
54 }
55 _ => {}
56 }
57 }
58 _ => {
59 transpiler.analyze_mutability(std::slice::from_ref(&expr));
62 let token_stream = transpiler.transpile_expr(&expr)?;
63 let raw_code = token_stream.to_string();
64
65 let mut stmt = raw_code.trim().to_string();
66
67 if !stmt.ends_with(';') {
69 stmt.push(';');
70 }
71
72 if stmt.starts_with("let ") {
75 if !stmt.starts_with("let mut ") {
76 stmt = stmt.replace("let ", "let mut ");
77 }
78 } else {
79 stmt = format!("let mut {}", stmt);
81 }
82
83 variables.push(stmt);
84 }
85 }
86 }
87 }
88
89 Ok(RuchyOutput {
90 setup: setup_body,
91 loop_body,
92 variables,
93 })
94}
95
96fn format_rust_code(input: &str, indent_level: usize) -> String {
98 let indent = " ".repeat(indent_level);
99
100 let mut content = input.trim();
103 while content.starts_with('{') && content.ends_with('}') {
104 content = content[1..content.len() - 1].trim();
105 }
106
107 let mut cleaned = content.to_string();
109 cleaned = cleaned.replace(" . ", ".");
110 cleaned = cleaned.replace(" (", "(");
111 cleaned = cleaned.replace(" )", ")");
112 cleaned = cleaned.replace(" ;", ";");
113 cleaned = cleaned.replace(" !", "!");
114 cleaned = cleaned.replace(" :: ", "::");
115
116 let mut formatted = String::new();
118 let statements: Vec<&str> = cleaned
119 .split(';')
120 .map(|s| s.trim())
121 .filter(|s| !s.is_empty())
122 .collect();
123
124 for (i, stmt) in statements.iter().enumerate() {
125 if i == 0 {
126 formatted.push_str(&format!("{};", stmt));
128 } else {
129 formatted.push_str(&format!("\n{}{};", indent, stmt));
131 }
132 }
133
134 formatted
135}