Files
crafting-interpreters/rlox/src/vm.rs

131 lines
2.8 KiB
Rust
Raw Normal View History

2023-03-29 21:15:41 +02:00
use std::convert::From;
2023-03-29 20:03:16 +02:00
use std::fmt;
2023-03-29 20:07:31 +02:00
#[repr(u8)]
2023-03-29 21:15:41 +02:00
#[derive(Copy, Clone, Debug)]
2023-03-29 20:07:31 +02:00
pub enum Op {
2023-03-29 21:15:41 +02:00
Return,
Constant { offset: usize },
}
2023-03-30 11:49:38 +02:00
#[derive(Copy, Clone)]
2023-03-29 21:15:41 +02:00
pub struct Value {
val: f64,
}
2023-03-30 11:49:38 +02:00
impl fmt::Debug for Value {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
write!(f, "{}", self.val)
}
}
2023-03-29 21:15:41 +02:00
impl From<f64> for Value {
fn from(value: f64) -> Self {
Value { val: value }
}
2023-03-29 20:07:31 +02:00
}
2023-03-29 20:03:16 +02:00
pub struct Chunk {
code: Vec<Op>,
2023-03-29 21:15:41 +02:00
name: String,
debug_info: Vec<usize>,
constants: Vec<Value>,
2023-03-29 20:03:16 +02:00
}
impl Chunk {
2023-03-29 21:15:41 +02:00
pub fn new(name: String) -> Self {
2023-03-29 20:03:16 +02:00
Chunk {
code: Vec::new(),
2023-03-29 21:15:41 +02:00
name: name,
debug_info: Vec::new(),
constants: Vec::new(),
2023-03-29 20:03:16 +02:00
}
}
2023-03-29 21:15:41 +02:00
pub fn add_op(&mut self, op: Op, line: usize) {
self.code.push(op);
self.debug_info.push(line);
}
pub fn add_constant(&mut self, value: Value) {
self.constants.push(value);
2023-03-29 20:03:16 +02:00
}
}
impl fmt::Debug for Chunk {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
writeln!(f, "-*-*- {} -*-*-", self.name)?;
2023-03-29 21:15:41 +02:00
for (idx, op) in self.code.iter().copied().enumerate() {
write!(f, "{:04} ", idx)?;
let line = self.debug_info[idx];
if idx > 0 && self.debug_info[idx-1] == line {
2023-03-30 11:49:38 +02:00
write!(f, " | ")
2023-03-29 21:15:41 +02:00
} else {
2023-03-30 11:49:38 +02:00
write!(f, "{:4} ", line)
}?;
2023-03-29 21:15:41 +02:00
match op {
Op::Return => writeln!(f, "{:?}", op),
Op::Constant { offset } =>
f.debug_struct("Constant")
.field("val", &self.constants[offset].val)
.finish(),
}?;
2023-03-29 20:03:16 +02:00
}
return Ok(());
}
}
2023-03-30 11:49:38 +02:00
const VM_STACK_SIZE: usize = 256;
struct VM {
trace: bool,
stack: Vec<Value>,
code: Chunk
}
enum VMError {
Compile,
Runtime
}
impl VM {
fn push(&mut self, value: Value) {
self.stack.push(value);
}
fn pop(&mut self) -> Value {
self.stack.pop().unwrap()
}
pub fn interpret(&mut self, chunk: &Chunk) -> Result<(), VMError> {
for instr in chunk.code.iter().copied() {
if self.trace {
print!(" [");
for value in self.stack.iter() {
println!("{:?} | ", value);
}
println!("_ ]");
println!("{:?}", instr);
}
match instr {
Op::Return => {
print!("{:?}", self.pop());
return Ok(())
},
Op::Constant { offset } => {
self.push(self.code.constants[offset])
}
}
}
return Ok(())
}
}