From 3d48558b94ebfcfab62cbfa5b6d9931f598a4991 Mon Sep 17 00:00:00 2001 From: Jeff Date: Fri, 7 Feb 2025 19:37:39 -0500 Subject: [PATCH] Add and pass new tests --- dust-lang/Cargo.toml | 4 - dust-lang/src/compiler/mod.rs | 27 ++-- dust-lang/src/vm/action.rs | 54 ++++++- dust-lang/tests/add.rs | 138 ++++++++++++++++++ .../{values/load_values.rs => values.rs} | 0 5 files changed, 204 insertions(+), 19 deletions(-) create mode 100644 dust-lang/tests/add.rs rename dust-lang/tests/{values/load_values.rs => values.rs} (100%) diff --git a/dust-lang/Cargo.toml b/dust-lang/Cargo.toml index d88f264..da8fe02 100644 --- a/dust-lang/Cargo.toml +++ b/dust-lang/Cargo.toml @@ -38,7 +38,3 @@ harness = false [[bench]] name = "threads" harness = false - -[[test]] -name = "load_values" -path = "tests/values/load_values.rs" diff --git a/dust-lang/src/compiler/mod.rs b/dust-lang/src/compiler/mod.rs index 16e9b24..865053a 100644 --- a/dust-lang/src/compiler/mod.rs +++ b/dust-lang/src/compiler/mod.rs @@ -842,20 +842,6 @@ impl<'src> Compiler<'src> { check_math_type(&left_type, operator, &left_position)?; - let destination = if is_assignment { - left.index() - } else { - match left_type { - Type::Boolean => self.next_boolean_register(), - Type::Byte => self.next_byte_register(), - Type::Character => self.next_character_register(), - Type::Float => self.next_float_register(), - Type::Integer => self.next_integer_register(), - Type::String => self.next_string_register(), - _ => unreachable!(), - } - }; - if is_assignment && !left_is_mutable_local { return Err(CompileError::ExpectedMutableVariable { found: self.previous_token.to_owned(), @@ -890,6 +876,19 @@ impl<'src> Compiler<'src> { } else { left_type.clone() }; + let destination = if is_assignment { + left.index() + } else { + match left_type { + Type::Boolean => self.next_boolean_register(), + Type::Byte => self.next_byte_register(), + Type::Character => self.next_character_register(), + Type::Float => self.next_float_register(), + Type::Integer => self.next_integer_register(), + Type::String => self.next_string_register(), + _ => unreachable!(), + } + }; let instruction = match operator { Token::Plus | Token::PlusEqual => Instruction::add(destination, left, right), Token::Minus | Token::MinusEqual => Instruction::subtract(destination, left, right), diff --git a/dust-lang/src/vm/action.rs b/dust-lang/src/vm/action.rs index 2f16638..b15a615 100644 --- a/dust-lang/src/vm/action.rs +++ b/dust-lang/src/vm/action.rs @@ -1,5 +1,5 @@ use crate::{ - AbstractList, ConcreteValue, Instruction, Value, + AbstractList, ConcreteValue, DustString, Instruction, Value, instruction::{InstructionFields, TypeCode}, }; @@ -372,6 +372,58 @@ pub fn add(instruction: InstructionFields, thread: &mut Thread) { thread.set_string_register(destination, register); } + (TypeCode::CHARACTER, TypeCode::CHARACTER) => { + let left_value = if left_is_constant { + if cfg!(debug_assertions) { + thread.get_constant(left).as_character().unwrap() + } else { + unsafe { thread.get_constant(left).as_character().unwrap_unchecked() } + } + } else { + thread.get_character_register(left) + }; + let right_value = if right_is_constant { + if cfg!(debug_assertions) { + thread.get_constant(right).as_character().unwrap() + } else { + unsafe { thread.get_constant(right).as_character().unwrap_unchecked() } + } + } else { + thread.get_character_register(right) + }; + let mut sum = DustString::new(); + + sum.push(*left_value); + sum.push(*right_value); + + let register = Register::Value(sum); + + thread.set_string_register(destination, register); + } + (TypeCode::FLOAT, TypeCode::FLOAT) => { + let left_value = if left_is_constant { + if cfg!(debug_assertions) { + thread.get_constant(left).as_float().unwrap() + } else { + unsafe { thread.get_constant(left).as_float().unwrap_unchecked() } + } + } else { + thread.get_float_register(left) + }; + let right_value = if right_is_constant { + if cfg!(debug_assertions) { + thread.get_constant(right).as_float().unwrap() + } else { + unsafe { thread.get_constant(right).as_float().unwrap_unchecked() } + } + } else { + thread.get_float_register(right) + }; + let sum = left_value + right_value; + let register = Register::Value(sum); + + thread.set_float_register(destination, register); + } _ => unimplemented!(), } } diff --git a/dust-lang/tests/add.rs b/dust-lang/tests/add.rs new file mode 100644 index 0000000..ab228f7 --- /dev/null +++ b/dust-lang/tests/add.rs @@ -0,0 +1,138 @@ +use dust_lang::{ + Chunk, ConcreteValue, DustString, FunctionType, Instruction, Operand, Span, Type, Value, + compile, instruction::TypeCode, run, +}; + +#[test] +fn add_bytes() { + let source = "0x28 + 0x02"; + let chunk = Chunk { + r#type: FunctionType { + return_type: Type::Byte, + ..FunctionType::default() + }, + instructions: vec![ + Instruction::load_encoded(0, 40, TypeCode::BYTE, false), + Instruction::load_encoded(1, 2, TypeCode::BYTE, false), + Instruction::add( + 2, + Operand::Register(0, TypeCode::BYTE), + Operand::Register(1, TypeCode::BYTE), + ), + Instruction::r#return(true, 2, TypeCode::BYTE), + ], + positions: vec![Span(0, 4), Span(7, 11), Span(5, 6), Span(11, 11)], + ..Chunk::default() + }; + let return_value = Some(Value::byte(0x2A)); + + assert_eq!(chunk, compile(source).unwrap()); + assert_eq!(return_value, run(source).unwrap()); +} + +#[test] +fn add_characters() { + let source = "'a' + 'b'"; + let chunk = Chunk { + r#type: FunctionType { + return_type: Type::String, + ..FunctionType::default() + }, + instructions: vec![ + Instruction::add( + 0, + Operand::Constant(0, TypeCode::CHARACTER), + Operand::Constant(1, TypeCode::CHARACTER), + ), + Instruction::r#return(true, 0, TypeCode::STRING), + ], + positions: vec![Span(4, 5), Span(9, 9)], + constants: vec![ConcreteValue::Character('a'), ConcreteValue::Character('b')], + ..Chunk::default() + }; + let return_value = Some(Value::string("ab")); + + assert_eq!(chunk, compile(source).unwrap()); + assert_eq!(return_value, run(source).unwrap()); +} + +#[test] +fn add_floats() { + let source = "2.40 + 40.02"; + let chunk = Chunk { + r#type: FunctionType { + return_type: Type::Float, + ..FunctionType::default() + }, + instructions: vec![ + Instruction::add( + 0, + Operand::Constant(0, TypeCode::FLOAT), + Operand::Constant(1, TypeCode::FLOAT), + ), + Instruction::r#return(true, 0, TypeCode::FLOAT), + ], + positions: vec![Span(0, 4), Span(7, 11), Span(5, 6), Span(11, 11)], + constants: vec![ConcreteValue::Float(2.40), ConcreteValue::Float(40.02)], + ..Chunk::default() + }; + let return_value = Some(Value::float(42.42)); + + assert_eq!(chunk, compile(source).unwrap()); + assert_eq!(return_value, run(source).unwrap()); +} + +#[test] +fn add_integers() { + let source = "40 + 2"; + let chunk = Chunk { + r#type: FunctionType { + return_type: Type::Integer, + ..FunctionType::default() + }, + instructions: vec![ + Instruction::add( + 0, + Operand::Constant(0, TypeCode::INTEGER), + Operand::Constant(1, TypeCode::INTEGER), + ), + Instruction::r#return(true, 0, TypeCode::INTEGER), + ], + positions: vec![Span(3, 4), Span(7, 7)], + constants: vec![ConcreteValue::Integer(40), ConcreteValue::Integer(2)], + ..Chunk::default() + }; + let return_value = Some(Value::integer(42)); + + assert_eq!(chunk, compile(source).unwrap()); + assert_eq!(return_value, run(source).unwrap()); +} + +#[test] +fn add_strings() { + let source = "\"Hello, \" + \"World!\""; + let chunk = Chunk { + r#type: FunctionType { + return_type: Type::String, + ..FunctionType::default() + }, + instructions: vec![ + Instruction::add( + 0, + Operand::Constant(0, TypeCode::STRING), + Operand::Constant(1, TypeCode::STRING), + ), + Instruction::r#return(true, 0, TypeCode::STRING), + ], + positions: vec![Span(0, 8), Span(11, 18), Span(9, 10), Span(19, 25)], + constants: vec![ + ConcreteValue::String(DustString::from("Hello, ")), + ConcreteValue::String(DustString::from("World!")), + ], + ..Chunk::default() + }; + let return_value = Some(Value::string("Hello, World!")); + + assert_eq!(chunk, compile(source).unwrap()); + assert_eq!(return_value, run(source).unwrap()); +} diff --git a/dust-lang/tests/values/load_values.rs b/dust-lang/tests/values.rs similarity index 100% rename from dust-lang/tests/values/load_values.rs rename to dust-lang/tests/values.rs