Add new "add" tests; Allow adding strings to characters and visa versa
This commit is contained in:
parent
31a41581eb
commit
544edaf5f4
@ -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(())
|
||||
|
@ -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(),
|
||||
|
@ -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())))
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user