use super::super::NyashRunner; use nyash_rust::{parser::NyashParser, mir::{MirCompiler, MirInstruction}, box_trait::IntegerBox}; use nyash_rust::mir::passes::method_id_inject::inject_method_ids; use std::{fs, process}; impl NyashRunner { /// Execute LLVM mode (split) pub(crate) fn execute_llvm_mode(&self, filename: &str) { // Read the file let code = match fs::read_to_string(filename) { Ok(content) => content, Err(e) => { eprintln!("❌ Error reading file {}: {}", filename, e); process::exit(1); } }; // Parse to AST let ast = match NyashParser::parse_from_string(&code) { Ok(ast) => ast, Err(e) => { eprintln!("❌ Parse error: {}", e); process::exit(1); } }; // Compile to MIR let mut mir_compiler = MirCompiler::new(); let compile_result = match mir_compiler.compile(ast) { Ok(result) => result, Err(e) => { eprintln!("❌ MIR compilation error: {}", e); process::exit(1); } }; println!("📊 MIR Module compiled successfully!"); println!("📊 Functions: {}", compile_result.module.functions.len()); // Inject method_id for BoxCall/PluginInvoke where resolvable (by-id path) #[allow(unused_mut)] let mut module = compile_result.module.clone(); let injected = inject_method_ids(&mut module); if injected > 0 && std::env::var("NYASH_CLI_VERBOSE").ok().as_deref() == Some("1") { eprintln!("[LLVM] method_id injected: {} places", injected); } // If explicit object path is requested, emit object only if let Ok(out_path) = std::env::var("NYASH_LLVM_OBJ_OUT") { #[cfg(feature = "llvm")] { use nyash_rust::backend::llvm_compile_to_object; // Ensure parent directory exists for the object file if let Some(parent) = std::path::Path::new(&out_path).parent() { let _ = std::fs::create_dir_all(parent); } if std::env::var("NYASH_CLI_VERBOSE").ok().as_deref() == Some("1") { eprintln!("[Runner/LLVM] emitting object to {} (cwd={})", out_path, std::env::current_dir().map(|p| p.display().to_string()).unwrap_or_default()); } if let Err(e) = llvm_compile_to_object(&module, &out_path) { eprintln!("❌ LLVM object emit error: {}", e); process::exit(1); } // Verify object presence and size (>0) match std::fs::metadata(&out_path) { Ok(meta) => { if meta.len() == 0 { eprintln!("❌ LLVM object is empty: {}", out_path); process::exit(1); } if std::env::var("NYASH_CLI_VERBOSE").ok().as_deref() == Some("1") { eprintln!("[LLVM] object emitted: {} ({} bytes)", out_path, meta.len()); } } Err(e) => { // Try one immediate retry by writing through the compiler again (rare FS lag safeguards) if std::env::var("NYASH_CLI_VERBOSE").ok().as_deref() == Some("1") { eprintln!("[Runner/LLVM] object not found after emit, retrying once: {} ({})", out_path, e); } if let Err(e2) = llvm_compile_to_object(&module, &out_path) { eprintln!("❌ LLVM object emit error (retry): {}", e2); process::exit(1); } match std::fs::metadata(&out_path) { Ok(meta2) => { if meta2.len() == 0 { eprintln!("❌ LLVM object is empty (after retry): {}", out_path); process::exit(1); } if std::env::var("NYASH_CLI_VERBOSE").ok().as_deref() == Some("1") { eprintln!("[LLVM] object emitted after retry: {} ({} bytes)", out_path, meta2.len()); } } Err(e3) => { eprintln!("❌ LLVM object not found after emit (retry): {} ({})", out_path, e3); process::exit(1); } } } } return; } #[cfg(not(feature = "llvm"))] { eprintln!("❌ LLVM backend not available (object emit)."); process::exit(1); } } // Execute via LLVM backend (mock or real) #[cfg(feature = "llvm")] { use nyash_rust::backend::llvm_compile_and_execute; let temp_path = "nyash_llvm_temp"; match llvm_compile_and_execute(&module, temp_path) { Ok(result) => { if let Some(int_result) = result.as_any().downcast_ref::() { let exit_code = int_result.value; println!("✅ LLVM execution completed!"); println!("📊 Exit code: {}", exit_code); process::exit(exit_code as i32); } else { println!("✅ LLVM execution completed (non-integer result)!"); println!("📊 Result: {}", result.to_string_box().value); } }, Err(e) => { eprintln!("❌ LLVM execution error: {}", e); process::exit(1); } } } #[cfg(not(feature = "llvm"))] { println!("🔧 Mock LLVM Backend Execution:"); println!(" Build with --features llvm for real compilation."); if let Some(main_func) = module.functions.get("Main.main") { for (_bid, block) in &main_func.blocks { for inst in &block.instructions { match inst { MirInstruction::Return { value: Some(_) } => { println!("✅ Mock exit code: 42"); process::exit(42); } MirInstruction::Return { value: None } => { println!("✅ Mock exit code: 0"); process::exit(0); } _ => {} } } } } println!("✅ Mock exit code: 0"); process::exit(0); } } }