diff --git a/interpreter/src/ir/lower.rs b/interpreter/src/ir/lower.rs index bb02cd4..161d48c 100644 --- a/interpreter/src/ir/lower.rs +++ b/interpreter/src/ir/lower.rs @@ -3,10 +3,9 @@ // For the full copyright and license information, please view the LICENSE // files that was distributed with this source code. -use std::{fmt::Display, hash::Hash, mem::forget}; +use std::{hash::Hash, mem::forget}; use bumpalo::{Bump, collections::Vec}; -use indexmap::IndexSet; use parser::{ Atom, BinaryOperator, BinaryPlaceOperator, Body, Expr, ExprNode, Place, SimpleStatement, Statement, UnaryOperator, Variable, @@ -14,14 +13,14 @@ use parser::{ use crate::{ ir::{Hint, HintedReg, Instruction, Label, NonLocal, OpCode, Reg}, - vm::{ExecMode, Interpreter, SymbolTable, Value}, + vm::{Consts, ExecMode, Interpreter, SymbolTable, Value}, }; #[derive(Debug)] pub struct Code<'arena> { pub arena: &'arena Bump, pub bc: Bytecode<'arena>, - pub consts: IndexSet, + pub consts: Consts, pub symbols: SymbolTable<'arena>, free_regs: Vec<'arena, Reg>, pub reg_pointer: u16, @@ -176,7 +175,7 @@ impl Code<'_> { } fn register_const(&mut self, value: Value) -> NonLocal { - NonLocal(self.consts.insert_full(value).0 as u16) + NonLocal(self.consts.0.insert_full(value).0 as u16) } fn following_instr(&self, nth: u16) -> Label { @@ -236,21 +235,20 @@ impl RegsState { } } -pub fn test_interpreter(stmnt: &Body<'_>) -> impl Display { +pub fn test_interpreter(stmnt: &Body<'_>) -> String { let bump = Bump::with_capacity(16384); let mut c = Code { arena: &bump, bc: Bytecode::new_in(&bump), - consts: IndexSet::new(), + consts: Consts::new(), symbols: SymbolTable::new_in(&bump), reg_pointer: 0, free_regs: Vec::new_in(&bump), }; c.lower_body(stmnt); - let code = c.to_string(); let mut vm = Interpreter::new(ExecMode::Uu, c); vm.run(); - format!("{code}---\n{vm:#?}") + vm.to_string() } impl From for OpCode { @@ -301,33 +299,6 @@ impl Eq for Value {} // fn fold(&self, args: Self::Args) -> T; // } -impl Display for Bytecode<'_> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let n = self.code.len() / 10 + 1; - for (i, e) in self.code.iter().enumerate() { - write!(f, "{i:n$}: {e}")?; - if i + 1 < self.code.len() as _ { - writeln!(f)?; - } - } - Ok(()) - } -} - -impl Display for Code<'_> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - writeln!(f, "Bytecode:\n{}\n", self.bc)?; - writeln!(f, "Consts:")?; - for (i, e) in self.consts.iter().enumerate() { - write!(f, "mem[{i}] = {}", e.0)?; - if i + 1 < self.consts.len() as _ { - writeln!(f)?; - } - } - Ok(()) - } -} - impl LinearReg { fn into_inner(self) -> Reg { let inner = self.0; diff --git a/interpreter/src/vm.rs b/interpreter/src/vm.rs index 4a4838c..10970c7 100644 --- a/interpreter/src/vm.rs +++ b/interpreter/src/vm.rs @@ -1,3 +1,5 @@ +use std::fmt::{self, Display}; + use bumpalo::{Bump, collections::Vec}; use hashbrown::{DefaultHashBuilder, HashMap}; use indexmap::{IndexMap, IndexSet}; @@ -26,7 +28,7 @@ pub struct Interpreter<'a> { program_counter: usize, registers: Registers<'a>, symbols: SymbolTable<'a>, - consts: IndexSet, + consts: Consts, compat: ExecMode, } @@ -41,6 +43,9 @@ pub struct SymbolTable<'a> { // etc } +#[derive(Debug)] +pub struct Consts(pub IndexSet); + impl<'a> Interpreter<'a> { pub fn new(compat: ExecMode, code: Code<'a>) -> Self { Self { @@ -83,6 +88,12 @@ impl<'a> SymbolTable<'a> { } } +impl Consts { + pub fn new() -> Self { + Self(IndexSet::with_capacity(4)) + } +} + impl Interpreter<'_> { pub fn run(&mut self) { while let Some(instr) = self.bc.code.get(self.program_counter) { @@ -103,7 +114,7 @@ impl Interpreter<'_> { ix if let Some(&(dest, src)) = ix.get_load_store() => match ix.opcode { OpCode::LoadConst => self .registers - .write(dest, self.consts.get_index(src.0 as _).unwrap()), + .write(dest, self.consts.0.get_index(src.0 as _).unwrap()), OpCode::LoadUser => { self.registers .write(dest, self.symbols.lookup_user_var(src)); @@ -141,3 +152,64 @@ impl Registers<'_> { self.0[dest.0 as usize] = Value::clone(src); } } + +impl Display for Interpreter<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + writeln!(f, "{}\n", self.bc)?; + writeln!(f, "{}\n", self.registers)?; + writeln!(f, "{}\n", self.symbols)?; + write!(f, "{}", self.consts) + } +} + +impl Display for Code<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + writeln!(f, "{}\n", self.bc)?; + writeln!(f, "{}\n", self.symbols)?; + write!(f, "{}", self.consts) + } +} + +impl Display for Bytecode<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Bytecode:")?; + let n = self.code.len().checked_ilog10().unwrap_or(0) as usize + 1; + fmt_list(f, self.code.iter(), |f, i, e| write!(f, "{i:0n$}: {e}")) + } +} + +impl Display for Registers<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Registers:")?; + let n = self.0.len().checked_ilog10().unwrap_or(0) as usize + 1; + fmt_list(f, self.0.iter(), |f, i, e| write!(f, "r{i:0n$} = {e:?}")) + } +} + +impl Display for SymbolTable<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Symbols:")?; + fmt_list(f, self.user.iter(), |f, i, (k, v)| { + write!(f, "user[{i}] @ {k} = {v:?}") + }) + } +} + +impl Display for Consts { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Consts:")?; + fmt_list(f, self.0.iter(), |f, i, e| write!(f, "mem[{i}] = {e:?}")) + } +} + +fn fmt_list<'a, T: Copy>( + f: &mut fmt::Formatter<'a>, + iter: impl Iterator, + cb: impl Fn(&mut fmt::Formatter<'a>, usize, T) -> fmt::Result, +) -> fmt::Result { + for (i, e) in iter.enumerate() { + write!(f, "\n ")?; + cb(f, i, e)?; + } + Ok(()) +}