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 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<f64, CalculatorError> {
pub fn pop(&mut self) -> CalculatorResult<f64> {
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<CalculatorStateChange, CalculatorError> {
) -> CalculatorResult<CalculatorStateChange> {
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<CalculatorStateChange, CalculatorError> {
) -> CalculatorResult<CalculatorStateChange> {
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<f64, CalculatorError> {
fn checked_get(&self, idx: usize) -> CalculatorResult<f64> {
match self.stack.get(idx) {
None => Err(CalculatorError::NotEnoughStackEntries),
Some(r) => Ok(*r),

View File

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

View File

@ -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<CalculatorOperation, CalculatorError> {
pub fn from_char(key: char) -> CalculatorResult<CalculatorOperation> {
match key {
'+' => Ok(CalculatorOperation::Add),
'-' => Ok(CalculatorOperation::Subtract),

View File

@ -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<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 {
AppState::Calculator => match key {
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') => {
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<bool, Calculat
if !app.input.is_empty() {
//TODO: A better way to do this
//Can use calc_operation in the future. Already performs this check
if let Ok(f) = app.input.parse::<f64>() {
match app.calculator.push(f) {
Ok(()) => app.input.clear(),
Err(e) => return Err(e),
}
} else {
return Err(CalculatorError::ParseError);
}
let f = app
.input
.parse::<f64>()
.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<bool, Calculat
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)?;
if !app.input.is_empty() {
if let Ok(f) = app.input.parse::<f64>() {
app.calculator.push(f)?;
app.input.clear();
} else {
return Err(CalculatorError::ParseError);
}
let f = app
.input
.parse::<f64>()
.or(Err(CalculatorError::ParseError))?;
app.calculator.push(f)?;
app.input.clear();
}
app.calculator.op(op)