diff --git a/src/calc.rs b/src/calc.rs index 0801da1..ff71c74 100644 --- a/src/calc.rs +++ b/src/calc.rs @@ -2,15 +2,11 @@ pub mod constants; pub mod errors; pub mod operations; -use constants::CalculatorConstant; -use constants::CalculatorConstants; -use constants::CalculatorConstantsIter; -use constants::CalculatorMacro; -use constants::CalculatorMacros; -use constants::CalculatorMacrosIter; -use constants::CalculatorRegisters; -use constants::CalculatorRegistersIter; -use errors::CalculatorError; +use constants::{ + CalculatorConstant, CalculatorConstants, CalculatorConstantsIter, CalculatorMacro, + CalculatorMacros, CalculatorMacrosIter, CalculatorRegisters, CalculatorRegistersIter, +}; +use errors::{CalculatorError, CalculatorResult}; use operations::CalculatorOperation; use std::collections::VecDeque; @@ -108,7 +104,7 @@ impl<'a> Calculator<'a> { self.registers.iter() } - pub fn push_constant(&mut self, key: char) -> Result<(), CalculatorError> { + pub fn push_constant(&mut self, key: char) -> CalculatorResult<()> { match self.constants.get(&key) { Some(CalculatorConstant { value, .. }) => { let value = *value; @@ -117,7 +113,7 @@ impl<'a> Calculator<'a> { None => Err(CalculatorError::NoSuchConstant), } } - pub fn push_register(&mut self, key: char) -> Result<(), CalculatorError> { + pub fn push_register(&mut self, key: char) -> CalculatorResult<()> { match self.registers.get(&key) { Some(f) => { let f = *f; @@ -127,7 +123,7 @@ impl<'a> Calculator<'a> { } } // TODO: Use hashmap - pub fn save_register(&mut self, key: char) -> Result<(), CalculatorError> { + pub fn save_register(&mut self, key: char) -> CalculatorResult<()> { let f = self.pop()?; self.registers.insert(key, f); Ok(()) @@ -139,13 +135,13 @@ impl<'a> Calculator<'a> { } } - pub fn push(&mut self, f: f64) -> Result<(), CalculatorError> { + pub fn push(&mut self, f: f64) -> CalculatorResult<()> { self.direct_state_change(CalculatorStateChange { pop: OpArgs::None, push: OpArgs::Unary(f), }) } - pub fn pop(&mut self) -> Result { + pub fn pop(&mut self) -> CalculatorResult { let f = self.checked_get(0)?; self.direct_state_change(CalculatorStateChange { pop: OpArgs::Unary(f), @@ -157,7 +153,7 @@ impl<'a> Calculator<'a> { &self.stack } //TODO: VecDeque could have other types - pub fn op(&mut self, op: CalculatorOperation) -> Result<(), CalculatorError> { + pub fn op(&mut self, op: CalculatorOperation) -> CalculatorResult<()> { let state_change = match op { CalculatorOperation::Add => self.binary_op(|[a, b]| OpArgs::Unary(b + a)), CalculatorOperation::Subtract => self.binary_op(|[a, b]| OpArgs::Unary(b - a)), @@ -210,7 +206,7 @@ impl<'a> Calculator<'a> { fn unary_op( &mut self, op: impl FnOnce(f64) -> OpArgs, - ) -> Result { + ) -> CalculatorResult { let arg = self .stack .get(0) @@ -223,7 +219,7 @@ impl<'a> Calculator<'a> { fn binary_op( &mut self, op: impl FnOnce([f64; 2]) -> OpArgs, - ) -> Result { + ) -> CalculatorResult { let args: [f64; 2] = [ *self .stack @@ -240,7 +236,7 @@ impl<'a> Calculator<'a> { }) } - fn direct_state_change(&mut self, c: CalculatorStateChange) -> Result<(), CalculatorError> { + fn direct_state_change(&mut self, c: CalculatorStateChange) -> CalculatorResult<()> { let result = self.apply_state_change(c, true); if result.is_ok() { // Clear the redo buffer since this was a direct state change @@ -253,7 +249,7 @@ impl<'a> Calculator<'a> { &mut self, c: CalculatorStateChange, forward: bool, - ) -> Result<(), CalculatorError> { + ) -> CalculatorResult<()> { let (to_pop, to_push) = if forward { (&c.pop, &c.push) } else { @@ -313,7 +309,7 @@ impl<'a> Calculator<'a> { Ok(()) } - fn stack_eq(&self, idx: usize, value: f64) -> Result<(), CalculatorError> { + fn stack_eq(&self, idx: usize, value: f64) -> CalculatorResult<()> { if (self.checked_get(idx)? - value).abs() > f64::EPSILON { Err(CalculatorError::CorruptStateChange(format!( "Stack index {} should be {}, but is {}", @@ -326,7 +322,7 @@ impl<'a> Calculator<'a> { } } - fn checked_get(&self, idx: usize) -> Result { + fn checked_get(&self, idx: usize) -> CalculatorResult { match self.stack.get(idx) { None => Err(CalculatorError::NotEnoughStackEntries), Some(r) => Ok(*r), diff --git a/src/calc/errors.rs b/src/calc/errors.rs index 37052ad..934c819 100644 --- a/src/calc/errors.rs +++ b/src/calc/errors.rs @@ -1,5 +1,7 @@ use std::fmt; +pub type CalculatorResult = Result; + pub enum CalculatorError { ArithmeticError, NotEnoughStackEntries, diff --git a/src/calc/operations.rs b/src/calc/operations.rs index c64c328..52663da 100644 --- a/src/calc/operations.rs +++ b/src/calc/operations.rs @@ -1,4 +1,4 @@ -use super::errors::CalculatorError; +use super::errors::{CalculatorError, CalculatorResult}; pub enum CalculatorOperation { Add, @@ -31,7 +31,7 @@ pub enum CalculatorOperation { } impl CalculatorOperation { - pub fn from_char(key: char) -> Result { + pub fn from_char(key: char) -> CalculatorResult { match key { '+' => Ok(CalculatorOperation::Add), '-' => Ok(CalculatorOperation::Subtract), diff --git a/src/main.rs b/src/main.rs index 74cfe94..2ab1813 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,7 +4,7 @@ mod calc; mod util; -use calc::errors::CalculatorError; +use calc::errors::{CalculatorError, CalculatorResult}; use calc::operations::CalculatorOperation; use calc::Calculator; use std::cmp; @@ -251,7 +251,7 @@ fn main() -> Result<(), Box> { } } -fn handle_key(app: &mut App, events: &Events, key: Key) -> Result { +fn handle_key(app: &mut App, events: &Events, key: Key) -> CalculatorResult { match &app.state { AppState::Calculator => match key { Key::Char('q') => { @@ -275,17 +275,22 @@ fn handle_key(app: &mut App, events: &Events, key: Key) -> Result { app.input.push(c); } - Key::Char(c @ 'e') | Key::Char(c @ '.') => { + Key::Char('e') => { if app.input.is_empty() { - if let Ok(f) = app.calculator.pop() { - app.input = f.to_string(); - } else { - return Err(CalculatorError::NotEnoughStackEntries); - } + let f = app + .calculator + .pop() + .or(Err(CalculatorError::NotEnoughStackEntries))?; + app.input = f.to_string(); } - if !app.input.contains(c) { - app.input.push(c); + if !app.input.contains('e') { + app.input.push('e'); + } + } + Key::Char('.') => { + if !app.input.contains('.') { + app.input.push('.'); } } Key::Char('\n') | Key::Char(' ') => { @@ -366,14 +371,14 @@ fn handle_key(app: &mut App, events: &Events, key: Key) -> Result() { - match app.calculator.push(f) { - Ok(()) => app.input.clear(), - Err(e) => return Err(e), - } - } else { - return Err(CalculatorError::ParseError); - } + let f = app + .input + .parse::() + .or(Err(CalculatorError::ParseError))?; + app.calculator.push(f).and_then(|()| { + app.input.clear(); + Ok(()) + })?; } // TODO: Handle macros internally to the calculator @@ -387,15 +392,15 @@ fn handle_key(app: &mut App, events: &Events, key: Key) -> Result Result<(), CalculatorError> { +fn calc_operation(app: &mut App, c: char) -> CalculatorResult<()> { let op = CalculatorOperation::from_char(c)?; if !app.input.is_empty() { - if let Ok(f) = app.input.parse::() { - app.calculator.push(f)?; - app.input.clear(); - } else { - return Err(CalculatorError::ParseError); - } + let f = app + .input + .parse::() + .or(Err(CalculatorError::ParseError))?; + app.calculator.push(f)?; + app.input.clear(); } app.calculator.op(op)