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

View File

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

View File

@ -32,6 +32,41 @@ fn add_characters() {
assert_eq!(run(source), Ok(Some(ConcreteValue::string("ab")))); 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] #[test]
fn add_floats() { fn add_floats() {
let source = "1.0 + 2.0"; 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())))
);
}