From 64baa7a7490dadf2252a963e554e00c5dece58d2 Mon Sep 17 00:00:00 2001 From: Nilstrieb Date: Sat, 18 Sep 2021 20:37:52 +0200 Subject: [PATCH] better info --- src/db.rs | 57 ++++++++++++++++++++++++++++++++--------------------- src/main.rs | 2 +- src/stmt.rs | 35 +++++++++++++++++--------------- test.m8 | 16 ++++++++++----- 4 files changed, 65 insertions(+), 45 deletions(-) diff --git a/src/db.rs b/src/db.rs index 5f267db..6387fc2 100644 --- a/src/db.rs +++ b/src/db.rs @@ -14,22 +14,24 @@ enum VmState { Run, Break, Stop, + OutOfBounds, } impl Vm { fn step(&mut self) -> VmState { let pc = self.pc; self.pc += 1; - match self.stmts[pc] { - Stmt::Inc(r) => self.registers[r] += 1, - Stmt::Dec(r) => self.registers[r] -= 1, - Stmt::IsZero(r, line) => { + match self.stmts.get(pc).cloned() { + Some(Stmt::Inc(r)) => self.registers[r] += 1, + Some(Stmt::Dec(r)) => self.registers[r] -= 1, + Some(Stmt::IsZero(r, line)) => { if self.registers[r] == 0 { self.pc = line - 1; } } - Stmt::Jump(line) => self.pc = line - 1, - Stmt::Stop => return VmState::Stop, + Some(Stmt::Jump(line)) => self.pc = line - 1, + Some(Stmt::Stop) => return VmState::Stop, + None => return VmState::OutOfBounds, } if self.breakpoints.contains(&self.pc) { VmState::Break @@ -40,9 +42,8 @@ impl Vm { fn run(&mut self) -> VmState { loop { - match self.step() { - state @ (VmState::Break | VmState::Stop) => return state, - _ => {} + if let state @ (VmState::Break | VmState::Stop | VmState::OutOfBounds) = self.step() { + return state; } } } @@ -66,16 +67,23 @@ pub fn run(stmts: Vec) { }; loop { - match debug_input(&mut vm) { + match debug_input(&vm) { VmInstruction::Run => match vm.run() { VmState::Stop => break, + VmState::OutOfBounds => { + print_program(&vm); + print_registers(&vm); + eprintln!("error: Program ran out of bounds."); + return; + } VmState::Run => unreachable!(), _ => {} }, - VmInstruction::Step => match vm.step() { - VmState::Stop => break, - _ => {} - }, + VmInstruction::Step => { + if let VmState::Stop = vm.step() { + break; + } + } VmInstruction::Break(line) => { let position = vm.breakpoints.iter().position(|point| *point == line); match position { @@ -92,14 +100,10 @@ pub fn run(stmts: Vec) { fn debug_input(vm: &Vm) -> VmInstruction { loop { - let mut input_buf = String::new(); - print!("(m8db) "); - std::io::stdout().flush().unwrap(); - std::io::stdin().read_line(&mut input_buf).unwrap(); - let input = input_buf.trim(); + let input = get_input(); let mut iter = input.split_ascii_whitespace(); - match iter.next() { - Some(str) => match str { + if let Some(str) = iter.next() { + match str { "r" | "register" => print_registers(vm), "p" | "program" => print_program(vm), "h" | "?" | "help" => print_help(), @@ -117,8 +121,7 @@ fn debug_input(vm: &Vm) -> VmInstruction { "c" | "continue" => return VmInstruction::Run, "s" | "step" => return VmInstruction::Step, _ => {} - }, - None => {} + } } } } @@ -195,3 +198,11 @@ fn print_help() { " ); } + +fn get_input() -> String { + let mut input_buf = String::new(); + print!("(m8db) "); + std::io::stdout().flush().unwrap(); + std::io::stdin().read_line(&mut input_buf).unwrap(); + input_buf.trim().to_owned() +} diff --git a/src/main.rs b/src/main.rs index bfdc7b0..c2e6c72 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,7 +2,7 @@ mod db; mod stmt; fn main() { - let filename = match std::env::args().skip(1).next() { + let filename = match std::env::args().nth(1) { Some(name) => name, None => { eprintln!("error: no file provided.\nUsage: "); diff --git a/src/stmt.rs b/src/stmt.rs index 12992cd..4c02a4c 100644 --- a/src/stmt.rs +++ b/src/stmt.rs @@ -11,54 +11,57 @@ pub enum Stmt { } pub fn parse(text: &str) -> Result, String> { - text.lines().map(parse_line).collect() + text.lines() + .filter(|line| line.split_whitespace().next().is_some()) + .map(parse_line) + .collect() } fn parse_line(line: &str) -> Result { - const NO_REGISTER: fn() -> String = || "No register".to_string(); - const NO_LINE_NUMBER: fn() -> String = || "No line number".to_string(); - const EMPTY_LINE: fn() -> String = || "Empty line not allowed".to_string(); - const DISPLAY_ERR: fn(ParseIntError) -> String = |parse_err| parse_err.to_string(); + let no_register = || "No register".to_string(); + let no_line_number = || "No line number".to_string(); + let empty_line = || "Empty line not allowed".to_string(); + let display_err = |parse_err: ParseIntError| parse_err.to_string(); let mut iter = line.split_ascii_whitespace(); - let first = iter.next().ok_or_else(EMPTY_LINE)?; + let first = iter.next().ok_or_else(empty_line)?; Ok(match first { "INC" => { let register = iter .next() - .ok_or_else(NO_REGISTER)? + .ok_or_else(no_register)? .parse() - .map_err(DISPLAY_ERR)?; + .map_err(display_err)?; Stmt::Inc(register) } "DEC" => { let register = iter .next() - .ok_or_else(NO_REGISTER)? + .ok_or_else(no_register)? .parse() - .map_err(DISPLAY_ERR)?; + .map_err(display_err)?; Stmt::Dec(register) } "IS_ZERO" => { let register = iter .next() - .ok_or_else(NO_REGISTER)? + .ok_or_else(no_register)? .parse() - .map_err(DISPLAY_ERR)?; + .map_err(display_err)?; let line_number = iter .next() - .ok_or_else(NO_LINE_NUMBER)? + .ok_or_else(no_line_number)? .parse() - .map_err(DISPLAY_ERR)?; + .map_err(display_err)?; Stmt::IsZero(register, line_number) } "JUMP" => { let line_number = iter .next() - .ok_or_else(NO_LINE_NUMBER)? + .ok_or_else(no_line_number)? .parse() - .map_err(DISPLAY_ERR)?; + .map_err(display_err)?; Stmt::Jump(line_number) } "STOP" => Stmt::Stop, diff --git a/test.m8 b/test.m8 index de343cd..64cc87e 100644 --- a/test.m8 +++ b/test.m8 @@ -1,5 +1,11 @@ -IS_ZERO 1 5 -INC 3 -DEC 1 -JUMP 1 -STOP \ No newline at end of file +INC 1 +INC 1 +INC 1 +INC 1 +INC 1 +INC 1 +INC 1 +INC 1 +INC 1 +INC 1 +INC 1