mod command; use std::{ thread, time, sync::mpsc, io::{ stdout, stdin, Write } }; use command::parse_and_exec; use super::vm::{ VirtualMachine, VirtualMachineInterface }; pub(crate) struct VirtualMachineMonitor { refresh_rate: u64, } macro_rules! info { () => { print!("\x1B[90m|\x1B[0m{:^8}\x1B[90m|> \x1B[0m", "RUN") }; (error $str:expr) => { info!(format!("\x1B[41m{:^8}\x1B[0m", $str)) }; ($str:expr) => { print!("\x1B7\x1B[1G\x1B[90m|\x1B[0m{:^8}\x1B[90m|> \x1B[0m\x1B8", $str) }; } impl VirtualMachineMonitor { pub(crate) fn new(refresh_rate: u64) -> VirtualMachineMonitor { VirtualMachineMonitor { refresh_rate, } } pub(crate) fn start(&mut self, mut vm: VirtualMachine) { // Spawn input handling thread let (tx, rx) = mpsc::channel::(); thread::spawn(move || loop { let mut buffer = String::new(); stdin().read_line(&mut buffer).unwrap(); tx.send(buffer).unwrap(); }); info!(); loop { match rx.try_recv() { Ok(input) => { if let Err(msg) = parse_and_exec(input, &mut vm) { if msg.is_empty() { break; } else { println!("{}", msg); } } else if vm.is_single_step() { println!(""); } info!(); }, _ => {}, } if vm.is_single_step() { info!("STEP"); } else if vm.is_halted() { info!(error "HALTED"); } let _ = stdout().flush(); thread::sleep(time::Duration::from_millis(self.refresh_rate)); } } }