[rlox] Implement basic arithmetic ops
This commit is contained in:
@@ -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();
|
||||||
|
|||||||
@@ -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!(
|
||||||
offset: idx,
|
f,
|
||||||
op: op,
|
"{:?}",
|
||||||
chunk: &self
|
TraceInfo {
|
||||||
})?;
|
offset: idx,
|
||||||
|
op: op,
|
||||||
|
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",
|
||||||
offset: self.pc - 1,
|
TraceInfo {
|
||||||
op: instr,
|
offset: self.pc - 1,
|
||||||
chunk: chunk
|
op: instr,
|
||||||
});
|
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(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user