From 2ff42bf62aab31440e833048e0c2d4dd7a929298 Mon Sep 17 00:00:00 2001 From: rm-dr <96270320+rm-dr@users.noreply.github.com> Date: Sun, 15 Oct 2023 11:26:45 -0700 Subject: [PATCH] Added unit checks to temp conversions --- src/evaluate/evaluate.rs | 2 +- src/evaluate/function.rs | 67 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 62 insertions(+), 7 deletions(-) diff --git a/src/evaluate/evaluate.rs b/src/evaluate/evaluate.rs index d80109a..64173da 100644 --- a/src/evaluate/evaluate.rs +++ b/src/evaluate/evaluate.rs @@ -63,7 +63,7 @@ pub fn evaluate( 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)? }, }; diff --git a/src/evaluate/function.rs b/src/evaluate/function.rs index e24a391..5f3b101 100644 --- a/src/evaluate/function.rs +++ b/src/evaluate/function.rs @@ -3,11 +3,12 @@ use crate::parser::Function; use crate::parser::Operator; use crate::parser::LineLocation; use crate::quantity::FreeUnit; +use crate::quantity::Unit; use crate::quantity::WholeUnit; use crate::quantity::Quantity; use crate::quantity::Scalar; use crate::errors::DaisyError; - +use crate::context::Context; // If unitless, do nothing // If compatible with radians, convert to radians and return unitless @@ -26,7 +27,7 @@ fn to_radians(q: Quantity) -> Result { -pub fn eval_function(g: &Expression) -> Result, (LineLocation, DaisyError)> { +pub fn eval_function(context: &mut Context, g: &Expression) -> Result, (LineLocation, DaisyError)> { let Expression::Operator(loc, Operator::Function(f), args) = g else {unreachable!()}; @@ -154,17 +155,51 @@ pub fn eval_function(g: &Expression) -> Result, (LineLocation Function::ToCelsius => { let mut k = Quantity::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(); r += Quantity::new_rational(-273.15f64).unwrap(); return Ok(Some(Expression::Quantity(*loc + *l, r))); }, + + Function::ToFahrenheit => { let mut k = Quantity::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(); r *= Quantity::new_rational_from_frac(9i64, 5i64).unwrap(); @@ -173,8 +208,18 @@ pub fn eval_function(g: &Expression) -> Result, (LineLocation return Ok(Some(Expression::Quantity(*loc + *l, r))); }, + + 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(); r += q.clone(); @@ -182,8 +227,18 @@ pub fn eval_function(g: &Expression) -> Result, (LineLocation return Ok(Some(Expression::Quantity(*loc + *l, r))); }, + + 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(); r += Quantity::new_rational(459.67).unwrap();