chore(interpreter): better formatting

This commit is contained in:
Guillem L. Jara
2026-05-25 01:11:03 +02:00
parent 8b29b26050
commit 8e979cfad1
2 changed files with 81 additions and 38 deletions
+7 -36
View File
@@ -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<Value>,
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<UnaryOperator> 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;
+74 -2
View File
@@ -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<Value>,
consts: Consts,
compat: ExecMode,
}
@@ -41,6 +43,9 @@ pub struct SymbolTable<'a> {
// etc
}
#[derive(Debug)]
pub struct Consts(pub IndexSet<Value>);
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<Item = T>,
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(())
}