use std::path::{Path, PathBuf};
use std::process::ExitCode;
use blue_lang_proc::{replay, Trace};
pub fn trace_dir() -> Option<PathBuf> {
match std::env::var_os("BLUE_TRACE_DIR") {
Some(d) if d.is_empty() => None,
Some(d) => Some(PathBuf::from(d)),
None => Some(std::env::temp_dir().join("blue-traces")),
}
}
pub fn run(path: &Path) -> Result<ExitCode, String> {
let text = std::fs::read_to_string(path).map_err(|e| format!("{}: {e}", path.display()))?;
let trace = Trace::parse(&text).map_err(|e| format!("{}: {e}", path.display()))?;
println!(
"process {}{} incarnation {}: {} tape entries{}",
trace.pid,
trace
.definition
.as_deref()
.map(|d| format!(" ({d})"))
.unwrap_or_default(),
trace.incarnation,
trace.tape.len(),
if trace.truncated { ", truncated" } else { "" },
);
println!("recorded: {} {}", trace.reason_kind, trace.reason_text);
let r = replay(&trace, blue_lang_runtime::interpreter_hostless());
println!(
"replayed: {} {} ({} of {} tape entries)",
r.kind, r.text, r.consumed, r.tape_len
);
if let Some(d) = &r.diverged {
println!("diverged: {d}");
}
if trace.truncated {
println!("not replayable: the tape outgrew its bound, and a replay needs all of it");
}
if r.reproduced {
println!("reproduced");
Ok(ExitCode::SUCCESS)
} else {
println!("not reproduced");
Ok(ExitCode::FAILURE)
}
}