iridium/repl/
mod.rs

1pub mod command_parser;
2
3use std;
4use std::fs::File;
5use std::io;
6use std::io::{Read};
7use std::net::TcpStream;
8use std::num::ParseIntError;
9use std::path::Path;
10use std::sync::mpsc;
11use std::sync::mpsc::{Receiver, Sender};
12
13use nom::types::CompleteStr;
14
15use assembler::program_parsers::program;
16use assembler::Assembler;
17use cluster;
18use repl::command_parser::CommandParser;
19use scheduler::Scheduler;
20use vm::VM;
21const COMMAND_PREFIX: char = '!';
22
23pub static REMOTE_BANNER: &'static str = "Welcome to Iridium! Let's be productive!";
24pub static PROMPT: &'static str = ">>> ";
25
26/// Core structure for the REPL for the Assembler
27#[derive(Default)]
28pub struct REPL {
29    command_buffer: Vec<String>,
30    vm: VM,
31    asm: Assembler,
32    scheduler: Scheduler,
33    pub tx_pipe: Option<Box<Sender<String>>>,
34    pub rx_pipe: Option<Box<Receiver<String>>>,
35}
36
37impl REPL {
38    /// Creates and returns a new assembly REPL
39    pub fn new(vm: VM) -> REPL {
40        let (tx, rx): (Sender<String>, Receiver<String>) = mpsc::channel();
41        REPL {
42            vm,
43            command_buffer: vec![],
44            asm: Assembler::new(),
45            scheduler: Scheduler::new(),
46            tx_pipe: Some(Box::new(tx)),
47            rx_pipe: Some(Box::new(rx)),
48        }
49    }
50
51    /// Run loop similar to the VM execution loop, but the instructions are taken from the user directly
52    /// at the terminal and not from pre-compiled bytecode
53    pub fn run(&mut self) {
54        debug!("Starting REPL run loop with VM ID of {:?}", self.vm.alias);
55        self.send_message(REMOTE_BANNER.to_string());
56        self.send_prompt();
57        loop {
58            // This allocates a new String in which to store whatever the user types each iteration.
59            // TODO: Figure out how allocate this outside of the loop and re-use it every iteration
60            let mut buffer = String::new();
61
62            // Blocking call until the user types in a command
63            let stdin = io::stdin();
64
65            // Here we'll look at the string the user gave us.
66            stdin
67                .read_line(&mut buffer)
68                .expect("Unable to read line from user");
69
70            let historical_copy = buffer.clone();
71            self.command_buffer.push(historical_copy);
72
73            if buffer.starts_with(COMMAND_PREFIX) {
74                self.execute_command(&buffer);
75            } else {
76                let program = match program(CompleteStr(&buffer)) {
77                    Ok((_remainder, program)) => program,
78                    Err(e) => {
79                        self.send_message(format!("There was an error executing the program: {:?}", e));
80                        continue;
81                    }
82                };
83                self.vm
84                    .program
85                    .append(&mut program.to_bytes(&self.asm.symbols));
86                self.vm.run_once();
87            }
88        }
89    }
90
91    pub fn run_single(&mut self, buffer: &str) -> Option<String> {
92        if buffer.starts_with(COMMAND_PREFIX) {
93            self.execute_command(&buffer);
94            None
95        } else {
96            let program = match program(CompleteStr(&buffer)) {
97                Ok((_remainder, program)) => Some(program),
98                Err(e) => {
99                    self.send_message(format!("Unable to parse input: {:?}", e));
100                    None
101                }
102            };
103            match program {
104                Some(p) => {
105                    let mut bytes = p.to_bytes(&self.asm.symbols);
106                    self.vm.program.append(&mut bytes);
107                    self.vm.run_once();
108                    None
109                }
110                None => None,
111            }
112        }
113    }
114
115    pub fn send_message(&mut self, msg: String) {
116        match &self.tx_pipe {
117            Some(pipe) => {
118                match pipe.send(msg) {
119                    Ok(_) => {}
120                    Err(_e) => {}
121                };
122            }
123            None => {}
124        }
125    }
126    pub fn send_prompt(&mut self) {
127        match &self.tx_pipe {
128            Some(pipe) => match pipe.send(PROMPT.to_owned()) {
129                Ok(_) => {}
130                Err(_e) => {}
131            },
132            None => {}
133        }
134    }
135
136    fn get_data_from_load(&mut self) -> Option<String> {
137        let stdin = io::stdin();
138        self.send_message("Please enter the path to the file you wish to load: ".to_string());
139        let mut tmp = String::new();
140
141        stdin
142            .read_line(&mut tmp)
143            .expect("Unable to read line from user");
144        self.send_message("Attempting to load program from file...".to_string());
145
146        let tmp = tmp.trim();
147        let filename = Path::new(&tmp);
148        let mut f = match File::open(&filename) {
149            Ok(f) => f,
150            Err(e) => {
151                self.send_message(format!("There was an error opening that file: {:?}", e));
152                return None;
153            }
154        };
155        let mut contents = String::new();
156        match f.read_to_string(&mut contents) {
157            Ok(_bytes_read) => Some(contents),
158            Err(e) => {
159                self.send_message(format!("there was an error reading that file: {:?}", e));
160                None
161            }
162        }
163    }
164
165    /// Accepts a hexadecimal string WITHOUT a leading `0x` and returns a Vec of u8
166    /// Example for a LOAD command: 00 01 03 E8
167    #[allow(dead_code)]
168    fn parse_hex(&mut self, i: &str) -> Result<Vec<u8>, ParseIntError> {
169        let split = i.split(' ').collect::<Vec<&str>>();
170        let mut results: Vec<u8> = vec![];
171        for hex_string in split {
172            let byte = u8::from_str_radix(&hex_string, 16);
173            match byte {
174                Ok(result) => {
175                    results.push(result);
176                }
177                Err(e) => {
178                    return Err(e);
179                }
180            }
181        }
182        Ok(results)
183    }
184
185    fn execute_command(&mut self, input: &str) {
186        let args = CommandParser::tokenize(input);
187        match args[0] {
188            "!quit" => self.quit(&args[1..]),
189            "!history" => self.history(&args[1..]),
190            "!program" => self.program(&args[1..]),
191            "!clear_program" => self.clear_program(&args[1..]),
192            "!clear_registers" => self.clear_registers(&args[1..]),
193            "!registers" => self.registers(&args[1..]),
194            "!symbols" => self.symbols(&args[1..]),
195            "!load_file" => self.load_file(&args[1..]),
196            "!spawn" => self.spawn(&args[1..]),
197            "!start_cluster" => self.start_cluster(&args[1..]),
198            "!join_cluster" => self.join_cluster(&args[1..]),
199            "!cluster_members" => self.cluster_members(&args[1..]),
200            _ => {
201                self.send_message("Invalid command!".to_string());
202            }
203        };
204    }
205
206    fn quit(&mut self, _args: &[&str]) {
207        self.send_message("Farewell! Have a great day!".to_string());
208        std::process::exit(0);
209    }
210
211    fn history(&mut self, _args: &[&str]) {
212        let mut results = vec![];
213        for command in &self.command_buffer {
214            results.push(command.clone());
215        }
216        self.send_message(format!("{:#?}", results));
217    }
218
219    fn program(&mut self, _args: &[&str]) {
220        self.send_message("Listing instructions currently in VM's program vector: ".to_string());
221        let mut results = vec![];
222        for instruction in &self.vm.program {
223            results.push(instruction.clone())
224        }
225        self.send_message(format!("{:#?}", results));
226        self.send_message("End of Program Listing".to_string());
227    }
228
229    fn clear_program(&mut self, _args: &[&str]) {
230        self.vm.program.clear();
231    }
232
233    fn clear_registers(&mut self, _args: &[&str]) {
234        self.send_message("Setting all registers to 0".to_string());
235        for i in 0..self.vm.registers.len() {
236            self.vm.registers[i] = 0;
237        }
238        self.send_message("Done!".to_string());
239    }
240
241    fn registers(&mut self, _args: &[&str]) {
242        self.send_message("Listing registers and all contents:".to_string());
243        let mut results = vec![];
244        for register in &self.vm.registers {
245            results.push(register.clone());
246        }
247        self.send_message(format!("{:#?}", results));
248        self.send_message("End of Register Listing".to_string());
249    }
250
251    fn symbols(&mut self, _args: &[&str]) {
252        let mut results = vec![];
253        for symbol in &self.asm.symbols.symbols {
254            results.push(symbol.clone());
255        }
256        self.send_message("Listing symbols table:".to_string());
257        self.send_message(format!("{:#?}", results));
258        self.send_message("End of Symbols Listing".to_string());
259    }
260
261    fn load_file(&mut self, _args: &[&str]) {
262        let contents = self.get_data_from_load();
263        if let Some(contents) = contents {
264            match self.asm.assemble(&contents) {
265                Ok(mut assembled_program) => {
266                    self.send_message("Sending assembled program to VM".to_string());
267                    self.vm.program.append(&mut assembled_program);
268                    self.vm.run();
269                }
270                Err(errors) => {
271                    for error in errors {
272                        self.send_message(format!("Unable to parse input: {}", error));
273                    }
274                    return;
275                }
276            }
277        } else {
278            return;
279        }
280    }
281
282    fn spawn(&mut self, _args: &[&str]) {
283        let contents = self.get_data_from_load();
284        self.send_message(format!("Loaded contents: {:#?}", contents));
285        if let Some(contents) = contents {
286            match self.asm.assemble(&contents) {
287                Ok(mut assembled_program) => {
288                    self.send_message("Sending assembled program to VM".to_string());
289                    self.vm.program.append(&mut assembled_program);
290                    self.scheduler.get_thread(self.vm.clone());
291                }
292                Err(errors) => {
293                    for error in errors {
294                        self.send_message(format!("Unable to parse input: {}", error));
295                    }
296                    return;
297                }
298            }
299        } else {
300            return;
301        }
302    }
303
304    fn start_cluster(&mut self, _args: &[&str]) {
305        self.send_message("Started cluster server!".to_string());
306        self.vm.bind_cluster_server();
307    }
308
309    fn join_cluster(&mut self, args: &[&str]) {
310        debug!("Joining cluster with VM ID: {:?}", self.vm.alias);
311        self.send_message("Attempting to join cluster...".to_string());
312        let ip = args[0];
313        let port = args[1];
314        let addr = ip.to_owned() + ":" + port.clone();
315        if let Ok(stream) = TcpStream::connect(addr) {
316            self.send_message("Connected to cluster!".to_string());
317            let mut cc =
318                cluster::client::ClusterClient::new(stream, self.vm.connection_manager.clone(), self.vm.server_port.clone().unwrap()).with_alias(self.vm.alias.clone().unwrap());
319            debug!("CC Hello is: {:#?}", cc);
320            cc.send_hello();
321            if let Some(ref a) = self.vm.alias {
322                if let Ok(mut lock) = self.vm.connection_manager.write() {
323                    let client_tuple = (a.to_string(), cc.ip_as_string().unwrap(), cc.port_as_string().unwrap());
324                    lock.add_client(client_tuple, cc);
325                }
326            }
327        } else {
328            self.send_message("Could not connect to cluster!".to_string());
329        }
330    }
331
332    fn cluster_members(&mut self, _args: &[&str]) {
333        self.send_message("Listing Known Nodes:".to_string());
334        let cluster_members = self
335            .vm
336            .connection_manager
337            .read()
338            .unwrap()
339            .get_client_names();
340        self.send_message(format!("{:#?}", cluster_members));
341    }
342}