diff --git a/data/bootcodex.um b/data/bootcodex.um new file mode 100644 index 0000000..7a805da Binary files /dev/null and b/data/bootcodex.um differ diff --git a/src/bin/um.rs b/src/bin/um.rs index 7bea400..bc25374 100644 --- a/src/bin/um.rs +++ b/src/bin/um.rs @@ -1,5 +1,5 @@ extern crate um; -use um::cpu::{Cpu}; +use um::cpu::{Cpu,Console}; use std::io; use std::io::prelude::*; use std::fs::File; @@ -9,8 +9,43 @@ use clap::Parser; /// Run a um program #[derive(Parser)] struct Cli { + // debug level + #[clap(short, long, default_value_t = 0)] + debug: u32, /// The path to the program to load - program: std::path::PathBuf, + program: std::path::PathBuf + +} + +struct IoConsole { + inptr: usize, + inbuf: String +} + +impl IoConsole { + pub fn make() -> IoConsole { + IoConsole { + inptr: 0, + inbuf: String::from("") + } + } +} + +impl Console for IoConsole { + fn read(&mut self) -> Option { + if self.inptr >= self.inbuf.len() { + if let Err(_) = std::io::stdin().read_line(&mut self.inbuf) { + return None; + } + } + let r = self.inbuf.bytes().nth(self.inptr).unwrap(); + self.inptr +=1; + Some(r) + } + fn write(&mut self, c: u8) { + let buf = [c;1]; + let _ = std::io::stdout().write(&buf); + } } @@ -36,21 +71,11 @@ fn main() -> io::Result<()> { } let mut c = Cpu::new(pgm); - cont = true; - println!("start\n{}", c.state()); - while cont { - let r = c.step(); - cont = match r { - Ok(_) => { - println!("ok\n{}", c.state()); - true - }, - Err(e) => { - println!("Error {:?}", e); - false - } - }; + c.set_debug(args.debug); + let mut cons = IoConsole::make(); + match c.run(&mut cons) { + Err(e) => println!("Error {:?}", e), + Ok(_) => () } Ok(()) - } \ No newline at end of file diff --git a/src/cpu.rs b/src/cpu.rs index 79502f5..e74678a 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -27,7 +27,8 @@ pub struct Cpu { iarr: u32, finger: u32, out: Option, - in_reg: Option + in_reg: Option, + debug: u32 } @@ -41,10 +42,14 @@ impl Cpu { iarr: 1, finger: 0, in_reg: None, - out: None + out: None, + debug: 0 } } + pub fn set_debug(&mut self, debug: u32) { + self.debug = debug; + } fn gr(&self, r: u8) -> u32{ self.reg[r as usize] } @@ -215,6 +220,22 @@ impl Cpu { Ok(()) } + fn handle_lod(&mut self, i:NormalInstruction) -> Result<(), CpuError>{ + let aidx = self.gr(i.b); + let aoff = self.gr(i.c); + if let Some(arr) = self.arr.get(&aidx){ + if arr.len() > aoff as usize { + self.arr.insert(0, arr.clone()); + self.finger = aoff; + Ok(()) + } else { + Err(CpuError::ArrayOutOfBounds) + } + } else { + Err(CpuError::InvalidArray) + } + } + fn exec(&mut self, instruction: Instruction)-> Result<(), CpuError>{ //println!("{:?}", instruction); match instruction { @@ -231,7 +252,8 @@ impl Cpu { Instruction::Abandon(i) => self.handle_abn(i), Instruction::Output(i) => self.handle_out(i), Instruction::Input(i) => self.handle_inp(i), - _ => Err(CpuError::InvalidInstruction) + Instruction::Load(i) => self.handle_lod(i), + //_ => Err(CpuError::InvalidInstruction) } } @@ -239,14 +261,19 @@ impl Cpu { self.out = None; self.in_reg = None; let i = self.ins()?; - self.exec(i)?; self.finger += 1; + self.exec(i)?; Ok(()) } pub fn run(&mut self, console: &mut impl Console) -> Result<(), CpuError> { let mut cont = true; + while cont { + if self.debug > 5 { + println!("{:?}", self.ins()); + println!("{}", self.state()); + } cont = match self.step() { Ok(_) => true, Err(CpuError::ProgramEnd) => false, @@ -632,4 +659,46 @@ mod tests{ assert_eq!(c.reg, exp); Ok(()) } + + #[test] + fn test_lod() -> Result<(), CpuError> { + let pgm = vec!( ezop(12, 1, 2, 3) ); + let mut c = Cpu::new(pgm); + c.arr.insert(1338, vec![0,0,0,1339]); + c.reg = [0, 0, 1338, 3, 0, 0, 0, 0]; + c.step()?; + assert_eq!(c.finger, 3); + if let Some(arr) = c.arr.get(&0){ + assert_eq!(arr,&vec![0,0,0,1339] ); + Ok(()) + } else { + Err(CpuError::InvalidArray) + } + } + + #[test] + fn test_lod_inv() -> Result<(), String> { + let pgm = vec!( ezop(12, 1, 2, 3) ); + let mut c = Cpu::new(pgm); + c.reg = [0, 0, 1338, 3, 0, 0, 0, 0]; + + match c.step() { + Err(CpuError::InvalidArray) => Ok(()), + Ok(_) => Err(format!("unexpected ok")), + Err(e) => Err(format!("unexpected err {:?}", e)) + } + } + + #[test] + fn test_lod_off() -> Result<(), String> { + let pgm = vec!( ezop(12, 1, 2, 3) ); + let mut c = Cpu::new(pgm); + c.reg = [0, 0, 1338, 3, 0, 0, 0, 0]; + c.arr.insert(1338, vec![0]); + match c.step() { + Err(CpuError::ArrayOutOfBounds) => Ok(()), + Ok(_) => Err(format!("unexpected ok")), + Err(e) => Err(format!("unexpected err {:?}", e)) + } + } } \ No newline at end of file