use std::path::PathBuf;
use qala_compiler::vm::Vm;
use reedline::{DefaultPrompt, FileBackedHistory, Reedline, Signal};
pub fn run_repl() -> std::process::ExitCode {
let mut vm = Vm::new_repl();
let history = history_path()
.and_then(|p| FileBackedHistory::with_file(500, p).ok())
.map(Box::new);
let mut editor = match history {
Some(h) => Reedline::create().with_history(h),
None => Reedline::create(),
};
let prompt = DefaultPrompt::default();
println!(
"qala {} repl -- type a line, ctrl-d to exit",
env!("CARGO_PKG_VERSION")
);
loop {
match editor.read_line(&prompt) {
Ok(Signal::Success(line)) => {
let trimmed = line.trim();
if trimmed.is_empty() {
continue;
}
if trimmed == ":quit" || trimmed == ":q" {
break;
}
match vm.repl_eval(trimmed) {
Ok(value) => {
let (rendered, type_name) = vm.render_value(value);
println!("{rendered} : {type_name}");
}
Err(err) => {
eprint!(
"{}",
qala_compiler::diagnostics::Diagnostic::from(err).render("")
);
}
}
}
Ok(Signal::CtrlD) => break,
Ok(Signal::CtrlC) => continue,
Ok(_) => break,
Err(e) => {
eprintln!("repl error: {e}");
return std::process::ExitCode::from(1);
}
}
}
std::process::ExitCode::SUCCESS
}
fn history_path() -> Option<PathBuf> {
std::env::var("HOME")
.or_else(|_| std::env::var("USERPROFILE"))
.ok()
.map(|home| PathBuf::from(home).join(".qala_history"))
}