can run simple script, add debug output
This commit is contained in:
@@ -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))),
|
||||
}
|
||||
|
||||
17
src/main.rs
17
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<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)
|
||||
|
||||
Reference in New Issue
Block a user