Implement better error messages for addition with incompatible types

Implements #60
This commit is contained in:
Sebastian Schmidt 2019-08-29 16:36:35 +03:00
parent 2ec3dc74c1
commit 2d1704b9a3
3 changed files with 23 additions and 10 deletions

View File

@ -214,6 +214,11 @@ impl EvalexprError {
EvalexprError::TypeError { actual, expected }
}
/// Constructs `EvalexprError::WrongTypeCombination{operator, actual}`.
pub fn wrong_type_combination(operator: Operator, actual: Vec<ValueType>) -> Self {
EvalexprError::WrongTypeCombination { operator, actual }
}
/// Constructs `EvalexprError::ExpectedString{actual}`.
pub fn expected_string(actual: Value) -> Self {
EvalexprError::ExpectedString { actual }

View File

@ -1,11 +1,12 @@
use crate::function::builtin::builtin_function;
use crate::{context::Context, error::*, value::Value};
use std::borrow::Borrow;
mod display;
/// An enum that represents operators in the operator tree.
#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, Clone)]
pub enum Operator {
/// A root node in the operator tree.
/// The whole expression is stored under a root node, as well as each subexpression surrounded by parentheses.
@ -205,9 +206,13 @@ impl Operator {
arguments[1].clone(),
))
}
} else if let (Ok(a), Ok(b)) = (arguments[0].as_number(), arguments[1].as_number())
{
Ok(Value::Float(a + b))
} else {
Ok(Value::Float(
arguments[0].as_number()? + arguments[1].as_number()?,
Err(EvalexprError::wrong_type_combination(
self.clone(),
vec![arguments[0].borrow().into(), arguments[1].borrow().into()],
))
}
},

View File

@ -698,17 +698,20 @@ fn test_operator_assignments() {
#[test]
fn test_type_errors_in_binary_operators() {
// This error is bad. In future, maybe add a special error message for this kind of call.
// Only addition supports incompatible types, all others work only on numbers or only on booleans.
// So only addition requires the more fancy error message.
assert_eq!(
eval("4 + \"abc\""),
Err(EvalexprError::expected_number(Value::from(
"abc".to_string()
)))
Err(EvalexprError::wrong_type_combination(
Operator::Add,
vec![ValueType::Int, ValueType::String]
))
);
assert_eq!(
eval("\"abc\" + 4"),
Err(EvalexprError::expected_number(Value::from(
"abc".to_string()
)))
Err(EvalexprError::wrong_type_combination(
Operator::Add,
vec![ValueType::String, ValueType::Int]
))
);
}