Moved * / % and ^ to units.rs, added support for 1km/1km
This commit is contained in:
parent
c7141e87ad
commit
1e83f50fbd
@ -1,6 +1,6 @@
|
|||||||
use decimal::d128;
|
use decimal::d128;
|
||||||
use crate::Token;
|
use crate::Token;
|
||||||
use crate::units::{Unit, UnitType, Number, convert, add, subtract};
|
use crate::units::{Unit, UnitType, Number, convert, add, subtract, multiply, divide, modulo, pow};
|
||||||
use crate::parser::AstNode;
|
use crate::parser::AstNode;
|
||||||
use crate::Operator::{Caret, Divide, Minus, Modulo, Multiply, Plus};
|
use crate::Operator::{Caret, Divide, Minus, Modulo, Multiply, Plus};
|
||||||
use crate::Constant::{Pi, E};
|
use crate::Constant::{Pi, E};
|
||||||
@ -245,51 +245,20 @@ fn evaluate_node(ast_node: &AstNode) -> Result<Number, String> {
|
|||||||
Ok(subtract(left, right)?)
|
Ok(subtract(left, right)?)
|
||||||
},
|
},
|
||||||
Multiply => {
|
Multiply => {
|
||||||
if left.unit == Unit::NoUnit && right.unit == Unit::NoUnit {
|
Ok(multiply(left, right)?)
|
||||||
// 3 * 2
|
// }
|
||||||
return Ok(Number::new(left.value * right.value, left.unit))
|
|
||||||
} else if left.unit == Unit::NoUnit && right.unit != Unit::NoUnit {
|
|
||||||
// 3 * 1 km
|
|
||||||
return Ok(Number::new(left.value * right.value, right.unit))
|
|
||||||
} else if right.unit == Unit::NoUnit && left.unit != Unit::NoUnit {
|
|
||||||
// 1 km * 3
|
|
||||||
return Ok(Number::new(left.value * right.value, left.unit))
|
|
||||||
} else {
|
|
||||||
return Err(format!("Cannot multiply {:?} and {:?}", left.unit, right.unit))
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
Divide => {
|
Divide => {
|
||||||
if left.unit == Unit::NoUnit && right.unit == Unit::NoUnit {
|
Ok(divide(left, right)?)
|
||||||
// 3 / 2
|
// }
|
||||||
return Ok(Number::new(left.value / right.value, left.unit))
|
|
||||||
} else if left.unit != Unit::NoUnit && right.unit == Unit::NoUnit {
|
|
||||||
// 1 km / 2
|
|
||||||
return Ok(Number::new(left.value / right.value, right.unit))
|
|
||||||
} else {
|
|
||||||
return Err(format!("Cannot divide {:?} by {:?}", left.unit, right.unit))
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
Modulo => {
|
Modulo => {
|
||||||
if left.unit == Unit::NoUnit && right.unit == Unit::NoUnit {
|
Ok(modulo(left, right)?)
|
||||||
// 3 / 2
|
// }
|
||||||
return Ok(Number::new(left.value % right.value, left.unit))
|
|
||||||
} else if left.unit != Unit::NoUnit && right.unit == Unit::NoUnit {
|
|
||||||
// 1 km / 2
|
|
||||||
return Ok(Number::new(left.value % right.value, right.unit))
|
|
||||||
} else {
|
|
||||||
return Err(format!("Cannot modulo {:?} by {:?}", left.unit, right.unit))
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
Caret => {
|
Caret => {
|
||||||
if left.unit == Unit::NoUnit && right.unit == Unit::NoUnit {
|
Ok(pow(left, right)?)
|
||||||
// 3 ^ 2
|
// }
|
||||||
return Ok(Number::new(left.value.pow(right.value), left.unit))
|
|
||||||
} else if right.unit == Unit::NoUnit && left.unit != Unit::NoUnit {
|
|
||||||
// 1 km ^ 3
|
|
||||||
return Ok(Number::new(left.value.pow(right.value), left.unit))
|
|
||||||
} else {
|
|
||||||
return Err(format!("Cannot multiply {:?} and {:?}", left.unit, right.unit))
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
Err(format!("Unexpected operator {:?}", operator))
|
Err(format!("Unexpected operator {:?}", operator))
|
||||||
|
|||||||
95
src/units.rs
95
src/units.rs
@ -254,38 +254,97 @@ pub fn convert(number: Number, to_unit: Unit) -> Result<Number, String> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn convert_to_lowest(left: Number, right: Number) -> Result<(Number, Number), String> {
|
||||||
|
if left.unit.weight() == right.unit.weight() {
|
||||||
|
Ok((left, right))
|
||||||
|
} else if left.unit.weight() > right.unit.weight() {
|
||||||
|
let left_converted = convert(left, right.unit)?;
|
||||||
|
Ok((left_converted, right))
|
||||||
|
} else {
|
||||||
|
let right_converted = convert(right, left.unit)?;
|
||||||
|
Ok((left, right_converted))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn add(left: Number, right: Number) -> Result<Number, String> {
|
pub fn add(left: Number, right: Number) -> Result<Number, String> {
|
||||||
if left.unit == right.unit {
|
if left.unit.category() == right.unit.category() && left.unit.category() != Temperature {
|
||||||
|
let (left, right) = convert_to_lowest(left, right)?;
|
||||||
Ok(Number::new(left.value + right.value, left.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 {
|
} else {
|
||||||
return Err(format!("Cannot add {:?} and {:?}", left.unit, right.unit))
|
return Err(format!("Cannot add {:?} and {:?}", left.unit, right.unit))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn subtract(left: Number, right: Number) -> Result<Number, String> {
|
pub fn subtract(left: Number, right: Number) -> Result<Number, String> {
|
||||||
if left.unit == right.unit {
|
if left.unit.category() == right.unit.category() && left.unit.category() != Temperature {
|
||||||
|
let (left, right) = convert_to_lowest(left, right)?;
|
||||||
Ok(Number::new(left.value - right.value, left.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 {
|
} else {
|
||||||
return Err(format!("Cannot subtract {:?} by {:?}", left.unit, right.unit))
|
return Err(format!("Cannot subtract {:?} by {:?}", left.unit, right.unit))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn multiply(left: Number, right: Number) -> Result<Number, String> {
|
||||||
|
if left.unit == Unit::NoUnit && right.unit == Unit::NoUnit {
|
||||||
|
// 3 * 2
|
||||||
|
return Ok(Number::new(left.value * right.value, left.unit))
|
||||||
|
} else if left.unit.category() == Temperature || right.unit.category() == Temperature {
|
||||||
|
// if temperature
|
||||||
|
return Err(format!("Cannot multiply {:?} and {:?}", left.unit, right.unit))
|
||||||
|
} else if left.unit == Unit::NoUnit && right.unit != Unit::NoUnit {
|
||||||
|
// 3 * 1 km
|
||||||
|
return Ok(Number::new(left.value * right.value, right.unit))
|
||||||
|
} else if right.unit == Unit::NoUnit && left.unit != Unit::NoUnit {
|
||||||
|
// 1 km * 3
|
||||||
|
return Ok(Number::new(left.value * right.value, left.unit))
|
||||||
|
} else {
|
||||||
|
return Err(format!("Cannot multiply {:?} and {:?}", left.unit, right.unit))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn divide(left: Number, right: Number) -> Result<Number, String> {
|
||||||
|
if left.unit == Unit::NoUnit && right.unit == Unit::NoUnit {
|
||||||
|
// 3 / 2
|
||||||
|
Ok(Number::new(left.value / right.value, left.unit))
|
||||||
|
} else if left.unit.category() == Temperature || right.unit.category() == Temperature {
|
||||||
|
// if temperature
|
||||||
|
return Err(format!("Cannot divide {:?} by {:?}", left.unit, right.unit))
|
||||||
|
} else if left.unit != Unit::NoUnit && right.unit == Unit::NoUnit {
|
||||||
|
// 1 km / 2
|
||||||
|
Ok(Number::new(left.value / right.value, right.unit))
|
||||||
|
} else if left.unit.category() == right.unit.category() {
|
||||||
|
// 1 km / 1 km
|
||||||
|
let (left, right) = convert_to_lowest(left, right)?;
|
||||||
|
Ok(Number::new(left.value * right.value, Unit::NoUnit))
|
||||||
|
} else {
|
||||||
|
Err(format!("Cannot divide {:?} by {:?}", left.unit, right.unit))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn modulo(left: Number, right: Number) -> Result<Number, String> {
|
||||||
|
if left.unit == Unit::NoUnit && right.unit == Unit::NoUnit {
|
||||||
|
// 3 / 2
|
||||||
|
return Ok(Number::new(left.value % right.value, left.unit))
|
||||||
|
} else if left.unit != Unit::NoUnit && right.unit == Unit::NoUnit {
|
||||||
|
// 1 km / 2
|
||||||
|
return Ok(Number::new(left.value % right.value, right.unit))
|
||||||
|
} else {
|
||||||
|
return Err(format!("Cannot modulo {:?} by {:?}", left.unit, right.unit))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn pow(left: Number, right: Number) -> Result<Number, String> {
|
||||||
|
if left.unit == Unit::NoUnit && right.unit == Unit::NoUnit {
|
||||||
|
// 3 ^ 2
|
||||||
|
return Ok(Number::new(left.value.pow(right.value), left.unit))
|
||||||
|
} else if right.unit == Unit::NoUnit && left.unit != Unit::NoUnit {
|
||||||
|
// 1 km ^ 3
|
||||||
|
return Ok(Number::new(left.value.pow(right.value), left.unit))
|
||||||
|
} else {
|
||||||
|
return Err(format!("Cannot multiply {:?} and {:?}", left.unit, right.unit))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user