diff --git a/src/db.rs b/src/db.rs index a4f4664..5f267db 100644 --- a/src/db.rs +++ b/src/db.rs @@ -25,10 +25,10 @@ impl Vm { Stmt::Dec(r) => self.registers[r] -= 1, Stmt::IsZero(r, line) => { if self.registers[r] == 0 { - self.pc = line; + self.pc = line - 1; } } - Stmt::Jump(line) => self.pc = line, + Stmt::Jump(line) => self.pc = line - 1, Stmt::Stop => return VmState::Stop, } if self.breakpoints.contains(&self.pc) { @@ -39,8 +39,12 @@ impl Vm { } fn run(&mut self) -> VmState { - while let VmState::Run = self.step() {} - VmState::Break + loop { + match self.step() { + state @ (VmState::Break | VmState::Stop) => return state, + _ => {} + } + } } } @@ -49,14 +53,15 @@ enum VmInstruction { Step, Run, Break(usize), + Set(usize, usize), } pub fn run(stmts: Vec) { - let max_register = max_register(&stmts); + let max_register_index = max_register(&stmts); let mut vm = Vm { stmts, pc: 0, - registers: vec![0; max_register], + registers: vec![0; max_register_index + 1], breakpoints: vec![], }; @@ -80,6 +85,7 @@ pub fn run(stmts: Vec) { } } } + VmInstruction::Set(r, value) => vm.registers[r] = value, } } } @@ -104,6 +110,10 @@ fn debug_input(vm: &Vm) -> VmInstruction { }, None => print_breakpoints(vm), }, + "set" => match parse_set_command(&mut iter) { + Some((reg, value)) => return VmInstruction::Set(reg, value), + None => println!("Invalid arguments provided"), + }, "c" | "continue" => return VmInstruction::Run, "s" | "step" => return VmInstruction::Step, _ => {} @@ -113,6 +123,12 @@ fn debug_input(vm: &Vm) -> VmInstruction { } } +fn parse_set_command<'a>(iter: &mut impl Iterator) -> Option<(usize, usize)> { + let reg: usize = iter.next().and_then(|reg| reg.parse().ok())?; + let value: usize = iter.next().and_then(|value| value.parse().ok())?; + Some((reg, value)) +} + fn max_register(stmts: &[Stmt]) -> usize { stmts .iter() @@ -135,11 +151,12 @@ fn print_registers(vm: &Vm) { } fn print_program(vm: &Vm) { - use std::cmp::{max, min}; + use std::cmp::min; println!("Program:"); - let lower = max(vm.pc, 5) - 5; - let higher = min(vm.pc, vm.stmts.len() - 6) + 5; + let lower = if vm.pc > 5 { vm.pc - 5 } else { 0 }; + let len = vm.stmts.len(); + let higher = if len < 5 { len } else { min(vm.pc + 5, len) }; for i in lower..higher { let stmt = vm.stmts[i]; @@ -169,6 +186,7 @@ fn print_help() { "List of commands and their aliases: step (s) -- Steps the program forward by one step + set -- Sets a register to a value break (b) -- Set a breakpoint to a line, use again to toggle continue (c) -- Run the program until the next breakpoint register (r) -- Shows the contents of the registers diff --git a/src/main.rs b/src/main.rs index 4f4acea..bfdc7b0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -26,4 +26,5 @@ Type 'help' for help } }; db::run(statements); + println!("Execution finished."); } diff --git a/test.m8 b/test.m8 index 0118e76..de343cd 100644 --- a/test.m8 +++ b/test.m8 @@ -1,22 +1,5 @@ -INC 1 -INC 1 -INC 1 -INC 2 -INC 2 -IS_ZERO 1 22 -DEC 1 -IS_ZERO 2 13 -INC 4 -INC 5 -DEC 2 -JUMP 8 -IS_ZERO 4 17 +IS_ZERO 1 5 INC 3 -DEC 4 -JUMP 13 -IS_ZERO 5 21 -INC 2 -DEC 5 -JUMP 17 -JUMP 6 +DEC 1 +JUMP 1 STOP \ No newline at end of file