From eb8c1a0a372725290aaed170686925798a710fdb Mon Sep 17 00:00:00 2001 From: Kasper Date: Mon, 13 Jan 2020 23:38:31 +0100 Subject: [PATCH] Moved addition/subtraction to units.rs --- src/evaluator.rs | 30 ++++++------------------------ src/units.rs | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 24 deletions(-) diff --git a/src/evaluator.rs b/src/evaluator.rs index 05bca72..6f4eb76 100644 --- a/src/evaluator.rs +++ b/src/evaluator.rs @@ -1,6 +1,6 @@ use decimal::d128; use crate::Token; -use crate::units::{Unit, UnitType, Number, convert}; +use crate::units::{Unit, UnitType, Number, convert, add, subtract}; use crate::parser::AstNode; use crate::Operator::{Caret, Divide, Minus, Modulo, Multiply, Plus}; use crate::Constant::{Pi, E}; @@ -215,12 +215,8 @@ fn evaluate_node(ast_node: &AstNode) -> Result { To => { if let Token::Unit(right_unit) = right_child.token { let left = evaluate_node(left_child)?; - if left.unit.category() == right_unit.category() { - let result = convert(left, right_unit)?; - return Ok(result) - } else { - return Err(format!("Cannot convert from {:?} to {:?}", left.unit, right_unit)) - } + let result = convert(left, right_unit)?; + return Ok(result) } else { return Err("Right side of To operator needs to be a unit".to_string()) } @@ -231,7 +227,7 @@ fn evaluate_node(ast_node: &AstNode) -> Result { if left.unit == Unit::NoUnit { return Ok(Number::new(left.value * right.value, right.unit)) } else { - return Err("child[0] of the Of operator must be NoUnit".to_string()) + return Err("Left side of the Of operator must be NoUnit".to_string()) } }, } @@ -243,24 +239,10 @@ fn evaluate_node(ast_node: &AstNode) -> Result { let right = evaluate_node(right_child)?; match operator { Plus => { - if left.unit == right.unit { - Ok(Number::new(left.value + right.value, left.unit)) - } else if left.unit.category() == right.unit.category() { - let result = left.value * left.unit.weight() + right.value * right.unit.weight(); - Ok(Number::new(result, Unit::Millimeter)) - } else { - return Err(format!("Cannot add {:?} and {:?}", left.unit, right.unit)) - } + Ok(add(left, right)?) }, Minus => { - if left.unit == right.unit { - Ok(Number::new(left.value - right.value, left.unit)) - } else if left.unit.category() == right.unit.category() { - let result = left.value * left.unit.weight() - right.value * right.unit.weight(); - Ok(Number::new(result, Unit::Millimeter)) - } else { - return Err(format!("Cannot subtract {:?} by {:?}", left.unit, right.unit)) - } + Ok(subtract(left, right)?) }, Multiply => { if left.unit == Unit::NoUnit && right.unit == Unit::NoUnit { diff --git a/src/units.rs b/src/units.rs index ec287d0..dc6415e 100644 --- a/src/units.rs +++ b/src/units.rs @@ -228,6 +228,9 @@ fn get_convertion_factor(unit: Unit, to_unit: Unit) -> d128 { } pub fn convert(number: Number, to_unit: Unit) -> Result { + if number.unit.category() != to_unit.category() { + return Err(format!("Cannot convert from {:?} to {:?}", number.unit, to_unit)); + } let value = number.value; let ok = |new_value| { Ok(Number::new(new_value, to_unit)) @@ -251,6 +254,38 @@ pub fn convert(number: Number, to_unit: Unit) -> Result { } } +pub fn add(left: Number, right: Number) -> Result { + if left.unit == right.unit { + Ok(Number::new(left.value + right.value, left.unit)) + } else if left.unit.category() == right.unit.category() && left.unit.category() != Temperature { + if left.unit.weight() > right.unit.weight() { + let left_converted = convert(left, right.unit)?; + Ok(Number::new(left_converted.value + right.value, right.unit)) + } else { + let right_converted = convert(right, left.unit)?; + Ok(Number::new(right_converted.value + left.value, left.unit)) + } + } else { + return Err(format!("Cannot add {:?} and {:?}", left.unit, right.unit)) + } +} + +pub fn subtract(left: Number, right: Number) -> Result { + if left.unit == right.unit { + Ok(Number::new(left.value - right.value, left.unit)) + } else if left.unit.category() == right.unit.category() && left.unit.category() != Temperature { + if left.unit.weight() > right.unit.weight() { + let left_converted = convert(left, right.unit)?; + Ok(Number::new(left_converted.value - right.value, right.unit)) + } else { + let right_converted = convert(right, left.unit)?; + Ok(Number::new(right_converted.value - left.value, left.unit)) + } + } else { + return Err(format!("Cannot subtract {:?} by {:?}", left.unit, right.unit)) + } +} + #[cfg(test)] mod tests { use super::*;