Add binary operations
This commit is contained in:
parent
1ecaac0819
commit
3c2e3699ab
@ -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))));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user