1
0

Add new tests

This commit is contained in:
Jeff 2025-02-08 11:21:29 -05:00
parent dc2acbfe46
commit dcea611a0b
5 changed files with 225 additions and 18 deletions

View File

@ -42,3 +42,7 @@ harness = false
[[test]]
name = "add"
path = "tests/math/add.rs"
[[test]]
name = "subtract"
path = "tests/math/subtract.rs"

View File

@ -924,8 +924,9 @@ impl<'src> Compiler<'src> {
});
}
};
let position = Span(left_position.0, right_position.1);
self.emit_instruction(instruction, r#type, operator_position);
self.emit_instruction(instruction, r#type, position);
Ok(())
}

View File

@ -441,6 +441,30 @@ pub fn add(instruction: InstructionFields, thread: &mut Thread) {
thread.set_byte_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);
}
(TypeCode::STRING, TypeCode::STRING) => {
let left_value = if left_is_constant {
if cfg!(debug_assertions) {
@ -505,29 +529,65 @@ pub fn add(instruction: InstructionFields, thread: &mut Thread) {
thread.set_string_register(destination, register);
}
(TypeCode::FLOAT, TypeCode::FLOAT) => {
(TypeCode::STRING, TypeCode::CHARACTER) => {
let left_value = if left_is_constant {
if cfg!(debug_assertions) {
thread.get_constant(left).as_float().unwrap()
thread.get_constant(left).as_string().unwrap().clone()
} else {
unsafe { thread.get_constant(left).as_float().unwrap_unchecked() }
unsafe {
thread
.get_constant(left)
.as_string()
.unwrap_unchecked()
.clone()
}
}
} else {
thread.get_float_register(left)
thread.get_string_register(left).clone()
};
let right_value = if right_is_constant {
if cfg!(debug_assertions) {
thread.get_constant(right).as_float().unwrap()
thread.get_constant(right).as_character().unwrap()
} else {
unsafe { thread.get_constant(right).as_float().unwrap_unchecked() }
unsafe { thread.get_constant(right).as_character().unwrap_unchecked() }
}
} else {
thread.get_float_register(right)
thread.get_character_register(right)
};
let sum = left_value + right_value;
let mut sum = left_value.clone();
sum.push(*right_value);
let register = Register::Value(sum);
thread.set_float_register(destination, register);
thread.set_string_register(destination, register);
}
(TypeCode::CHARACTER, TypeCode::STRING) => {
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_string().unwrap()
} else {
unsafe { thread.get_constant(right).as_string().unwrap_unchecked() }
}
} else {
thread.get_string_register(right)
};
let mut sum = right_value.clone();
sum.insert(0, *left_value);
let register = Register::Value(sum);
thread.set_string_register(destination, register);
}
_ => unimplemented!(),
}

View File

@ -18,7 +18,7 @@ fn add_bytes() {
),
Instruction::r#return(true, 2, TypeCode::BYTE),
],
positions: vec![Span(0, 4), Span(7, 11), Span(5, 6), Span(11, 11)],
positions: vec![Span(0, 4), Span(7, 11), Span(0, 11), Span(11, 11)],
..Chunk::default()
};
let return_value = Some(Value::byte(0x2A));
@ -57,11 +57,11 @@ fn add_many_bytes() {
positions: vec![
Span(0, 4),
Span(7, 11),
Span(5, 6),
Span(0, 11),
Span(14, 18),
Span(12, 13),
Span(0, 18),
Span(21, 25),
Span(19, 20),
Span(0, 25),
Span(25, 25),
],
..Chunk::default()
@ -85,7 +85,7 @@ fn add_characters() {
),
Instruction::r#return(true, 0, TypeCode::STRING),
],
positions: vec![Span(4, 5), Span(9, 9)],
positions: vec![Span(0, 9), Span(9, 9)],
constants: vec![ConcreteValue::Character('a'), ConcreteValue::Character('b')],
..Chunk::default()
};
@ -95,6 +95,44 @@ fn add_characters() {
assert_eq!(return_value, run(source).unwrap());
}
#[test]
fn add_many_characters() {
let source = "'a' + 'b' + 'c' + 'd'";
let chunk = Chunk {
r#type: FunctionType::new([], [], Type::String),
instructions: vec![
Instruction::add(
0,
Operand::Constant(0, TypeCode::CHARACTER),
Operand::Constant(1, TypeCode::CHARACTER),
),
Instruction::add(
1,
Operand::Register(0, TypeCode::STRING),
Operand::Constant(2, TypeCode::CHARACTER),
),
Instruction::add(
2,
Operand::Register(1, TypeCode::STRING),
Operand::Constant(3, TypeCode::CHARACTER),
),
Instruction::r#return(true, 2, TypeCode::STRING),
],
positions: vec![Span(0, 9), Span(0, 15), Span(0, 21), Span(21, 21)],
constants: vec![
ConcreteValue::Character('a'),
ConcreteValue::Character('b'),
ConcreteValue::Character('c'),
ConcreteValue::Character('d'),
],
..Chunk::default()
};
let return_value = Some(Value::string("abcd"));
assert_eq!(chunk, compile(source).unwrap());
assert_eq!(return_value, run(source).unwrap());
}
#[test]
fn add_floats() {
let source = "2.40 + 40.02";
@ -108,7 +146,7 @@ fn add_floats() {
),
Instruction::r#return(true, 0, TypeCode::FLOAT),
],
positions: vec![Span(5, 6), Span(12, 12)],
positions: vec![Span(0, 12), Span(12, 12)],
constants: vec![ConcreteValue::Float(2.40), ConcreteValue::Float(40.02)],
..Chunk::default()
};
@ -118,6 +156,39 @@ fn add_floats() {
assert_eq!(return_value, run(source).unwrap());
}
#[test]
fn add_many_floats() {
let source = "2.40 + 40.02 + 2.40 + 40.02";
let chunk = Chunk {
r#type: FunctionType::new([], [], Type::Float),
instructions: vec![
Instruction::add(
0,
Operand::Constant(0, TypeCode::FLOAT),
Operand::Constant(1, TypeCode::FLOAT),
),
Instruction::add(
1,
Operand::Register(0, TypeCode::FLOAT),
Operand::Constant(0, TypeCode::FLOAT),
),
Instruction::add(
2,
Operand::Register(1, TypeCode::FLOAT),
Operand::Constant(1, TypeCode::FLOAT),
),
Instruction::r#return(true, 2, TypeCode::FLOAT),
],
positions: vec![Span(0, 12), Span(0, 19), Span(0, 27), Span(27, 27)],
constants: vec![ConcreteValue::Float(2.40), ConcreteValue::Float(40.02)],
..Chunk::default()
};
let return_value = Some(Value::float(84.84));
assert_eq!(chunk, compile(source).unwrap());
assert_eq!(return_value, run(source).unwrap());
}
#[test]
fn add_integers() {
let source = "40 + 2";
@ -131,7 +202,7 @@ fn add_integers() {
),
Instruction::r#return(true, 0, TypeCode::INTEGER),
],
positions: vec![Span(3, 4), Span(6, 6)],
positions: vec![Span(0, 6), Span(6, 6)],
constants: vec![ConcreteValue::Integer(40), ConcreteValue::Integer(2)],
..Chunk::default()
};
@ -141,6 +212,39 @@ fn add_integers() {
assert_eq!(return_value, run(source).unwrap());
}
#[test]
fn add_many_integers() {
let source = "40 + 2 + 40 + 2";
let chunk = Chunk {
r#type: FunctionType::new([], [], Type::Integer),
instructions: vec![
Instruction::add(
0,
Operand::Constant(0, TypeCode::INTEGER),
Operand::Constant(1, TypeCode::INTEGER),
),
Instruction::add(
1,
Operand::Register(0, TypeCode::INTEGER),
Operand::Constant(0, TypeCode::INTEGER),
),
Instruction::add(
2,
Operand::Register(1, TypeCode::INTEGER),
Operand::Constant(1, TypeCode::INTEGER),
),
Instruction::r#return(true, 2, TypeCode::INTEGER),
],
positions: vec![Span(0, 6), Span(0, 11), Span(0, 15), Span(15, 15)],
constants: vec![ConcreteValue::Integer(40), ConcreteValue::Integer(2)],
..Chunk::default()
};
let return_value = Some(Value::integer(84));
assert_eq!(chunk, compile(source).unwrap());
assert_eq!(return_value, run(source).unwrap());
}
#[test]
fn add_strings() {
let source = "\"Hello, \" + \"World!\"";
@ -154,7 +258,7 @@ fn add_strings() {
),
Instruction::r#return(true, 0, TypeCode::STRING),
],
positions: vec![Span(10, 11), Span(20, 20)],
positions: vec![Span(0, 20), Span(20, 20)],
constants: vec![
ConcreteValue::String(DustString::from("Hello, ")),
ConcreteValue::String(DustString::from("World!")),
@ -166,3 +270,41 @@ fn add_strings() {
assert_eq!(chunk, compile(source).unwrap());
assert_eq!(return_value, run(source).unwrap());
}
#[test]
fn add_many_strings() {
let source = "\"foo\" + \"bar\" + \"baz\" + \"buzz\"";
let chunk = Chunk {
r#type: FunctionType::new([], [], Type::String),
instructions: vec![
Instruction::add(
0,
Operand::Constant(0, TypeCode::STRING),
Operand::Constant(1, TypeCode::STRING),
),
Instruction::add(
1,
Operand::Register(0, TypeCode::STRING),
Operand::Constant(2, TypeCode::STRING),
),
Instruction::add(
2,
Operand::Register(1, TypeCode::STRING),
Operand::Constant(3, TypeCode::STRING),
),
Instruction::r#return(true, 2, TypeCode::STRING),
],
positions: vec![Span(0, 13), Span(0, 21), Span(0, 30), Span(30, 30)],
constants: vec![
ConcreteValue::String(DustString::from("foo")),
ConcreteValue::String(DustString::from("bar")),
ConcreteValue::String(DustString::from("baz")),
ConcreteValue::String(DustString::from("buzz")),
],
..Chunk::default()
};
let return_value = Some(Value::string("foobarbazbuzz"));
assert_eq!(chunk, compile(source).unwrap());
assert_eq!(return_value, run(source).unwrap());
}

View File