can run simple script, add debug output

This commit is contained in:
2020-05-08 07:56:26 +08:00
parent 382b604f39
commit b0c5a509ca
2 changed files with 68 additions and 25 deletions

View File

@@ -4,6 +4,7 @@ use super::err::RuntimeError;
#[derive(Debug)]
pub struct Context {
debug: bool,
ptr: isize,
stack: Vec<isize>,
label_map: HashMap<isize, isize>,
@@ -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<isize> {
// self.label_map.get(&label).map(|i| *i)
// }
pub fn find_label(&mut self, label: isize) -> Option<isize> {
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<isize> {
pub fn get_mem(&self, addr: isize) -> Option<isize> {
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))),
}

View File

@@ -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<Vec<Instruction>, ParseError> {
@@ -63,13 +72,11 @@ fn match_instruction(ins_coll: &InsColl, cs: &mut dyn Iterator<Item=char>) -> 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)