Various code improvements
This commit is contained in:
parent
cdb2011efa
commit
5772147ef1
38
src/calc.rs
38
src/calc.rs
@ -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),
|
||||||
|
@ -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,
|
||||||
|
@ -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),
|
||||||
|
49
src/main.rs
49
src/main.rs
@ -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
|
||||||
|
.calculator
|
||||||
|
.pop()
|
||||||
|
.or(Err(CalculatorError::NotEnoughStackEntries))?;
|
||||||
app.input = f.to_string();
|
app.input = f.to_string();
|
||||||
} else {
|
|
||||||
return Err(CalculatorError::NotEnoughStackEntries);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
|
.input
|
||||||
|
.parse::<f64>()
|
||||||
|
.or(Err(CalculatorError::ParseError))?;
|
||||||
app.calculator.push(f)?;
|
app.calculator.push(f)?;
|
||||||
app.input.clear();
|
app.input.clear();
|
||||||
} else {
|
|
||||||
return Err(CalculatorError::ParseError);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
app.calculator.op(op)
|
app.calculator.op(op)
|
||||||
|
Loading…
Reference in New Issue
Block a user