Added unit checks to temp conversions

dev
rm-dr 2023-10-15 11:26:45 -07:00
parent b5a23f814f
commit 2ff42bf62a
Signed by: Mark
GPG Key ID: AD62BB059C2AAEE4
2 changed files with 62 additions and 7 deletions

View File

@ -63,7 +63,7 @@ pub fn evaluate(
context.get_variable(&s) context.get_variable(&s)
}, },
Expression::Operator(_, Operator::Function(_), _) => { eval_function(g)? }, Expression::Operator(_, Operator::Function(_), _) => { eval_function(context, g)? },
Expression::Operator(_, _, _) => { eval_operator(context, g)? }, Expression::Operator(_, _, _) => { eval_operator(context, g)? },
}; };

View File

@ -3,11 +3,12 @@ use crate::parser::Function;
use crate::parser::Operator; use crate::parser::Operator;
use crate::parser::LineLocation; use crate::parser::LineLocation;
use crate::quantity::FreeUnit; use crate::quantity::FreeUnit;
use crate::quantity::Unit;
use crate::quantity::WholeUnit; use crate::quantity::WholeUnit;
use crate::quantity::Quantity; use crate::quantity::Quantity;
use crate::quantity::Scalar; use crate::quantity::Scalar;
use crate::errors::DaisyError; use crate::errors::DaisyError;
use crate::context::Context;
// If unitless, do nothing // If unitless, do nothing
// If compatible with radians, convert to radians and return unitless // If compatible with radians, convert to radians and return unitless
@ -26,7 +27,7 @@ fn to_radians(q: Quantity) -> Result<Quantity, ()> {
pub fn eval_function(g: &Expression) -> Result<Option<Expression>, (LineLocation, DaisyError)> { pub fn eval_function(context: &mut Context, g: &Expression) -> Result<Option<Expression>, (LineLocation, DaisyError)> {
let Expression::Operator(loc, Operator::Function(f), args) = g else {unreachable!()}; let Expression::Operator(loc, Operator::Function(f), args) = g else {unreachable!()};
@ -154,17 +155,51 @@ pub fn eval_function(g: &Expression) -> Result<Option<Expression>, (LineLocation
Function::ToCelsius => { Function::ToCelsius => {
let mut k = Quantity::new_rational(1f64).unwrap(); let mut k = Quantity::new_rational(1f64).unwrap();
k.insert_unit(FreeUnit::from_whole(WholeUnit::Kelvin), Scalar::new_rational(1f64).unwrap()); k.insert_unit(FreeUnit::from_whole(WholeUnit::Kelvin), Scalar::new_rational(1f64).unwrap());
let Some(q) = q.convert_to(k) else { return Err((*loc + *l, DaisyError::IncompatibleUnit)) };
let q_s: String;
if q.unitless() {
q_s = String::from("scalar");
} else {
q_s = q.convert_to_base().unit().display(context);
}
let Some(q) = q.convert_to(k) else {
return Err((
*loc + *l,
DaisyError::IncompatibleUnits(
q_s,
Unit::from_free(FreeUnit::from_whole(WholeUnit::Kelvin)).display(context)
)
))
};
let mut r = q.without_unit(); let mut r = q.without_unit();
r += Quantity::new_rational(-273.15f64).unwrap(); r += Quantity::new_rational(-273.15f64).unwrap();
return Ok(Some(Expression::Quantity(*loc + *l, r))); return Ok(Some(Expression::Quantity(*loc + *l, r)));
}, },
Function::ToFahrenheit => { Function::ToFahrenheit => {
let mut k = Quantity::new_rational(1f64).unwrap(); let mut k = Quantity::new_rational(1f64).unwrap();
k.insert_unit(FreeUnit::from_whole(WholeUnit::Kelvin), Scalar::new_rational(1f64).unwrap()); k.insert_unit(FreeUnit::from_whole(WholeUnit::Kelvin), Scalar::new_rational(1f64).unwrap());
let Some(q) = q.convert_to(k) else { return Err((*loc + *l, DaisyError::IncompatibleUnit)) };
let q_s: String;
if q.unitless() {
q_s = String::from("scalar");
} else {
q_s = q.convert_to_base().unit().display(context);
}
let Some(q) = q.convert_to(k) else {
return Err((
*loc + *l,
DaisyError::IncompatibleUnits(
q_s,
Unit::from_free(FreeUnit::from_whole(WholeUnit::Kelvin)).display(context)
)
))
};
let mut r = q.without_unit(); let mut r = q.without_unit();
r *= Quantity::new_rational_from_frac(9i64, 5i64).unwrap(); r *= Quantity::new_rational_from_frac(9i64, 5i64).unwrap();
@ -173,8 +208,18 @@ pub fn eval_function(g: &Expression) -> Result<Option<Expression>, (LineLocation
return Ok(Some(Expression::Quantity(*loc + *l, r))); return Ok(Some(Expression::Quantity(*loc + *l, r)));
}, },
Function::FromCelsius => { Function::FromCelsius => {
if !q.unitless() { return Err((*loc + *l, DaisyError::IncompatibleUnit));} if !q.unitless() {
return Err((
*loc + *l,
DaisyError::IncompatibleUnits(
q.convert_to_base().unit().display(context),
"scalar".to_string()
)
));
}
let mut r = Quantity::new_rational(273.15f64).unwrap(); let mut r = Quantity::new_rational(273.15f64).unwrap();
r += q.clone(); r += q.clone();
@ -182,8 +227,18 @@ pub fn eval_function(g: &Expression) -> Result<Option<Expression>, (LineLocation
return Ok(Some(Expression::Quantity(*loc + *l, r))); return Ok(Some(Expression::Quantity(*loc + *l, r)));
}, },
Function::FromFahrenheit => { Function::FromFahrenheit => {
if !q.unitless() { return Err((*loc + *l, DaisyError::IncompatibleUnit));} if !q.unitless() {
return Err((
*loc + *l,
DaisyError::IncompatibleUnits(
q.convert_to_base().unit().display(context),
"scalar".to_string()
)
));
}
let mut r = q.clone(); let mut r = q.clone();
r += Quantity::new_rational(459.67).unwrap(); r += Quantity::new_rational(459.67).unwrap();