Website Summary Files Commits Branches @commit @diff @stats
path: root / vm / src / vmm / mod.rs
blob: 6f42b4e10372c38dd6ce1a3419bdfeee5c1690de (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
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::<String>();
        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));
        }
    }
}