Various code improvements

This commit is contained in:
Austen Adler 2021-04-27 23:04:14 -04:00
parent cdb2011efa
commit 5772147ef1
4 changed files with 51 additions and 48 deletions

View File

@ -2,15 +2,11 @@ pub mod constants;
pub mod errors; pub mod errors;
pub mod operations; pub mod operations;
use constants::CalculatorConstant; use constants::{
use constants::CalculatorConstants; CalculatorConstant, CalculatorConstants, CalculatorConstantsIter, CalculatorMacro,
use constants::CalculatorConstantsIter; CalculatorMacros, CalculatorMacrosIter, CalculatorRegisters, CalculatorRegistersIter,
use constants::CalculatorMacro; };
use constants::CalculatorMacros; use errors::{CalculatorError, CalculatorResult};
use constants::CalculatorMacrosIter;
use constants::CalculatorRegisters;
use constants::CalculatorRegistersIter;
use errors::CalculatorError;
use operations::CalculatorOperation; use operations::CalculatorOperation;
use std::collections::VecDeque; use std::collections::VecDeque;
@ -108,7 +104,7 @@ impl<'a> Calculator<'a> {
self.registers.iter() 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) { match self.constants.get(&key) {
Some(CalculatorConstant { value, .. }) => { Some(CalculatorConstant { value, .. }) => {
let value = *value; let value = *value;
@ -117,7 +113,7 @@ impl<'a> Calculator<'a> {
None => Err(CalculatorError::NoSuchConstant), 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) { match self.registers.get(&key) {
Some(f) => { Some(f) => {
let f = *f; let f = *f;
@ -127,7 +123,7 @@ impl<'a> Calculator<'a> {
} }
} }
// TODO: Use hashmap // 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()?; let f = self.pop()?;
self.registers.insert(key, f); self.registers.insert(key, f);
Ok(()) 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 { self.direct_state_change(CalculatorStateChange {
pop: OpArgs::None, pop: OpArgs::None,
push: OpArgs::Unary(f), push: OpArgs::Unary(f),
}) })
} }
pub fn pop(&mut self) -> Result<f64, CalculatorError> { pub fn pop(&mut self) -> CalculatorResult<f64> {
let f = self.checked_get(0)?; let f = self.checked_get(0)?;
self.direct_state_change(CalculatorStateChange { self.direct_state_change(CalculatorStateChange {
pop: OpArgs::Unary(f), pop: OpArgs::Unary(f),
@ -157,7 +153,7 @@ impl<'a> Calculator<'a> {
&self.stack &self.stack
} }
//TODO: VecDeque could have other types //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 { let state_change = match op {
CalculatorOperation::Add => self.binary_op(|[a, b]| OpArgs::Unary(b + a)), CalculatorOperation::Add => self.binary_op(|[a, b]| OpArgs::Unary(b + a)),
CalculatorOperation::Subtract => 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( fn unary_op(
&mut self, &mut self,
op: impl FnOnce(f64) -> OpArgs, op: impl FnOnce(f64) -> OpArgs,
) -> Result<CalculatorStateChange, CalculatorError> { ) -> CalculatorResult<CalculatorStateChange> {
let arg = self let arg = self
.stack .stack
.get(0) .get(0)
@ -223,7 +219,7 @@ impl<'a> Calculator<'a> {
fn binary_op( fn binary_op(
&mut self, &mut self,
op: impl FnOnce([f64; 2]) -> OpArgs, op: impl FnOnce([f64; 2]) -> OpArgs,
) -> Result<CalculatorStateChange, CalculatorError> { ) -> CalculatorResult<CalculatorStateChange> {
let args: [f64; 2] = [ let args: [f64; 2] = [
*self *self
.stack .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); let result = self.apply_state_change(c, true);
if result.is_ok() { if result.is_ok() {
// Clear the redo buffer since this was a direct state change // Clear the redo buffer since this was a direct state change
@ -253,7 +249,7 @@ impl<'a> Calculator<'a> {
&mut self, &mut self,
c: CalculatorStateChange, c: CalculatorStateChange,
forward: bool, forward: bool,
) -> Result<(), CalculatorError> { ) -> CalculatorResult<()> {
let (to_pop, to_push) = if forward { let (to_pop, to_push) = if forward {
(&c.pop, &c.push) (&c.pop, &c.push)
} else { } else {
@ -313,7 +309,7 @@ impl<'a> Calculator<'a> {
Ok(()) 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 { if (self.checked_get(idx)? - value).abs() > f64::EPSILON {
Err(CalculatorError::CorruptStateChange(format!( Err(CalculatorError::CorruptStateChange(format!(
"Stack index {} should be {}, but is {}", "Stack index {} should be {}, but is {}",
@ -326,7 +322,7 @@ impl<'a> Calculator<'a> {
} }
} }
fn checked_get(&self, idx: usize) -> Result<f64, CalculatorError> { fn checked_get(&self, idx: usize) -> CalculatorResult<f64> {
match self.stack.get(idx) { match self.stack.get(idx) {
None => Err(CalculatorError::NotEnoughStackEntries), None => Err(CalculatorError::NotEnoughStackEntries),
Some(r) => Ok(*r), Some(r) => Ok(*r),

View File

@ -1,5 +1,7 @@
use std::fmt; use std::fmt;
pub type CalculatorResult<T> = Result<T, CalculatorError>;
pub enum CalculatorError { pub enum CalculatorError {
ArithmeticError, ArithmeticError,
NotEnoughStackEntries, NotEnoughStackEntries,

View File

@ -1,4 +1,4 @@
use super::errors::CalculatorError; use super::errors::{CalculatorError, CalculatorResult};
pub enum CalculatorOperation { pub enum CalculatorOperation {
Add, Add,
@ -31,7 +31,7 @@ pub enum CalculatorOperation {
} }
impl CalculatorOperation { impl CalculatorOperation {
pub fn from_char(key: char) -> Result<CalculatorOperation, CalculatorError> { pub fn from_char(key: char) -> CalculatorResult<CalculatorOperation> {
match key { match key {
'+' => Ok(CalculatorOperation::Add), '+' => Ok(CalculatorOperation::Add),
'-' => Ok(CalculatorOperation::Subtract), '-' => Ok(CalculatorOperation::Subtract),

View File

@ -4,7 +4,7 @@
mod calc; mod calc;
mod util; mod util;
use calc::errors::CalculatorError; use calc::errors::{CalculatorError, CalculatorResult};
use calc::operations::CalculatorOperation; use calc::operations::CalculatorOperation;
use calc::Calculator; use calc::Calculator;
use std::cmp; use std::cmp;
@ -251,7 +251,7 @@ fn main() -> Result<(), Box<dyn Error>> {
} }
} }
fn handle_key(app: &mut App, events: &Events, key: Key) -> Result<bool, CalculatorError> { fn handle_key(app: &mut App, events: &Events, key: Key) -> CalculatorResult<bool> {
match &app.state { match &app.state {
AppState::Calculator => match key { AppState::Calculator => match key {
Key::Char('q') => { Key::Char('q') => {
@ -275,17 +275,22 @@ fn handle_key(app: &mut App, events: &Events, key: Key) -> Result<bool, Calculat
Key::Char(c @ '0'..='9') => { Key::Char(c @ '0'..='9') => {
app.input.push(c); app.input.push(c);
} }
Key::Char(c @ 'e') | Key::Char(c @ '.') => { Key::Char('e') => {
if app.input.is_empty() { if app.input.is_empty() {
if let Ok(f) = app.calculator.pop() { let f = app
app.input = f.to_string(); .calculator
} else { .pop()
return Err(CalculatorError::NotEnoughStackEntries); .or(Err(CalculatorError::NotEnoughStackEntries))?;
} app.input = f.to_string();
} }
if !app.input.contains(c) { if !app.input.contains('e') {
app.input.push(c); app.input.push('e');
}
}
Key::Char('.') => {
if !app.input.contains('.') {
app.input.push('.');
} }
} }
Key::Char('\n') | Key::Char(' ') => { Key::Char('\n') | Key::Char(' ') => {
@ -366,14 +371,14 @@ fn handle_key(app: &mut App, events: &Events, key: Key) -> Result<bool, Calculat
if !app.input.is_empty() { if !app.input.is_empty() {
//TODO: A better way to do this //TODO: A better way to do this
//Can use calc_operation in the future. Already performs this check //Can use calc_operation in the future. Already performs this check
if let Ok(f) = app.input.parse::<f64>() { let f = app
match app.calculator.push(f) { .input
Ok(()) => app.input.clear(), .parse::<f64>()
Err(e) => return Err(e), .or(Err(CalculatorError::ParseError))?;
} app.calculator.push(f).and_then(|()| {
} else { app.input.clear();
return Err(CalculatorError::ParseError); Ok(())
} })?;
} }
// TODO: Handle macros internally to the calculator // TODO: Handle macros internally to the calculator
@ -387,15 +392,15 @@ fn handle_key(app: &mut App, events: &Events, key: Key) -> Result<bool, Calculat
return Ok(false); return Ok(false);
} }
fn calc_operation(app: &mut App, c: char) -> Result<(), CalculatorError> { fn calc_operation(app: &mut App, c: char) -> CalculatorResult<()> {
let op = CalculatorOperation::from_char(c)?; let op = CalculatorOperation::from_char(c)?;
if !app.input.is_empty() { if !app.input.is_empty() {
if let Ok(f) = app.input.parse::<f64>() { let f = app
app.calculator.push(f)?; .input
app.input.clear(); .parse::<f64>()
} else { .or(Err(CalculatorError::ParseError))?;
return Err(CalculatorError::ParseError); app.calculator.push(f)?;
} app.input.clear();
} }
app.calculator.op(op) app.calculator.op(op)