Cleanup numeric entries
This commit is contained in:
parent
dab0333b31
commit
39e3c83abc
106
src/calc.rs
106
src/calc.rs
@ -14,8 +14,8 @@ use std::collections::{BTreeMap, HashMap};
|
||||
use std::collections::{HashSet, VecDeque};
|
||||
use types::{
|
||||
CalculatorAlignment, CalculatorAngleMode, CalculatorConstant, CalculatorConstants,
|
||||
CalculatorDisplayMode, CalculatorMacro, CalculatorMacros, CalculatorRegisters, CalculatorState,
|
||||
RegisterState,
|
||||
CalculatorDisplayMode, CalculatorMacro, CalculatorMacros, CalculatorRegisters,
|
||||
CalculatorState, RegisterState,
|
||||
};
|
||||
|
||||
/// The maximum precision allowed for the calculator
|
||||
@ -186,7 +186,8 @@ impl Calculator {
|
||||
}
|
||||
fn normal_input(&mut self, c: char) -> CalculatorResult<()> {
|
||||
match c {
|
||||
c @ '0'..='9' | c @ '.' | c @ 'e' => match c {
|
||||
c @ '0'..='9' | c @ '.' | c @ 'e' => {
|
||||
match c {
|
||||
'0'..='9' => {
|
||||
self.l.push(c);
|
||||
Ok(())
|
||||
@ -211,7 +212,8 @@ impl Calculator {
|
||||
Ok(())
|
||||
}
|
||||
_ => Err(CalculatorError::ParseError),
|
||||
},
|
||||
}
|
||||
}
|
||||
'+' => self.op(CalculatorOperation::Add),
|
||||
'-' => self.op(CalculatorOperation::Subtract),
|
||||
'*' => self.op(CalculatorOperation::Multiply),
|
||||
@ -243,11 +245,13 @@ impl Calculator {
|
||||
Ok(())
|
||||
}
|
||||
'r' => {
|
||||
self.state = CalculatorState::WaitingForRegister(RegisterState::Load);
|
||||
self.state =
|
||||
CalculatorState::WaitingForRegister(RegisterState::Load);
|
||||
Ok(())
|
||||
}
|
||||
'R' => {
|
||||
self.state = CalculatorState::WaitingForRegister(RegisterState::Save);
|
||||
self.state =
|
||||
CalculatorState::WaitingForRegister(RegisterState::Save);
|
||||
Ok(())
|
||||
}
|
||||
'`' => {
|
||||
@ -306,7 +310,11 @@ impl Calculator {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
fn register_input(&mut self, register_state: RegisterState, c: char) -> CalculatorResult<()> {
|
||||
fn register_input(
|
||||
&mut self,
|
||||
register_state: RegisterState,
|
||||
c: char,
|
||||
) -> CalculatorResult<()> {
|
||||
match register_state {
|
||||
RegisterState::Save => {
|
||||
let f = self.pop()?;
|
||||
@ -333,8 +341,14 @@ impl Calculator {
|
||||
'r' => self.angle_mode = CalculatorAngleMode::Radians,
|
||||
'g' => self.angle_mode = CalculatorAngleMode::Grads,
|
||||
'_' => self.display_mode = CalculatorDisplayMode::Default,
|
||||
',' => self.display_mode = CalculatorDisplayMode::Separated { separator: ',' },
|
||||
' ' => self.display_mode = CalculatorDisplayMode::Separated { separator: ' ' },
|
||||
',' => {
|
||||
self.display_mode =
|
||||
CalculatorDisplayMode::Separated { separator: ',' }
|
||||
}
|
||||
' ' => {
|
||||
self.display_mode =
|
||||
CalculatorDisplayMode::Separated { separator: ' ' }
|
||||
}
|
||||
's' => {
|
||||
self.display_mode = CalculatorDisplayMode::Scientific {
|
||||
precision: DEFAULT_PRECISION,
|
||||
@ -493,17 +507,33 @@ impl Calculator {
|
||||
}
|
||||
}
|
||||
let state_change = match op {
|
||||
CalculatorOperation::Add => self.binary_op(|[a, b]| Ok(OpArgs::Unary(b.add(a)?))),
|
||||
CalculatorOperation::Subtract => self.binary_op(|[a, b]| Ok(OpArgs::Unary(b.sub(a)?))),
|
||||
CalculatorOperation::Multiply => self.binary_op(|[a, b]| Ok(OpArgs::Unary(b.mul(a)?))),
|
||||
CalculatorOperation::Divide => self.binary_op(|[a, b]| Ok(OpArgs::Unary(b.div(a)?))),
|
||||
CalculatorOperation::Add => {
|
||||
self.binary_op(|[a, b]| Ok(OpArgs::Unary(b.add(a)?)))
|
||||
}
|
||||
CalculatorOperation::Subtract => {
|
||||
self.binary_op(|[a, b]| Ok(OpArgs::Unary(b.sub(a)?)))
|
||||
}
|
||||
CalculatorOperation::Multiply => {
|
||||
self.binary_op(|[a, b]| Ok(OpArgs::Unary(b.mul(a)?)))
|
||||
}
|
||||
CalculatorOperation::Divide => {
|
||||
self.binary_op(|[a, b]| Ok(OpArgs::Unary(b.div(a)?)))
|
||||
}
|
||||
CalculatorOperation::IntegerDivide => {
|
||||
self.binary_op(|[a, b]| Ok(OpArgs::Unary(b.int_divide(a)?)))
|
||||
}
|
||||
CalculatorOperation::Negate => self.unary_op(|a| Ok(OpArgs::Unary(a.negate()?))),
|
||||
CalculatorOperation::AbsoluteValue => self.unary_op(|a| Ok(OpArgs::Unary(a.abs()?))),
|
||||
CalculatorOperation::Inverse => self.unary_op(|a| Ok(OpArgs::Unary(a.inverse()?))),
|
||||
CalculatorOperation::Modulo => self.binary_op(|[a, b]| Ok(OpArgs::Unary(b.modulo(a)?))),
|
||||
CalculatorOperation::Negate => {
|
||||
self.unary_op(|a| Ok(OpArgs::Unary(a.negate()?)))
|
||||
}
|
||||
CalculatorOperation::AbsoluteValue => {
|
||||
self.unary_op(|a| Ok(OpArgs::Unary(a.abs()?)))
|
||||
}
|
||||
CalculatorOperation::Inverse => {
|
||||
self.unary_op(|a| Ok(OpArgs::Unary(a.inverse()?)))
|
||||
}
|
||||
CalculatorOperation::Modulo => {
|
||||
self.binary_op(|[a, b]| Ok(OpArgs::Unary(b.modulo(a)?)))
|
||||
}
|
||||
CalculatorOperation::Sin => {
|
||||
let angle_mode = self.angle_mode;
|
||||
self.unary_op(|a| Ok(OpArgs::Unary(a.sin(angle_mode)?)))
|
||||
@ -528,13 +558,21 @@ impl Calculator {
|
||||
let angle_mode = self.angle_mode;
|
||||
self.unary_op(|a| Ok(OpArgs::Unary(a.atan(angle_mode)?)))
|
||||
}
|
||||
CalculatorOperation::Sqrt => self.unary_op(|a| Ok(OpArgs::Unary(a.sqrt()?))),
|
||||
CalculatorOperation::Sqrt => {
|
||||
self.unary_op(|a| Ok(OpArgs::Unary(a.sqrt()?)))
|
||||
}
|
||||
CalculatorOperation::Log => self.unary_op(|a| Ok(OpArgs::Unary(a.log()?))),
|
||||
CalculatorOperation::Ln => self.unary_op(|a| Ok(OpArgs::Unary(a.ln()?))),
|
||||
CalculatorOperation::Pow => self.binary_op(|[a, b]| Ok(OpArgs::Unary(b.pow(a)?))),
|
||||
CalculatorOperation::Dup => self.unary_op(|a| Ok(OpArgs::Binary([a, a]))),
|
||||
CalculatorOperation::Pow => {
|
||||
self.binary_op(|[a, b]| Ok(OpArgs::Unary(b.pow(a)?)))
|
||||
}
|
||||
CalculatorOperation::Dup => {
|
||||
self.unary_op(|a| Ok(OpArgs::Binary([a.clone(), a])))
|
||||
}
|
||||
CalculatorOperation::Drop => self.unary_op(|_| Ok(OpArgs::None)),
|
||||
CalculatorOperation::Swap => self.binary_op(|[a, b]| Ok(OpArgs::Binary([b, a]))),
|
||||
CalculatorOperation::Swap => {
|
||||
self.binary_op(|[a, b]| Ok(OpArgs::Binary([b, a])))
|
||||
}
|
||||
CalculatorOperation::Undo => return self.history_op(false),
|
||||
CalculatorOperation::Redo => return self.history_op(true),
|
||||
// Macros are a no-op operator; need to insert for undo/redo
|
||||
@ -565,7 +603,11 @@ impl Calculator {
|
||||
}
|
||||
.last()
|
||||
.ok_or_else(|| {
|
||||
CalculatorError::EmptyHistory(String::from(if forward { "redo" } else { "undo" }))
|
||||
CalculatorError::EmptyHistory(String::from(if forward {
|
||||
"redo"
|
||||
} else {
|
||||
"undo"
|
||||
}))
|
||||
})?;
|
||||
|
||||
let target_history_mode = if forward {
|
||||
@ -648,12 +690,12 @@ impl Calculator {
|
||||
|
||||
match to_pop {
|
||||
OpArgs::Unary(a) => {
|
||||
self.stack_eq(0, *a)?;
|
||||
self.stack_eq(0, a)?;
|
||||
self.stack.pop_front();
|
||||
}
|
||||
OpArgs::Binary([a, b]) => {
|
||||
self.stack_eq(0, *a)?;
|
||||
self.stack_eq(1, *b)?;
|
||||
self.stack_eq(0, a)?;
|
||||
self.stack_eq(1, b)?;
|
||||
self.stack.pop_front();
|
||||
self.stack.pop_front();
|
||||
}
|
||||
@ -662,11 +704,11 @@ impl Calculator {
|
||||
|
||||
match to_push {
|
||||
OpArgs::Unary(a) => {
|
||||
self.stack.push_front(*a);
|
||||
self.stack.push_front(a.clone()); // TODO: Remove the clones
|
||||
}
|
||||
OpArgs::Binary([a, b]) => {
|
||||
self.stack.push_front(*b);
|
||||
self.stack.push_front(*a);
|
||||
self.stack.push_front(b.clone()); // TODO: Remove the clones
|
||||
self.stack.push_front(a.clone()); // TODO: Remove the clones
|
||||
}
|
||||
OpArgs::Macro(_) | OpArgs::None => {}
|
||||
};
|
||||
@ -681,8 +723,8 @@ impl Calculator {
|
||||
}
|
||||
|
||||
/// Checks if a value on the stack is equal to a given value
|
||||
fn stack_eq(&mut self, idx: usize, value: Entry) -> CalculatorResult<()> {
|
||||
if self.peek(idx)? == value {
|
||||
fn stack_eq(&mut self, idx: usize, value: &Entry) -> CalculatorResult<()> {
|
||||
if self.peek(idx)? == *value {
|
||||
Err(CalculatorError::CorruptStateChange(format!(
|
||||
"Stack index {} should be {}, but is {}",
|
||||
idx,
|
||||
@ -702,7 +744,7 @@ impl Calculator {
|
||||
// TODO: Use peek instead of stack.get()
|
||||
let arg = self.peek(0)?;
|
||||
Ok(CalculatorStateChange {
|
||||
pop: OpArgs::Unary(arg),
|
||||
pop: OpArgs::Unary(arg.clone()),
|
||||
push: op(arg)?,
|
||||
})
|
||||
}
|
||||
@ -713,7 +755,7 @@ impl Calculator {
|
||||
) -> CalculatorResult<CalculatorStateChange> {
|
||||
let args: [Entry; 2] = [self.peek(0)?, self.peek(1)?];
|
||||
Ok(CalculatorStateChange {
|
||||
pop: OpArgs::Binary(args),
|
||||
pop: OpArgs::Binary(args.clone()),
|
||||
push: op(args)?,
|
||||
})
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ impl PartialEq for Number {
|
||||
// pub value: Vec<Number>,
|
||||
// }
|
||||
|
||||
// TODO: Remove the copy trait
|
||||
#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
|
||||
#[serde(tag = "type")]
|
||||
pub enum Entry {
|
||||
@ -194,61 +195,61 @@ impl CalculatorEntry for Number {
|
||||
}
|
||||
fn add(&self, arg: Entry) -> CalculatorResult<Entry> {
|
||||
match arg {
|
||||
Entry::Number(Number { value }) => Ok(Entry::Number(Number {
|
||||
Entry::Number(Self { value }) => Ok(Entry::Number(Self {
|
||||
value: value + self.value,
|
||||
})),
|
||||
}
|
||||
}
|
||||
fn sub(&self, arg: Entry) -> CalculatorResult<Entry> {
|
||||
match arg {
|
||||
Entry::Number(Number { value }) => Ok(Entry::Number(Number {
|
||||
Entry::Number(Self { value }) => Ok(Entry::Number(Self {
|
||||
value: value - self.value,
|
||||
})),
|
||||
}
|
||||
}
|
||||
fn mul(&self, arg: Entry) -> CalculatorResult<Entry> {
|
||||
match arg {
|
||||
Entry::Number(Number { value }) => Ok(Entry::Number(Number {
|
||||
Entry::Number(Self { value }) => Ok(Entry::Number(Self {
|
||||
value: value * self.value,
|
||||
})),
|
||||
}
|
||||
}
|
||||
fn div(&self, arg: Entry) -> CalculatorResult<Entry> {
|
||||
match arg {
|
||||
Entry::Number(Number { value }) => Ok(Entry::Number(Number {
|
||||
Entry::Number(Self { value }) => Ok(Entry::Number(Self {
|
||||
value: value / self.value,
|
||||
})),
|
||||
}
|
||||
}
|
||||
fn int_divide(&self, arg: Entry) -> CalculatorResult<Entry> {
|
||||
match arg {
|
||||
Entry::Number(Number { value }) => Ok(Entry::Number(Number {
|
||||
Entry::Number(Self { value }) => Ok(Entry::Number(Self {
|
||||
value: value.div_euclid(self.value),
|
||||
})),
|
||||
}
|
||||
}
|
||||
fn negate(&self) -> CalculatorResult<Entry> {
|
||||
Ok(Entry::Number(Number { value: -self.value }))
|
||||
Ok(Entry::Number(Self { value: -self.value }))
|
||||
}
|
||||
fn abs(&self) -> CalculatorResult<Entry> {
|
||||
Ok(Entry::Number(Number {
|
||||
Ok(Entry::Number(Self {
|
||||
value: self.value.abs(),
|
||||
}))
|
||||
}
|
||||
fn inverse(&self) -> CalculatorResult<Entry> {
|
||||
Ok(Entry::Number(Number {
|
||||
Ok(Entry::Number(Self {
|
||||
value: self.value.recip(),
|
||||
}))
|
||||
}
|
||||
fn modulo(&self, arg: Entry) -> CalculatorResult<Entry> {
|
||||
match arg {
|
||||
Entry::Number(Number { value }) => Ok(Entry::Number(Number {
|
||||
Entry::Number(Self { value }) => Ok(Entry::Number(Self {
|
||||
value: value % self.value,
|
||||
})),
|
||||
}
|
||||
}
|
||||
fn sin(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult<Entry> {
|
||||
Ok(Entry::Number(Number {
|
||||
Ok(Entry::Number(Self {
|
||||
value: match angle_mode {
|
||||
CalculatorAngleMode::Degrees => self.value.to_radians().sin(),
|
||||
CalculatorAngleMode::Radians => self.value.sin(),
|
||||
@ -259,7 +260,7 @@ impl CalculatorEntry for Number {
|
||||
}))
|
||||
}
|
||||
fn cos(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult<Entry> {
|
||||
Ok(Entry::Number(Number {
|
||||
Ok(Entry::Number(Self {
|
||||
value: match angle_mode {
|
||||
CalculatorAngleMode::Degrees => self.value.to_radians().cos(),
|
||||
CalculatorAngleMode::Radians => self.value.cos(),
|
||||
@ -270,7 +271,7 @@ impl CalculatorEntry for Number {
|
||||
}))
|
||||
}
|
||||
fn tan(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult<Entry> {
|
||||
Ok(Entry::Number(Number {
|
||||
Ok(Entry::Number(Self {
|
||||
value: match angle_mode {
|
||||
CalculatorAngleMode::Degrees => self.value.to_radians().tan(),
|
||||
CalculatorAngleMode::Radians => self.value.tan(),
|
||||
@ -281,7 +282,7 @@ impl CalculatorEntry for Number {
|
||||
}))
|
||||
}
|
||||
fn asin(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult<Entry> {
|
||||
Ok(Entry::Number(Number {
|
||||
Ok(Entry::Number(Self {
|
||||
value: match angle_mode {
|
||||
CalculatorAngleMode::Degrees => self.value.asin().to_degrees(),
|
||||
CalculatorAngleMode::Radians => self.value.asin(),
|
||||
@ -292,7 +293,7 @@ impl CalculatorEntry for Number {
|
||||
}))
|
||||
}
|
||||
fn acos(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult<Entry> {
|
||||
Ok(Entry::Number(Number {
|
||||
Ok(Entry::Number(Self {
|
||||
value: match angle_mode {
|
||||
CalculatorAngleMode::Degrees => self.value.acos().to_degrees(),
|
||||
CalculatorAngleMode::Radians => self.value.acos(),
|
||||
@ -303,7 +304,7 @@ impl CalculatorEntry for Number {
|
||||
}))
|
||||
}
|
||||
fn atan(&self, angle_mode: CalculatorAngleMode) -> CalculatorResult<Entry> {
|
||||
Ok(Entry::Number(Number {
|
||||
Ok(Entry::Number(Self {
|
||||
value: match angle_mode {
|
||||
CalculatorAngleMode::Degrees => self.value.atan().to_degrees(),
|
||||
CalculatorAngleMode::Radians => self.value.atan(),
|
||||
@ -314,23 +315,23 @@ impl CalculatorEntry for Number {
|
||||
}))
|
||||
}
|
||||
fn sqrt(&self) -> CalculatorResult<Entry> {
|
||||
Ok(Entry::Number(Number {
|
||||
Ok(Entry::Number(Self {
|
||||
value: self.value.sqrt(),
|
||||
}))
|
||||
}
|
||||
fn log(&self) -> CalculatorResult<Entry> {
|
||||
Ok(Entry::Number(Number {
|
||||
Ok(Entry::Number(Self {
|
||||
value: self.value.log10(),
|
||||
}))
|
||||
}
|
||||
fn ln(&self) -> CalculatorResult<Entry> {
|
||||
Ok(Entry::Number(Number {
|
||||
Ok(Entry::Number(Self {
|
||||
value: self.value.ln(),
|
||||
}))
|
||||
}
|
||||
fn pow(&self, arg: Entry) -> CalculatorResult<Entry> {
|
||||
match arg {
|
||||
Entry::Number(Number { value }) => Ok(Entry::Number(Number {
|
||||
Entry::Number(Self { value }) => Ok(Entry::Number(Self {
|
||||
value: value.powf(self.value),
|
||||
})),
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user