diff --git a/src/context.rs b/src/context.rs index 7b09dd2..795110e 100644 --- a/src/context.rs +++ b/src/context.rs @@ -4,6 +4,7 @@ use super::err::RuntimeError; #[derive(Debug)] pub struct Context { + debug: bool, ptr: isize, stack: Vec, label_map: HashMap, @@ -12,8 +13,9 @@ pub struct Context { impl Context { - pub fn new() -> Self { + pub fn new(debug: bool) -> Self { Self { + debug, ptr: 0, stack: vec![], label_map: HashMap::new(), @@ -21,18 +23,22 @@ impl Context { } } + pub fn is_debug(&self) -> bool { + self.debug + } + // label and ptr pub fn define_label(&mut self, label: isize, ptr: isize) { self.label_map.insert(label, ptr); } - // pub fn find_label(&mut self, label: isize) -> Option { - // self.label_map.get(&label).map(|i| *i) - // } + pub fn find_label(&mut self, label: isize) -> Option { + self.label_map.get(&label).map(|i| *i) + } - // pub fn goto(&mut self, p: isize) { - // self.ptr = p; - // } + pub fn goto(&mut self, p: isize) { + self.ptr = p; + } pub fn get_ptr(&self) -> isize { self.ptr @@ -56,11 +62,11 @@ impl Context { } // memory - pub fn mem_put(&mut self, addr: isize, val: isize) { + pub fn put_mem(&mut self, addr: isize, val: isize) { self.mem_map.insert(addr, val); } - pub fn mem_get(&self, addr: isize) -> Option { + pub fn get_mem(&self, addr: isize) -> Option { self.mem_map.get(&addr).map(|i| *i) } } @@ -139,7 +145,7 @@ impl Instruction { let val = context.pop(); let addr = context.pop(); if let (Some(val), Some(addr)) = (val, addr) { - context.mem_put(addr, val); + context.put_mem(addr, val); } else { return Err(RuntimeError::ErrorVmState(format!("Stack is not enough when call store!"))); } @@ -147,8 +153,8 @@ impl Instruction { Instruction::Retrieve => { let addr = context.pop(); if let Some(addr) = addr { - match context.mem_get(addr) { - Some(val) => { context.mem_put(addr, val); }, + match context.get_mem(addr) { + Some(val) => { context.put_mem(addr, val); }, None => return Err(RuntimeError::ErrorVmState(format!("Memory addr not found: {}!", addr))), } } else { @@ -157,17 +163,36 @@ impl Instruction { } Instruction::DefineLabel(_) => (), // JUST SKIP! Instruction::CallAtLabel(_i) => return Err(RuntimeError::NotImplemented("CallAtLabel".into())), - Instruction::GotoLabel(_i) => return Err(RuntimeError::NotImplemented("GotoLabel".into())), - Instruction::GotoLabelE0(_i) => return Err(RuntimeError::NotImplemented("GotoLabelE0".into())), - Instruction::GotoLabelL0(_i) => return Err(RuntimeError::NotImplemented("GotoLabelL0".into())), + Instruction::GotoLabel(i) => match context.find_label(*i) { + Some(ptr) => context.goto(ptr), + None => return Err(RuntimeError::ErrorVmState(format!("Label not found: {}", i))), + }, + Instruction::GotoLabelE0(i) => match context.pop() { + Some(v) => if v == 0 { + match context.find_label(*i) { + Some(ptr) => context.goto(ptr), + None => return Err(RuntimeError::ErrorVmState(format!("Label not found: {}", i))), + } + }, + None => return Err(RuntimeError::ErrorVmState(format!("Stack is not enough when call gotolabele0!"))), + }, + Instruction::GotoLabelL0(i) => match context.pop() { + Some(v) => if v < 0 { + match context.find_label(*i) { + Some(ptr) => context.goto(ptr), + None => return Err(RuntimeError::ErrorVmState(format!("Label not found: {}", i))), + } + }, + None => return Err(RuntimeError::ErrorVmState(format!("Stack is not enough when call gotolabell0!"))), + }, Instruction::ReturnCallAt => return Err(RuntimeError::NotImplemented("ReturnCallAt".into())), Instruction::End => return Err(RuntimeError::EndVm), Instruction::StdOutChar => match context.pop() { - Some(i) => println!("{}", i as u8 as char), + Some(i) => print!("{}", i as u8 as char), None => return Err(RuntimeError::ErrorVmState(format!("Stack is not enough when call stdoutchar!"))), }, Instruction::StdOutNum => match context.pop() { - Some(i) => println!("{}", i), + Some(i) => print!("{}", i), None => return Err(RuntimeError::ErrorVmState(format!("Stack is not enough when call stdoutnum!"))), }, Instruction::StdInChar => return Err(RuntimeError::NotImplemented("StdInChar".into())), @@ -192,6 +217,9 @@ impl Vm { pub fn defint_labels(&self, context: &mut Context) { for (ptr, ins) in self.instructions.iter().enumerate() { if let Instruction::DefineLabel(i) = ins { + if context.is_debug() { + println!("[DEBUG] Define label: {} -> {}", *i, ptr as isize); + } context.define_label(*i, ptr as isize); } } @@ -202,9 +230,17 @@ impl Vm { let ptr = context.get_ptr(); let ins = self.instructions.get(ptr as usize); match ins { - Some(ins) => match ins.execute(context) { - Err(err) => return Err(err), - Ok(_) => context.move_ptr_next(), + Some(ins) => { + if context.is_debug() { + let is_define_label = if let Instruction::DefineLabel(_) = ins { true } else { false }; + if !is_define_label { + println!("[DEBUG] Execute instruction: {:?}", ins); + } + } + match ins.execute(context) { + Err(err) => return Err(err), + Ok(_) => context.move_ptr_next(), + } }, None => return Err(RuntimeError::ErrorVmState(format!("Instruction at {} not found", ptr))), } diff --git a/src/main.rs b/src/main.rs index 51d3649..85dfd48 100644 --- a/src/main.rs +++ b/src/main.rs @@ -22,7 +22,14 @@ fn main() { }, }; - let mut context = Context::new(); + let mut context = Context::new(false); + + if context.is_debug() { + println!("[DEBUG] parsed instructions:"); + for (ptr, ins) in instructions.iter().enumerate() { + println!("{} {:?}", ptr, ins); + } + } let vm = Vm::new(instructions); vm.defint_labels(&mut context); @@ -32,8 +39,10 @@ fn main() { Err(err) => println!("Vm error: {}", err), Ok(_) => (), } - println!("{:?}", vm); - println!("{:?}", context); + + if context.is_debug() { + println!("[DEBUG] Vm ended, context: {:?}", context); + } } fn parse_lang(lang: &str) -> Result, ParseError> { @@ -63,13 +72,11 @@ fn match_instruction(ins_coll: &InsColl, cs: &mut dyn Iterator) -> Re InsType::Path(ins_coll) => return match_instruction(&ins_coll, cs), InsType::Node(ins) => { let data = if ins.has_data() { Some(read_number(cs)?) } else { None }; - println!("{:?} {}", ins, if let Some(n) = data { n.to_string() } else { "".to_owned() }); // TODO return Ok(Some(ins.new_instruction(data))); }, } } } - // println!("ERROR!!!! syntax error!"); return Err(ParseError::ErrorSyntax("ERROR!!!! syntax error!".into())); } Ok(None)