1
0

Add new "add" tests; Allow adding strings to characters and visa versa

This commit is contained in:
Jeff 2024-12-03 14:12:40 -05:00
parent 31a41581eb
commit 544edaf5f4
3 changed files with 91 additions and 13 deletions

View File

@ -629,20 +629,16 @@ impl<'src> Compiler<'src> {
};
let operator = self.current_token;
let operator_position = self.current_position;
Compiler::expect_addable_type(&left_type, &left_position)?;
let rule = ParseRule::from(&operator);
let is_assignment = matches!(
operator,
Token::PlusEqual | Token::MinusEqual | Token::StarEqual | Token::SlashEqual
);
let r#type = if is_assignment {
Type::None
} else {
left_type.clone()
};
if push_back_left {
self.instructions
.push((left_instruction, left_type.clone(), left_position));
}
if is_assignment && !left_is_mutable_local {
return Err(CompileError::ExpectedMutableVariable {
@ -651,10 +647,15 @@ impl<'src> Compiler<'src> {
});
}
if push_back_left {
self.instructions
.push((left_instruction, left_type.clone(), left_position));
}
Compiler::expect_addable_type(&left_type, &left_position)?;
let r#type = if is_assignment {
Type::None
} else if left_type == Type::Character {
Type::String
} else {
left_type.clone()
};
self.advance()?;
self.parse_sub_expression(&rule.precedence)?;
@ -1628,9 +1629,11 @@ impl<'src> Compiler<'src> {
) -> Result<(), CompileError> {
if matches!(
(left, right),
(Type::Character, Type::Character)
(Type::Character, Type::String)
| (Type::Character, Type::Character)
| (Type::Float, Type::Float)
| (Type::Integer, Type::Integer)
| (Type::String, Type::Character)
| (Type::String, Type::String),
) {
Ok(())

View File

@ -70,9 +70,11 @@ impl ConcreteValue {
(Character(left), Character(right)) => {
ConcreteValue::string(format!("{}{}", left, right))
}
(Character(left), String(right)) => ConcreteValue::string(format!("{}{}", left, right)),
(Float(left), Float(right)) => ConcreteValue::Float(*left + *right),
(Integer(left), Integer(right)) => ConcreteValue::Integer(left.saturating_add(*right)),
(String(left), String(right)) => ConcreteValue::string(format!("{}{}", left, right)),
(String(left), Character(right)) => ConcreteValue::string(format!("{}{}", left, right)),
_ => {
return Err(ValueError::CannotAdd(
self.clone().to_value(),

View File

@ -32,6 +32,41 @@ fn add_characters() {
assert_eq!(run(source), Ok(Some(ConcreteValue::string("ab"))));
}
#[test]
fn add_character_and_string() {
let source = "'a' + \"b\"";
assert_eq!(
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::String),
},
vec![
(
Instruction::add(
Destination::Register(0),
Argument::Constant(0),
Argument::Constant(1)
),
Span(4, 5)
),
(Instruction::r#return(true), Span(9, 9))
],
vec![
ConcreteValue::Character('a'),
ConcreteValue::String("b".to_string())
],
vec![]
))
);
assert_eq!(run(source), Ok(Some(ConcreteValue::string("ab"))));
}
#[test]
fn add_floats() {
let source = "1.0 + 2.0";
@ -128,3 +163,41 @@ fn add_strings() {
))
);
}
#[test]
fn add_string_and_character() {
let source = "\"a\" + 'b'";
assert_eq!(
compile(source),
Ok(Chunk::with_data(
None,
FunctionType {
type_parameters: None,
value_parameters: None,
return_type: Box::new(Type::String),
},
vec![
(
Instruction::add(
Destination::Register(0),
Argument::Constant(0),
Argument::Constant(1)
),
Span(4, 5)
),
(Instruction::r#return(true), Span(9, 9))
],
vec![
ConcreteValue::String("a".to_string()),
ConcreteValue::Character('b')
],
vec![]
))
);
assert_eq!(
run(source),
Ok(Some(ConcreteValue::String("ab".to_string())))
);
}