[rlox] Implement basic arithmetic ops

This commit is contained in:
ctsk
2023-04-04 19:03:57 +02:00
parent c0447cf7ab
commit d227e3d3ba
2 changed files with 67 additions and 24 deletions

View File

@@ -2,10 +2,32 @@ mod vm;
fn main() { fn main() {
let mut chunk = vm::Chunk::new("TEST".to_string()); let mut chunk = vm::Chunk::new("TEST".to_string());
chunk.add_constant(vm::Value::from(3.14)); chunk.add_constant(vm::Value::from(3.));
chunk.add_constant(vm::Value::from(7.));
chunk.add_constant(vm::Value::from(11.));
chunk.add_constant(vm::Value::from(17.));
chunk.add_constant(vm::Value::from(500.));
chunk.add_constant(vm::Value::from(1000.));
chunk.add_constant(vm::Value::from(250.));
chunk.add_op(vm::Op::Constant { offset: 0 }, 1); chunk.add_op(vm::Op::Constant { offset: 0 }, 1);
chunk.add_op(vm::Op::Constant { offset: 1 }, 1);
chunk.add_op(vm::Op::Multiply, 1);
chunk.add_op(vm::Op::Constant { offset: 2 }, 1);
chunk.add_op(vm::Op::Constant { offset: 3 }, 1);
chunk.add_op(vm::Op::Multiply, 1);
chunk.add_op(vm::Op::Multiply, 1);
chunk.add_op(vm::Op::Negate, 1); chunk.add_op(vm::Op::Negate, 1);
chunk.add_op(vm::Op::Return, 1); chunk.add_op(vm::Op::Constant { offset: 4 }, 2);
chunk.add_op(vm::Op::Constant { offset: 5 }, 2);
chunk.add_op(vm::Op::Add, 2);
chunk.add_op(vm::Op::Constant { offset: 6 }, 2);
chunk.add_op(vm::Op::Subtract, 2);
chunk.add_op(vm::Op::Negate, 2);
chunk.add_op(vm::Op::Divide, 2);
chunk.add_op(vm::Op::Return, 3);
println!("{:?}", chunk); println!("{:?}", chunk);
let mut interpreter = vm::VM::new(); let mut interpreter = vm::VM::new();

View File

@@ -7,6 +7,10 @@ pub enum Op {
Return, Return,
Constant { offset: usize }, Constant { offset: usize },
Negate, Negate,
Add,
Subtract,
Multiply,
Divide,
} }
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
@@ -46,7 +50,6 @@ impl Chunk {
pub fn add_op(&mut self, op: Op, line: usize) { pub fn add_op(&mut self, op: Op, line: usize) {
self.code.push(op); self.code.push(op);
self.debug_info.push(line); self.debug_info.push(line);
} }
pub fn add_constant(&mut self, value: Value) { pub fn add_constant(&mut self, value: Value) {
@@ -58,11 +61,15 @@ impl fmt::Debug for Chunk {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
writeln!(f, "-*-*- {} -*-*-", self.name)?; writeln!(f, "-*-*- {} -*-*-", self.name)?;
for (idx, op) in self.code.iter().copied().enumerate() { for (idx, op) in self.code.iter().copied().enumerate() {
writeln!(f, "{:?}", TraceInfo { writeln!(
f,
"{:?}",
TraceInfo {
offset: idx, offset: idx,
op: op, op: op,
chunk: &self chunk: &self
})?; }
)?;
} }
return Ok(()); return Ok(());
@@ -72,7 +79,7 @@ impl fmt::Debug for Chunk {
struct TraceInfo<'a> { struct TraceInfo<'a> {
offset: usize, offset: usize,
op: Op, op: Op,
chunk: &'a Chunk chunk: &'a Chunk,
} }
impl fmt::Debug for TraceInfo<'_> { impl fmt::Debug for TraceInfo<'_> {
@@ -85,20 +92,22 @@ impl fmt::Debug for TraceInfo<'_> {
let line = chunk.debug_info[offset]; let line = chunk.debug_info[offset];
if offset > 0 && chunk.debug_info[offset-1] == line { if offset > 0 && chunk.debug_info[offset - 1] == line {
write!(f, " | ") write!(f, " | ")
} else { } else {
write!(f, "{:4} ", line) write!(f, "{:4} ", line)
}?; }?;
match op { match op {
Op::Return | Op::Negate => write!(f, "{:?}", op), Op::Return | Op::Negate | Op::Add | Op::Subtract | Op::Multiply | Op::Divide => {
write!(f, "{:?}", op)
}
Op::Constant { offset } => { Op::Constant { offset } => {
f.debug_struct("Constant") f.debug_struct("Constant")
.field("val", &chunk.constants[offset].val) .field("val", &chunk.constants[offset].val)
.finish()?; .finish()?;
write!(f, "") write!(f, "")
}, }
} }
} }
} }
@@ -112,7 +121,7 @@ pub struct VM {
#[derive(Debug)] #[derive(Debug)]
pub enum VMError { pub enum VMError {
Compile, Compile,
Runtime Runtime,
} }
impl VM { impl VM {
@@ -144,29 +153,41 @@ impl VM {
} }
println!("_ ]\n"); println!("_ ]\n");
println!(
println!("{:?}\n", TraceInfo { "{:?}\n",
TraceInfo {
offset: self.pc - 1, offset: self.pc - 1,
op: instr, op: instr,
chunk: chunk chunk: chunk
}); }
);
} }
match instr { match instr {
Op::Return => { Op::Return => {
print!("{:?}", self.pop()?); print!("{:?}", self.pop()?);
return Ok(()) return Ok(());
},
Op::Constant { offset } => {
self.push(chunk.constants[offset])
} }
Op::Constant { offset } => self.push(chunk.constants[offset]),
Op::Negate => { Op::Negate => {
let new_val = -self.pop()?.val; let new_val = -self.pop()?.val;
self.push(Value::from(new_val)); self.push(Value::from(new_val));
} }
Op::Add | Op::Subtract | Op::Multiply | Op::Divide => {
let b = self.pop()?;
let a = self.pop()?;
let r = match instr {
Op::Add => a.val + b.val,
Op::Subtract => a.val - b.val,
Op::Multiply => a.val * b.val,
Op::Divide => a.val / b.val,
_ => unreachable!()
};
self.push(Value::from(r))
}
} }
} }
return Ok(()) return Ok(());
} }
} }