use anyhow::Result;
use std::io::{self, Write};
use std::sync::Arc;
use crate::runtime_minimal::MinimalRuntime;
#[derive(Debug, Clone)]
pub struct SimpleReplConfig {
pub prompt: String,
pub history_size: usize,
}
impl Default for SimpleReplConfig {
fn default() -> Self {
Self {
prompt: "amber> ".to_string(),
history_size: 100,
}
}
}
pub struct SimpleRepl {
runtime: Arc<Mutex<MinimalRuntime>>,
config: SimpleReplConfig,
}
impl SimpleRepl {
pub fn new() -> Result<Self> {
let runtime = MinimalRuntime::new()?;
Ok(Self {
runtime: Arc::new(Mutex::new(runtime)),
config: SimpleReplConfig::default(),
})
}
pub fn with_config(config: SimpleReplConfig) -> Result<Self> {
let runtime = MinimalRuntime::new()?;
Ok(Self {
runtime: Arc::new(Mutex::new(runtime)),
config,
})
}
pub fn run(&mut self) -> Result<()> {
println!("🐝 Amber REPL - High-performance JavaScript/TypeScript runtime");
println!("Built with Rust + V8 (minimal edition)");
println!("Type JavaScript code and press Enter to execute");
println!("Type .exit or Ctrl+C to quit");
println!("Type .help for more information");
println!();
let mut buffer = String::new();
loop {
print!("{}", self.config.prompt);
io::stdout().flush()?;
buffer.clear();
match io::stdin().read_line(&mut buffer) {
Ok(_) => {
let input = buffer.trim();
if input.is_empty() {
continue;
}
if input.starts_with('.') {
self.handle_command(input)?;
continue;
}
let result = self.execute_code(input);
match result {
Ok(output) => {
if !output.trim().is_empty() {
println!("{}", output);
}
}
Err(e) => {
eprintln!("Error: {}", e);
}
}
}
Err(_) => {
println!("\nExiting REPL...");
break;
}
}
}
Ok(())
}
fn handle_command(&mut self, command: &str) -> Result<()> {
match command {
".help" => {
println!("Available commands:");
println!(" .help - Show this help message");
println!(" .exit - Exit the REPL");
println!(" .clear - Clear the screen");
println!(" .info - Show runtime information");
}
".exit" => {
println!("Exiting REPL...");
std::process::exit(0);
}
".clear" => {
print!("\x1B[2J\x1B[H");
io::stdout().flush()?;
}
".info" => {
println!("Amber Runtime Information:");
println!(" Version: 0.1.3");
println!(" Engine: V8 (rusty_v8)");
println!(" Runtime: MinimalRuntime");
println!(" Features: Basic JavaScript execution");
}
_ => {
println!("Unknown command: {}", command);
println!("Type .help for available commands");
}
}
Ok(())
}
fn execute_code(&self, code: &str) -> Result<String> {
let runtime = self.runtime.lock().map_err(|e| anyhow::anyhow!("Failed to lock runtime: {}", e))?;
runtime.execute_code(code)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_simple_repl_creation() {
let repl = SimpleRepl::new();
assert!(repl.is_ok());
}
#[test]
fn test_simple_repl_with_config() {
let config = SimpleReplConfig {
prompt: "test> ".to_string(),
history_size: 50,
};
let repl = SimpleRepl::with_config(config);
assert!(repl.is_ok());
}
}