commit 4db36eb57b6fe303a334d126e682c7f7bcb6e546
parent 5ee61f6ac45dbb8e0598e83badffae679c2de79f
Author: Zack Newman <zack@philomathiclife.com>
Date: Sun, 22 Oct 2023 16:39:07 -0600
minor doc fixes. deps update. minor clippy fixes.
Diffstat:
M | Cargo.toml | | | 6 | +++--- |
M | README.md | | | 123 | ++----------------------------------------------------------------------------- |
M | src/main.rs | | | 180 | +++++-------------------------------------------------------------------------- |
3 files changed, 15 insertions(+), 294 deletions(-)
diff --git a/Cargo.toml b/Cargo.toml
@@ -9,7 +9,7 @@ license = "MIT OR Apache-2.0"
name = "calc_rational"
readme = "README.md"
repository = "https://git.philomathiclife.com/repos/calc_rational/"
-version = "0.7.0"
+version = "0.8.0"
[lib]
name = "calc_lib"
@@ -23,8 +23,8 @@ path = "src/main.rs"
num-bigint = { version = "0.4.4", default-features = false }
num-integer = { version = "0.1.45", default-features = false }
num-rational = { version = "0.4.1", default-features = false, features = ["num-bigint"] }
-num-traits = { version = "0.2.16", default-features = false }
-priv_sep = { version = "0.6.1", default-features = false, features = ["openbsd"], optional = true }
+num-traits = { version = "0.2.17", default-features = false }
+priv_sep = { version = "0.7.0", default-features = false, features = ["openbsd"], optional = true }
rand = { version = "0.8.5", default-features = false, features = ["std", "std_rng"], optional = true }
[build-dependencies]
diff --git a/README.md b/README.md
@@ -155,7 +155,7 @@ it will error if [`pledge(2)`](https://man.openbsd.org/amd64/pledge.2) errors wi
## Exiting
-`q` with any number of spaces and tabs before and after will cause the program to terminate.
+`q` with any number of spaces and tabs before and after or sending `EOF` will cause the program to terminate.
### Status
@@ -170,126 +170,7 @@ The crates are only tested on the `x86_64-unknown-linux-gnu` and `x86_64-unknown
they should work on any [Tier 1 with Host Tools](https://doc.rust-lang.org/beta/rustc/platform-support.html)
target. Note one must be aware of the ASCII encoding requirement. In particular there are platforms
(e.g., Windows) where the default text encoding is not a superset of ASCII.
-
-### Installing
-
-```bash
-[zack@laptop ~]$ cargo install --all-features calc_rational
- Updating crates.io index
- Downloaded calc_rational v0.5.1
- Downloaded 1 crate (35.3 KB) in 0.60s
- Installing calc_rational v0.5.1
- Updating crates.io index
- Compiling autocfg v1.1.0
- Compiling semver v1.0.18
- Compiling libc v0.2.147
- Compiling cfg-if v1.0.0
- Compiling ppv-lite86 v0.2.17
- Compiling num-traits v0.2.16
- Compiling num-integer v0.1.45
- Compiling num-bigint v0.4.3
- Compiling num-rational v0.4.1
- Compiling rustc_version v0.4.0
- Compiling priv_sep v0.3.0
- Compiling calc_rational v0.5.1
- Compiling getrandom v0.2.10
- Compiling rand_core v0.6.4
- Compiling rand_chacha v0.3.1
- Compiling rand v0.8.5
- Finished release [optimized] target(s) in 6.92s
- Installing /home/zack/.cargo/bin/calc
- Installed package `calc_rational v0.5.1` (executable `calc`)
-```
-
-### Building and testing
-
-```bash
-[zack@laptop ~]$ git clone https://git.philomathiclife.com/repos/calc_rational
-Cloning into 'calc_rational'...
-[zack@laptop ~]$ cd calc_rational/
-[zack@laptop calc_rational]$ cargo build --release --all-features
- Updating crates.io index
- Compiling autocfg v1.1.0
- Compiling semver v1.0.18
- Compiling libc v0.2.147
- Compiling cfg-if v1.0.0
- Compiling ppv-lite86 v0.2.17
- Compiling num-traits v0.2.16
- Compiling num-integer v0.1.45
- Compiling num-bigint v0.4.3
- Compiling num-rational v0.4.1
- Compiling rustc_version v0.4.0
- Compiling priv_sep v0.3.0
- Compiling calc_rational v0.5.1 (/home/zack/calc_rational)
- Compiling getrandom v0.2.10
- Compiling rand_core v0.6.4
- Compiling rand_chacha v0.3.1
- Compiling rand v0.8.5
- Finished release [optimized] target(s) in 6.10s
-[zack@laptop calc_rational]$ cargo t --all-features
- Compiling autocfg v1.1.0
- Compiling semver v1.0.18
- Compiling libc v0.2.147
- Compiling cfg-if v1.0.0
- Compiling ppv-lite86 v0.2.17
- Compiling num-traits v0.2.16
- Compiling num-integer v0.1.45
- Compiling num-bigint v0.4.3
- Compiling num-rational v0.4.1
- Compiling rustc_version v0.4.0
- Compiling priv_sep v0.3.0
- Compiling calc_rational v0.5.1 (/home/zack/calc_rational)
- Compiling getrandom v0.2.10
- Compiling rand_core v0.6.4
- Compiling rand_chacha v0.3.1
- Compiling rand v0.8.5
- Finished test [unoptimized + debuginfo] target(s) in 2.38s
- Running unittests src/lib.rs (target/debug/deps/calc_lib-cd811ad9fff78426)
-
-running 26 tests
-test cache::tests::test_get ... ok
-test cache::tests::test_index ... ok
-test cache::tests::test_is_empty ... ok
-test cache::tests::test_new ... ok
-test cache::tests::test_get_unsafe ... ok
-test cache::tests::test_push ... ok
-test tests::abs ... ok
-test tests::add ... ok
-test cache::tests::test_len ... ok
-test cache::tests::test_index_panic - should panic ... ok
-test tests::exit ... ok
-test tests::rand_uni ... ignored
-test tests::eval_iter ... ok
-test tests::factorial ... ok
-test tests::neg ... ok
-test tests::empty ... ok
-test tests::recall_expression ... ok
-test tests::round ... ok
-test tests::store ... ok
-test tests::par ... ok
-test tests::eval ... ok
-test tests::number_literal ... ok
-test tests::term ... ok
-test tests::exp ... ok
-test tests::mult ... ok
-test tests::rand ... ok
-
-test result: ok. 25 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 0.01s
-
- Running unittests src/main.rs (target/debug/deps/calc-36458944d29cbbaf)
-
-running 0 tests
-
-test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
-
- Doc-tests calc_lib
-
-running 0 tests
-
-test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
-
-```
-
+
#### Formal language specification
For a more precise specification of the “calc language”, one can read the
diff --git a/src/main.rs b/src/main.rs
@@ -1,166 +1,6 @@
-//! # `calc`
-//!
-//! `calc` is a CLI calculator for basic
-//! rational number arithmetic using standard operator precedence and associativity. Internally, it is
-//! based on [`Ratio<T>`](https://docs.rs/num/latest/num/rational/struct.Ratio.html)
-//! and [`BigInt`](https://docs.rs/num-bigint/latest/num_bigint/struct.BigInt.html).
-//!
-//! ## Calc in action
-//!
-//! ```bash
-//! [zack@laptop ~]$ calc
-//! 2.71828^0^3.14159 + -1!
-//! > 0
-//! s
-//! > 0
-//! @^0
-//! > 1
-//! s
-//! > 1
-//! @/3 * 3
-//! > 1
-//! s
-//! > 1
-//! |@2 - 9|^(1 - 2*3)
-//! > 1/32768
-//! s
-//! > 1/32768
+//! # `calc`
//!
-//! > 0.000030517578125
-//! round(@, 3)
-//! > 0
-//! round(@, 6)
-//! > 31/1000000
-//!
-//! > 0.000031
-//! 2/3
-//! > 2/3
-//!
-//! > 0.666666667
-//! rand()
-//! > 939435294927814822
-//! rand(1+9,10!)
-//! > 2660936
-//! 1+4 mod 2 + 1
-//! > 2
-//! -5 mod 2
-//! > 1
-//! -5 mod -2
-//! > 1
-//! 5 mod -2
-//! > 1
-//! 9^0.5
-//! > 3
-//! (4/9)^(-1/2)
-//! > 3/2
-//! q
-//! [zack@laptop ~]$
-//! ```
-//!
-//! ## Expressions
-//!
-//! The following are the list of expressions in descending order of precedence:
-//! 1. number literals, `@`, `()`, `||`, `round()`, `rand()`
-//! 2. `!`
-//! 3. `^`
-//! 4. `-` (unary negation operator)
-//! 5. `*`, `/`, `mod`
-//! 6. `+`, `-`
-//!
-//! All binary operators are left-associative sans `^` which is right-associative.
-//!
-//! Any expression is allowed to be enclosed in `()`. Note that parentheses are purely for grouping expressions;
-//! in particular, you cannot use them to represent multiplication (e.g., `4(2)` is grammatically incorrect and
-//! will result in an error message).
-//!
-//! Any expression is allowed to be enclosed in `||`. This unary operator represents absolute value.
-//!
-//! `!` is the factorial operator. Due to its high precedence, something like *-i!^j!* for *i, j ∈ ℕ* is
-//! the same thing as *-((i!)^(j!))*. If the expression preceding it does not evaluate to a non-negative integer,
-//! then an error will be displayed. Spaces and tabs are *not* ignored; so `1 !` is grammatically incorrect and
-//! will result in an error message.
-//!
-//! `^` is the exponentiation operator. The expression left of the operator can evaluate to any rational number;
-//! however the expression right of the operator must evaluate to an integer or ±1/2 unless the expression on
-//! the left evaluates to `0` or `1`. In the event of the former, the expression right of the operator must evaluate
-//! to a non-negative rational number. In the event of the latter, the expression right of the operator can evaluate to
-//! any rational number. Note that `0^0` is defined to be 1. When the operand right of `^` evaluates to ±1/2, then
-//! the left operand must be the square of a rational number.
-//!
-//! The unary operator `-` represents negation.
-//!
-//! The operators `*` and `/` represent multiplication and division respectively. Expressions right of `/`
-//! must evaluate to any non-zero rational number; otherwise an error will be displayed.
-//!
-//! The binary operator `mod` represents modulo such that *n mod m = r = n - m\*q* for *n,q ∈ ℤ, m ∈ ℤ\\{0}, and r ∈ ℕ*
-//! where *r* is the minimum non-negative solution.
-//!
-//! The binary operators `+` and `-` represent addition and subtraction respectively.
-//!
-//! With the aforementioned exception of `!`, all spaces and tabs before and after operators are ignored.
-//!
-//! ## Round expression
-//!
-//! `round(expression, digit)` rounds `expression` to `digit`-number of fractional digits. An error will
-//! be displayed if called incorrectly.
-//!
-//! ## Rand expression
-//!
-//! `rand(expression, expression)` generates a random 64-bit integer inclusively between the passed expressions.
-//! An error will be displayed if called incorrectly. `rand()` generates a random 64-bit integer.
-//!
-//! ## Numbers
-//!
-//! A number literal is a non-empty sequence of digits or a non-empty sequence of digits immediately followed by `.`
-//! which is immediately followed by a non-empty sequence of digits (e.g., `134.901`). This means that number
-//! literals represent precisely all rational numbers that are equivalent to a ratio of a non-negative integer
-//! to a positive integer whose sole prime factors are 2 or 5. To represent all other rational numbers, the unary
-//! operator `-` and binary operator `/` must be used.
-//!
-//! ## Empty expression
-//!
-//! The empty expression (i.e., expression that at most only consists of spaces and tabs) will return
-//! the result from the previous non-(empty/store) expression in *decimal* form using the minimum number of digits.
-//! In the event an infinite number of digits is required, it will be rounded to 9 fractional digits using normal rounding
-//! rules first.
-//!
-//! ## Store expression
-//!
-//! To store the result of the previous non-(empty/store) expression, one simply passes `s`. In addition to storing the
-//! result which will subsequently be available via `@`, it displays the result. At most 8 results can be stored at once;
-//! at which point, results that are stored overwrite the oldest result.
-//!
-//! ## Recall expression
-//!
-//! `@` is used to recall previously stored results. It can be followed by any *digit* from `1` to `8`.
-//! If such a digit does not immediately follow it, then it will be interpreted as if there were a `1`.
-//! `@i` returns the *i*-th most-previous stored result where *i ∈ {1, 2, 3, 4, 5, 6, 7, 8}*.
-//! Note that spaces and tabs are *not* ignored so `@ 2` is grammatically incorrect and will result in an error message.
-//! As emphasized, it does not work on expressions; so both `@@` and `@(1)` are grammatically incorrect.
-//!
-//! ## Character encoding
-//!
-//! All inputs must only contain the ASCII encoding of the following Unicode scalar values: `0`-`9`, `.`, `+`, `-`,
-//! `*`, `/`, `^`, `!`, `mod`, `|`, `(`, `)`, `round`, `rand`, `,`, `@`, `s`, <space>, <tab>,
-//! <line feed>, <carriage return>, and `q`. Any other byte sequences are grammatically incorrect and will
-//! lead to an error message.
-//!
-//! ## Errors
-//!
-//! Errors due to a language violation (e.g., dividing by `0`) manifest into an error message. `panic!`s
-//! and [`io::Error`](https://doc.rust-lang.org/std/io/struct.Error.html)s caused by writing to the global
-//! standard output stream lead to program abortion. On OpenBSD-stable when compiled with the `priv_sep` feature,
-//! it will error if [`pledge(2)`](https://man.openbsd.org/amd64/pledge.2) errors with the promise of
-//! `"stdio"`.
-//!
-//! ## Exiting
-//!
-//! `q` with any number of spaces and tabs before and after will cause the program to terminate.
-//!
-//! ### Formal language specification
-//!
-//! For a more precise specification of the “calc language”, one can read the
-//! [calc language specification](https://git.philomathiclife.com/calc_rational/lang.pdf).
+//! Consult [`README.md`](https://crates.io/crates/calc_rational).
#![cfg_attr(all(doc, CHANNEL_NIGHTLY), feature(doc_auto_cfg))]
#![deny(
unsafe_code,
@@ -195,11 +35,11 @@ use std::io::{self, Error, Write};
/// Error returned by [`main`].
#[allow(clippy::exhaustive_enums)]
#[derive(Debug)]
-pub enum Err {
- // Error returned from [`writeln`].
- Error(Error),
+enum Err {
+ /// Error returned from [`writeln`].
+ Io(Error),
#[cfg(all(feature = "priv_sep", target_os = "openbsd"))]
- // Error returned from [`pledge`].
+ /// Error returned from [`pledge`].
Pledge(Error),
}
impl Display for Err {
@@ -207,7 +47,7 @@ impl Display for Err {
#[inline]
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match *self {
- Self::Error(ref e) => e.fmt(f),
+ Self::Io(ref e) => e.fmt(f),
#[cfg(all(feature = "priv_sep", target_os = "openbsd"))]
Self::Pledge(ref e) => write!(f, "pledge(2)ing 'stdio' failed with {e}"),
}
@@ -237,14 +77,14 @@ fn main() -> Result<(), Err> {
const fn privsep() -> Result<(), Err> {
Ok(())
}
- privsep().and_then(|_| {
+ privsep().and_then(|()| {
let mut out = io::stdout().lock();
- EvalIter::new(io::stdin().lock()).lend_try_fold((), |_, res| {
+ EvalIter::new(io::stdin().lock()).lend_try_fold((), |(), res| {
match res {
Ok(o) => writeln!(&mut out, "{o}"),
Err(e) => writeln!(&mut out, "{e}"),
}
- .map_err(Err::Error)
+ .map_err(Err::Io)
})
})
}