diff --git a/dust-lang/src/parser/tests.rs b/dust-lang/src/parser/tests.rs index e39fa00..f0c82cb 100644 --- a/dust-lang/src/parser/tests.rs +++ b/dust-lang/src/parser/tests.rs @@ -2,37 +2,6 @@ use crate::Local; use super::*; -#[test] -fn comparison_chain() { - let source = "1 == 2 > 3 < 4 != 5;"; - - assert_eq!( - parse(source), - Ok(Chunk::with_data( - vec![ - ( - *Instruction::equal(true, 0, 1) - .set_first_argument_to_constant() - .set_second_argument_to_constant(), - Span(2, 4) - ), - (Instruction::jump(1, true), Span(2, 4)), - ( - *Instruction::equal(true, 1, 2) - .set_first_argument_to_constant() - .set_second_argument_to_constant(), - Span(7, 9) - ), - (Instruction::jump(1, true), Span(7, 9)), - (Instruction::load_boolean(0, true, true), Span(2, 4)), - (Instruction::load_boolean(0, false, false), Span(2, 4)), - ], - vec![Value::integer(1), Value::integer(2), Value::integer(3)], - vec![] - )), - ); -} - #[test] fn not() { let source = "!true"; diff --git a/dust-lang/src/vm.rs b/dust-lang/src/vm.rs index e474171..17c710e 100644 --- a/dust-lang/src/vm.rs +++ b/dust-lang/src/vm.rs @@ -38,16 +38,16 @@ impl Vm { pub fn run(&mut self) -> Result, VmError> { // DRY helper to take constants or clone registers for binary operations - fn take_constants_or_clone( + fn get_arguments( vm: &mut Vm, instruction: Instruction, position: Span, - ) -> Result<(Value, &Value), VmError> { + ) -> Result<(&Value, &Value), VmError> { let left = if instruction.first_argument_is_constant() { vm.chunk - .take_constant(instruction.first_argument(), position)? + .get_constant(instruction.first_argument(), position)? } else { - vm.clone(instruction.first_argument(), position)? + vm.get(instruction.first_argument(), position)? }; let right = if instruction.second_argument_is_constant() { vm.chunk @@ -66,7 +66,7 @@ impl Vm { Operation::Move => { let from = instruction.first_argument(); let to = instruction.destination(); - let value = self.clone(from, position)?; + let value = self.take(from, position)?; self.insert(value, to, position)?; } @@ -149,7 +149,7 @@ impl Vm { self.insert(value, register_index, position)?; } Operation::Add => { - let (left, right) = take_constants_or_clone(self, instruction, position)?; + let (left, right) = get_arguments(self, instruction, position)?; let sum = left .add(right) .map_err(|error| VmError::Value { error, position })?; @@ -157,7 +157,7 @@ impl Vm { self.insert(sum, instruction.destination(), position)?; } Operation::Subtract => { - let (left, right) = take_constants_or_clone(self, instruction, position)?; + let (left, right) = get_arguments(self, instruction, position)?; let difference = left .subtract(right) .map_err(|error| VmError::Value { error, position })?; @@ -165,7 +165,7 @@ impl Vm { self.insert(difference, instruction.destination(), position)?; } Operation::Multiply => { - let (left, right) = take_constants_or_clone(self, instruction, position)?; + let (left, right) = get_arguments(self, instruction, position)?; let product = left .multiply(right) .map_err(|error| VmError::Value { error, position })?; @@ -173,7 +173,7 @@ impl Vm { self.insert(product, instruction.destination(), position)?; } Operation::Divide => { - let (left, right) = take_constants_or_clone(self, instruction, position)?; + let (left, right) = get_arguments(self, instruction, position)?; let quotient = left .divide(right) .map_err(|error| VmError::Value { error, position })?; @@ -181,7 +181,7 @@ impl Vm { self.insert(quotient, instruction.destination(), position)?; } Operation::Modulo => { - let (left, right) = take_constants_or_clone(self, instruction, position)?; + let (left, right) = get_arguments(self, instruction, position)?; let remainder = left .modulo(right) .map_err(|error| VmError::Value { error, position })?; @@ -191,9 +191,9 @@ impl Vm { Operation::Test => { let register = instruction.destination(); let test_value = instruction.second_argument_as_boolean(); - let value = self.clone(register, position)?; + let value = self.get(register, position)?; let boolean = value.as_boolean().ok_or_else(|| VmError::ExpectedBoolean { - found: value, + found: value.clone(), position, })?; @@ -218,7 +218,7 @@ impl Vm { } } Operation::Equal => { - let (left, right) = take_constants_or_clone(self, instruction, position)?; + let (left, right) = get_arguments(self, instruction, position)?; let equal = left .equal(right) .map_err(|error| VmError::Value { error, position })?; @@ -231,27 +231,27 @@ impl Vm { } } Operation::Less => { - let (left, right) = take_constants_or_clone(self, instruction, position)?; + let (left, right) = get_arguments(self, instruction, position)?; let less = left .less_than(right) .map_err(|error| VmError::Value { error, position })?; let compare_to = instruction.destination() != 0; if let Some(boolean) = less.as_boolean() { - if boolean != compare_to { + if boolean == compare_to { self.ip += 1; } } } Operation::LessEqual => { - let (left, right) = take_constants_or_clone(self, instruction, position)?; + let (left, right) = get_arguments(self, instruction, position)?; let less_equal = left .less_than_or_equal(right) .map_err(|error| VmError::Value { error, position })?; let compare_to = instruction.destination() != 0; if let Some(boolean) = less_equal.as_boolean() { - if boolean != compare_to { + if boolean == compare_to { self.ip += 1; } } @@ -259,9 +259,9 @@ impl Vm { Operation::Negate => { let value = if instruction.first_argument_is_constant() { self.chunk - .take_constant(instruction.first_argument(), position)? + .get_constant(instruction.first_argument(), position)? } else { - self.clone(instruction.first_argument(), position)? + self.get(instruction.first_argument(), position)? }; let negated = value .negate() @@ -272,9 +272,9 @@ impl Vm { Operation::Not => { let value = if instruction.first_argument_is_constant() { self.chunk - .take_constant(instruction.first_argument(), position)? + .get_constant(instruction.first_argument(), position)? } else { - self.clone(instruction.first_argument(), position)? + self.get(instruction.first_argument(), position)? }; let not = value .not() diff --git a/dust-lang/tests/operations.rs b/dust-lang/tests/operations.rs index 3d33c76..a76292e 100644 --- a/dust-lang/tests/operations.rs +++ b/dust-lang/tests/operations.rs @@ -1,5 +1,59 @@ use dust_lang::*; +#[test] +fn less_than() { + assert_eq!(run("1 < 2"), Ok(Some(Value::boolean(true)))); +} + +#[test] +fn greater_than() { + assert_eq!(run("1 > 2"), Ok(Some(Value::boolean(false)))); +} + +#[test] +fn less_than_or_equal() { + assert_eq!(run("1 <= 2"), Ok(Some(Value::boolean(true)))); + assert_eq!(run("1 <= 1"), Ok(Some(Value::boolean(true)))); +} + +#[test] +fn greater_than_or_equal() { + assert_eq!(run("1 >= 2"), Ok(Some(Value::boolean(false)))); + assert_eq!(run("1 >= 1"), Ok(Some(Value::boolean(true)))); +} + +#[test] +fn equal() { + assert_eq!(run("1 == 1"), Ok(Some(Value::boolean(true)))); +} + +#[test] +fn not_equal() { + assert_eq!(run("1 != 1"), Ok(Some(Value::boolean(false)))); +} + +#[test] +fn and() { + assert_eq!(run("true && true"), Ok(Some(Value::boolean(true)))); + assert_eq!(run("true && false"), Ok(Some(Value::boolean(false)))); + assert_eq!(run("false && true"), Ok(Some(Value::boolean(false)))); + assert_eq!(run("false && false"), Ok(Some(Value::boolean(false)))); +} + +#[test] +fn or() { + assert_eq!(run("true || true"), Ok(Some(Value::boolean(true)))); + assert_eq!(run("true || false"), Ok(Some(Value::boolean(true)))); + assert_eq!(run("false || true"), Ok(Some(Value::boolean(true)))); + assert_eq!(run("false || false"), Ok(Some(Value::boolean(false)))); +} + +#[test] +fn not() { + assert_eq!(run("!true"), Ok(Some(Value::boolean(false)))); + assert_eq!(run("!false"), Ok(Some(Value::boolean(true)))); +} + #[test] fn long_math() { assert_eq!(