1
0

Add binary operations

This commit is contained in:
Jeff 2024-09-06 19:37:12 -04:00
parent 1ecaac0819
commit 3c2e3699ab

View File

@ -30,15 +30,51 @@ impl Vm {
self.stack.push(value.clone()); self.stack.push(value.clone());
} }
Instruction::Return => {
let value = self.pop()?;
return Ok(Some(value));
}
// Unary
Instruction::Negate => { Instruction::Negate => {
let negated = self.pop()?.negate()?; let negated = self.pop()?.negate()?;
self.stack.push(negated); self.stack.push(negated);
} }
Instruction::Return => {
let value = self.pop()?;
return Ok(Some(value)); // Binary
Instruction::Add => {
let b = self.pop()?;
let a = self.pop()?;
let sum = a.add(&b)?;
self.stack.push(sum);
}
Instruction::Subtract => {
let b = self.pop()?;
let a = self.pop()?;
let difference = a.subtract(&b)?;
self.stack.push(difference);
}
Instruction::Multiply => {
let b = self.pop()?;
let a = self.pop()?;
let product = a.multiply(&b)?;
self.stack.push(product);
}
Instruction::Divide => {
let b = self.pop()?;
let a = self.pop()?;
let quotient = a.divide(&b)?;
self.stack.push(quotient);
} }
} }
@ -91,8 +127,16 @@ impl From<ValueError> for VmError {
#[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)] #[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)]
pub enum Instruction { pub enum Instruction {
Constant(usize), Constant(usize),
Negate,
Return, Return,
// Unary
Negate,
// Binary
Add,
Subtract,
Multiply,
Divide,
} }
impl Instruction { impl Instruction {
@ -103,8 +147,16 @@ impl Instruction {
format!("{:04} CONSTANT {} {}", offset, index, value) format!("{:04} CONSTANT {} {}", offset, index, value)
} }
Instruction::Negate => format!("{:04} NEGATE", offset),
Instruction::Return => format!("{:04} RETURN", offset), Instruction::Return => format!("{:04} RETURN", offset),
// Unary
Instruction::Negate => format!("{:04} NEGATE", offset),
// Binary
Instruction::Add => format!("{:04} ADD", offset),
Instruction::Subtract => format!("{:04} SUBTRACT", offset),
Instruction::Multiply => format!("{:04} MULTIPLY", offset),
Instruction::Divide => format!("{:04} DIVIDE", offset),
} }
} }
} }
@ -183,4 +235,73 @@ pub mod tests {
assert_eq!(result, Ok(Some(Value::integer(-42)))); assert_eq!(result, Ok(Some(Value::integer(-42))));
} }
#[test]
fn addition() {
let mut chunk = Chunk::new();
let left = chunk.push_constant(Value::integer(42));
let right = chunk.push_constant(Value::integer(23));
chunk.write(Instruction::Constant(left), Span(0, 1));
chunk.write(Instruction::Constant(right), Span(2, 3));
chunk.write(Instruction::Add, Span(4, 5));
chunk.write(Instruction::Return, Span(6, 7));
let mut vm = Vm::new(chunk);
let result = vm.interpret();
assert_eq!(result, Ok(Some(Value::integer(65))));
}
#[test]
fn subtraction() {
let mut chunk = Chunk::new();
let left = chunk.push_constant(Value::integer(42));
let right = chunk.push_constant(Value::integer(23));
chunk.write(Instruction::Constant(left), Span(0, 1));
chunk.write(Instruction::Constant(right), Span(2, 3));
chunk.write(Instruction::Subtract, Span(4, 5));
chunk.write(Instruction::Return, Span(6, 7));
let mut vm = Vm::new(chunk);
let result = vm.interpret();
assert_eq!(result, Ok(Some(Value::integer(19))));
}
#[test]
fn multiplication() {
let mut chunk = Chunk::new();
let left = chunk.push_constant(Value::integer(42));
let right = chunk.push_constant(Value::integer(23));
chunk.write(Instruction::Constant(left), Span(0, 1));
chunk.write(Instruction::Constant(right), Span(2, 3));
chunk.write(Instruction::Multiply, Span(4, 5));
chunk.write(Instruction::Return, Span(6, 7));
let mut vm = Vm::new(chunk);
let result = vm.interpret();
assert_eq!(result, Ok(Some(Value::integer(966))));
}
#[test]
fn division() {
let mut chunk = Chunk::new();
let left = chunk.push_constant(Value::integer(42));
let right = chunk.push_constant(Value::integer(23));
chunk.write(Instruction::Constant(left), Span(0, 1));
chunk.write(Instruction::Constant(right), Span(2, 3));
chunk.write(Instruction::Divide, Span(4, 5));
chunk.write(Instruction::Return, Span(6, 7));
let mut vm = Vm::new(chunk);
let result = vm.interpret();
assert_eq!(result, Ok(Some(Value::integer(1))));
}
} }