From 92b026ccba90ab7b14c8a70537d8511474e51ce9 Mon Sep 17 00:00:00 2001 From: Nilstrieb Date: Sat, 18 Sep 2021 21:28:24 +0200 Subject: [PATCH] debug printing the program now shows the original source code --- src/db.rs | 33 +++++++++++++++++----------- src/stmt.rs | 62 +++++++++++++++++++++++++++++++++++++---------------- test.m8 | 10 ++++----- 3 files changed, 69 insertions(+), 36 deletions(-) diff --git a/src/db.rs b/src/db.rs index 6387fc2..996ba0d 100644 --- a/src/db.rs +++ b/src/db.rs @@ -1,9 +1,11 @@ -use crate::stmt::Stmt; +use crate::stmt::{Code, Stmt}; use std::io::Write; #[derive(Debug, Clone)] -struct Vm { +struct Vm<'a> { stmts: Vec, + span: Vec, + code_lines: Vec<&'a str>, pc: usize, registers: Vec, breakpoints: Vec, @@ -17,7 +19,7 @@ enum VmState { OutOfBounds, } -impl Vm { +impl Vm<'_> { fn step(&mut self) -> VmState { let pc = self.pc; self.pc += 1; @@ -57,10 +59,12 @@ enum VmInstruction { Set(usize, usize), } -pub fn run(stmts: Vec) { - let max_register_index = max_register(&stmts); +pub fn run(code: Code) { + let max_register_index = max_register(&code.stmts); let mut vm = Vm { - stmts, + stmts: code.stmts, + span: code.span, + code_lines: code.code_lines, pc: 0, registers: vec![0; max_register_index + 1], breakpoints: vec![], @@ -157,16 +161,19 @@ fn print_program(vm: &Vm) { use std::cmp::min; println!("Program:"); - let lower = if vm.pc > 5 { vm.pc - 5 } else { 0 }; + let lower_stmt = 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) }; + let higher_stmt = if len < 5 { len } else { min(vm.pc + 5, len) }; - for i in lower..higher { - let stmt = vm.stmts[i]; - if i == vm.pc { - println!("> {} {}", i, stmt) + let lower_code = vm.span[lower_stmt]; + let higher_code = vm.span[higher_stmt - 1]; + + for line_number in lower_code..higher_code { + let code_line = vm.code_lines[line_number]; + if line_number == vm.span[vm.pc] { + println!("> {} {}", line_number, code_line) } else { - println!("{} {}", i, stmt); + println!("{} {}", line_number, code_line); } } } diff --git a/src/stmt.rs b/src/stmt.rs index 32e2d3a..c81c616 100644 --- a/src/stmt.rs +++ b/src/stmt.rs @@ -11,6 +11,13 @@ pub enum Stmt { Stop, } +pub struct Code<'a> { + pub stmts: Vec, + /// Has the same length as `stmts`, points to line numbers where the instructions come from + pub span: Vec, + pub code_lines: Vec<&'a str>, +} + enum IrStmt<'a> { Inc(usize), Dec(usize), @@ -20,13 +27,15 @@ enum IrStmt<'a> { Stop, } -pub fn parse(text: &str) -> Result, String> { +pub fn parse(text: &str) -> Result { let mut labels = HashMap::new(); let mut statements = Vec::new(); let mut statement_number = 0; - for (line_number, line) in text.lines().enumerate() { + let code_lines = text.lines().collect::>(); + + for (line_number, line) in code_lines.iter().enumerate() { if line.split_whitespace().next().is_none() { continue; } @@ -43,26 +52,43 @@ pub fn parse(text: &str) -> Result, String> { } } - statements + let result: Result, String> = statements .iter() - .map(|stmt| match stmt.0 { - IrStmt::Inc(r) => Ok(Stmt::Inc(r)), - IrStmt::Dec(r) => Ok(Stmt::Dec(r)), - IrStmt::IsZero(r, label) => Ok(Stmt::IsZero( - r, - match labels.get(label) { - Some(line) => *line, - None => return Err(format!("Label '{}' not found on line {}", label, stmt.1)), - }, + .map(|(stmt, span)| match *stmt { + IrStmt::Inc(r) => Ok((Stmt::Inc(r), *span)), + IrStmt::Dec(r) => Ok((Stmt::Dec(r), *span)), + IrStmt::IsZero(r, label) => Ok(( + Stmt::IsZero( + r, + match labels.get(label) { + Some(line) => *line, + None => { + return Err(format!("Label '{}' not found on line {}", label, span)) + } + }, + ), + *span, )), - IrStmt::Jump(label) => Ok(Stmt::Jump(match labels.get(label) { - Some(line) => *line, - None => return Err(format!("Label '{}' not found on line {}", label, stmt.1)), - })), - IrStmt::Stop => Ok(Stmt::Stop), + IrStmt::Jump(label) => Ok(( + Stmt::Jump(match labels.get(label) { + Some(line) => *line, + None => return Err(format!("Label '{}' not found on line {}", label, span)), + }), + *span, + )), + IrStmt::Stop => Ok((Stmt::Stop, *span)), IrStmt::Label(_) => unreachable!(), }) - .collect() + .collect(); + + result.map(|vec| { + let (stmts, span) = vec.iter().cloned().unzip(); + Code { + stmts, + span, + code_lines, + } + }) } fn parse_line(line: &str) -> Result { diff --git a/test.m8 b/test.m8 index d640005..280c150 100644 --- a/test.m8 +++ b/test.m8 @@ -1,8 +1,8 @@ -INC 0 -INC 0 +INC 1 +.test1 +.test2 +.test3 +INC 1 JUMP end -DEC 0 -DEC 0 -DEC 0 .end STOP \ No newline at end of file