diff --git a/src/calc.rs b/src/calc.rs index 427ca96..d224178 100644 --- a/src/calc.rs +++ b/src/calc.rs @@ -55,11 +55,38 @@ impl From for StackCalcError { impl StackCalc { + pub fn is_full(&self) -> bool { + self.index == STACK + } + + pub fn is_empty(&self) -> bool { + self.index == 0 + } + + pub fn len(&self) -> usize { + self.index + } + + pub fn reset(&mut self) { + self.index = 0; + } + + pub fn last(&self) -> Option> { + if self.is_empty() { + return None; + } + Some(self.stack[self.index - 1]) + } + + pub fn iter(&self) -> impl Iterator> { + self.stack.iter().take(self.index) + } + pub fn push( &mut self, val: impl TryInto, Error: Into>, ) -> Result<(), StackCalcError> { - if self.index == STACK { + if self.is_full() { return Err(StackCalcError::StackOverflow); } self.stack[self.index] = val.try_into().map_err(Into::into)?; @@ -68,22 +95,46 @@ impl Result, StackCalcError> { - if self.index == 0 { + if self.is_empty() { return Err(StackCalcError::StackUnderflow); } self.index -= 1; Ok(self.stack[self.index]) } - pub fn add(&mut self) -> Result, StackCalcError> { + fn pop_pair_float(&mut self) -> Result<(F, F), StackCalcError> { let a = self.pop()?; let b = self.pop()?; let a = a.to_float::()?; let b = b.to_float::()?; - let res = Decimal::from_float(a + b)?; + Ok((a, b)) + } + + fn calc_pair_float( + &mut self, + f: impl FnOnce(F, F) -> Result, + ) -> Result, StackCalcError> { + let (a, b) = self.pop_pair_float()?; + let res = Decimal::from_float(f(a, b)?)?; self.push(res)?; Ok(res) } + + pub fn add(&mut self) -> Result, StackCalcError> { + self.calc_pair_float(|a, b| Ok(b + a)) + } + + pub fn sub(&mut self) -> Result, StackCalcError> { + self.calc_pair_float(|a, b| Ok(b - a)) + } + + pub fn mul(&mut self) -> Result, StackCalcError> { + self.calc_pair_float(|a, b| Ok(b * a)) + } + + pub fn div(&mut self) -> Result, StackCalcError> { + self.calc_pair_float(|a, b| Ok(b / a)) + } } #[cfg(test)] @@ -103,8 +154,13 @@ mod tests { calc.push(3.0).unwrap_err(), StackCalcError::StackOverflow )); - assert_eq!(calc.add()?, Decimal::try_from(5.0)?); - assert_eq!(calc.add()?, Decimal::try_from(1337.42 * 2.0 + 5.0)?); + calc.add()?; + assert_eq!(calc.last().unwrap(), Decimal::try_from(5.0)?); + calc.add()?; + assert_eq!( + calc.last().unwrap(), + Decimal::try_from(1337.42 * 2.0 + 5.0)? + ); assert!(matches!( calc.add().unwrap_err(), StackCalcError::StackUnderflow