aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--native/thulani_calc/Cargo.lock101
-rw-r--r--native/thulani_calc/Cargo.toml10
-rw-r--r--native/thulani_calc/README.md19
-rw-r--r--native/thulani_calc/src/lib.rs214
4 files changed, 72 insertions, 272 deletions
diff --git a/native/thulani_calc/Cargo.lock b/native/thulani_calc/Cargo.lock
index 3504dc8..c1fdc2c 100644
--- a/native/thulani_calc/Cargo.lock
+++ b/native/thulani_calc/Cargo.lock
@@ -68,9 +68,9 @@ dependencies = [
[[package]]
name = "digest"
-version = "0.10.6"
+version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f"
+checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer",
"crypto-common",
@@ -99,9 +99,15 @@ dependencies = [
[[package]]
name = "heck"
-version = "0.4.0"
+version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
+checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
+
+[[package]]
+name = "inventory"
+version = "0.3.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f958d3d68f4167080a18141e10381e7634563984a537f2a49a30fd8e53ac5767"
[[package]]
name = "lazy_static"
@@ -122,15 +128,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb"
[[package]]
-name = "log"
-version = "0.4.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
-dependencies = [
- "cfg-if",
-]
-
-[[package]]
name = "matrixmultiply"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -171,7 +168,7 @@ checksum = "01fcc0b8149b4632adc89ac3b7b31a12fb6099a0317a4eb2ebff574ef7de7218"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 1.0.105",
]
[[package]]
@@ -228,19 +225,20 @@ checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1"
[[package]]
name = "pest"
-version = "2.5.1"
+version = "2.7.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc8bed3549e0f9b0a2a78bf7c0018237a2cdf085eecbbc048e52612438e4e9d0"
+checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95"
dependencies = [
+ "memchr",
"thiserror",
"ucd-trie",
]
[[package]]
name = "pest_derive"
-version = "2.5.1"
+version = "2.7.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cdc078600d06ff90d4ed238f0119d84ab5d43dbaad278b0e33a8820293b32344"
+checksum = "2a548d2beca6773b1c244554d36fcf8548a8a58e74156968211567250e48e49a"
dependencies = [
"pest",
"pest_generator",
@@ -248,26 +246,26 @@ dependencies = [
[[package]]
name = "pest_generator"
-version = "2.5.1"
+version = "2.7.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28a1af60b1c4148bb269006a750cff8e2ea36aff34d2d96cf7be0b14d1bed23c"
+checksum = "3c93a82e8d145725dcbaf44e5ea887c8a869efdcc28706df2d08c69e17077183"
dependencies = [
"pest",
"pest_meta",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.72",
]
[[package]]
name = "pest_meta"
-version = "2.5.1"
+version = "2.7.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fec8605d59fc2ae0c6c1aefc0c7c7a9769732017c0ce07f7a9cfffa7b4404f20"
+checksum = "a941429fea7e08bedec25e4f6785b6ffaacc6b755da98df5ef3e7dcf4a124c4f"
dependencies = [
"once_cell",
"pest",
- "sha1",
+ "sha2",
]
[[package]]
@@ -278,18 +276,18 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "proc-macro2"
-version = "1.0.47"
+version = "1.0.86"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
+checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
-version = "1.0.21"
+version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
+checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
dependencies = [
"proc-macro2",
]
@@ -359,32 +357,33 @@ checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
[[package]]
name = "rustler"
-version = "0.26.0"
+version = "0.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d61e8ddf75de20513455d7b6f17241a595abbb01b53a6340cecc798a1b13422d"
+checksum = "e94bdfa68c0388cbd725f1ca54e975956482c262599e5cced04a903eec918b7f"
dependencies = [
- "lazy_static",
+ "inventory",
"rustler_codegen",
"rustler_sys",
]
[[package]]
name = "rustler_codegen"
-version = "0.26.0"
+version = "0.34.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "baa2e45c0165272070f80ce93bcd7dd5407a3c84a1ef73ab9900e00f00ef3d36"
+checksum = "996dc019acb78b91b4e0c1bd6fa2cd509a835d309de762dc15213b97eac399da"
dependencies = [
"heck",
+ "inventory",
"proc-macro2",
"quote",
- "syn",
+ "syn 2.0.72",
]
[[package]]
name = "rustler_sys"
-version = "2.2.0"
+version = "2.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ff26a42e62d538f82913dd34f60105ecfdffbdb25abdc3c3580b0c622285332"
+checksum = "ddd0e2c955cfc86ea4680067e1d5e711427b43f7befcb6e23c7807cf3dd90e97"
dependencies = [
"regex",
"unreachable",
@@ -400,10 +399,10 @@ dependencies = [
]
[[package]]
-name = "sha1"
-version = "0.10.5"
+name = "sha2"
+version = "0.10.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3"
+checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
dependencies = [
"cfg-if",
"cpufeatures",
@@ -448,6 +447,17 @@ dependencies = [
]
[[package]]
+name = "syn"
+version = "2.0.72"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
name = "thiserror"
version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -464,19 +474,26 @@ checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb"
dependencies = [
"proc-macro2",
"quote",
- "syn",
+ "syn 1.0.105",
+]
+
+[[package]]
+name = "thulani_calc"
+version = "0.1.0"
+dependencies = [
+ "rustler",
+ "thulani_calc 0.1.0 (git+https://pub.npry.dev/thulani)",
]
[[package]]
name = "thulani_calc"
version = "0.1.0"
+source = "git+https://pub.npry.dev/thulani#ba827ea23b170365e86564912bf7c213af1b0c2f"
dependencies = [
"lazy_static",
- "log",
"pest",
"pest_derive",
"rand",
- "rustler",
"statrs",
"thiserror",
]
diff --git a/native/thulani_calc/Cargo.toml b/native/thulani_calc/Cargo.toml
index 8ba8a75..0bb638c 100644
--- a/native/thulani_calc/Cargo.toml
+++ b/native/thulani_calc/Cargo.toml
@@ -10,11 +10,5 @@ path = "src/lib.rs"
crate-type = ["cdylib"]
[dependencies]
-rustler = "0.26.0"
-pest = "2.5"
-pest_derive = "2.5"
-lazy_static = "1.4"
-statrs = "0.16"
-thiserror = "1.0"
-rand = "0.8"
-log = "0.4"
+rustler = "0.34"
+thulani_calc.git = "https://pub.npry.dev/thulani"
diff --git a/native/thulani_calc/README.md b/native/thulani_calc/README.md
index 03e1510..e8c1e8a 100644
--- a/native/thulani_calc/README.md
+++ b/native/thulani_calc/README.md
@@ -1,20 +1 @@
# NIF for Elixir.Thulani.Calc
-
-## To build the NIF module:
-
-- Your NIF will now build along with your project.
-
-## To load the NIF:
-
-```elixir
-defmodule Thulani.Calc do
- use Rustler, otp_app: :thulani, crate: "thulani_calc"
-
- # When your NIF is loaded, it will override this function.
- def add(_a, _b), do: :erlang.nif_error(:nif_not_loaded)
-end
-```
-
-## Examples
-
-[This](https://github.com/rusterlium/NifIo) is a complete example of a NIF written in Rust.
diff --git a/native/thulani_calc/src/lib.rs b/native/thulani_calc/src/lib.rs
index 75a6b37..23a8aea 100644
--- a/native/thulani_calc/src/lib.rs
+++ b/native/thulani_calc/src/lib.rs
@@ -1,215 +1,23 @@
-use log::error;
-use rand::prelude::*;
-use statrs;
-use thiserror::Error;
-use lazy_static::lazy_static;
use rustler::Encoder;
-mod atoms {
- rustler::atoms! {
- ok,
- error,
- inf,
- ninf,
- nan,
- }
+rustler::atoms! {
+ ok,
+ error,
+ inf,
+ ninf,
+ nan,
}
#[rustler::nif]
pub fn eval<'a>(env: rustler::Env<'a>, args: String) -> Result<rustler::Term<'a>, String> {
- Calc::eval(&args)
+ thulani_calc::Calc::eval(&args)
.map(|x| match x {
- f64::INFINITY => atoms::inf().encode(env),
- f64::NEG_INFINITY => atoms::ninf().encode(env),
- x if x.is_nan() => atoms::nan().encode(env),
+ x if x.is_infinite() && x.is_sign_positive() => inf().encode(env),
+ x if x.is_infinite() && x.is_sign_negative() => ninf().encode(env),
+ x if x.is_nan() => nan().encode(env),
x => x.encode(env),
})
.map_err(|e| e.to_string())
}
-rustler::init!("Elixir.Thulani.Calc", [eval]);
-
-
-#[derive(pest_derive::Parser)]
-#[grammar = "calc.pest"]
-struct Calc;
-
-#[derive(Copy, Clone, Error, Debug, PartialEq, Eq, Hash)]
-pub(crate) enum CalcError {
- #[error("pest was unable to parse the input")]
- Pest,
-
- #[error("invalid number format")]
- NumberFormat,
-
- #[error("bad argument count")]
- ArgCount,
-}
-
-impl Calc {
- fn eval<S: AsRef<str>>(s: S) -> Result<f64, CalcError> {
- use pest::{
- Parser,
- prec_climber::PrecClimber,
- iterators::{Pair, Pairs},
- };
-
- use self::Rule::*;
-
- lazy_static! {
- static ref CLIMBER: PrecClimber<self::Rule> = {
- use pest::prec_climber::{
- Operator,
- Assoc::*,
- };
-
- PrecClimber::new(vec![
- Operator::new(add, Left) | Operator::new(sub, Left) | Operator::new(modulo, Left),
- Operator::new(mul, Left) | Operator::new(div, Left),
- Operator::new(dice, Left),
- Operator::new(pow, Right),
- ])
- };
- }
-
- let result = Calc::parse(calc, s.as_ref()).map_err(|_| CalcError::Pest)?;
-
- fn eval_single_pair(pair: Pair<self::Rule>) -> Result<f64, CalcError> {
- let result = match pair.as_rule() {
- oct | hex | binary => {
- let base = match pair.as_rule() {
- hex => 16,
- oct => 8,
- binary => 2,
- _ => unreachable!(),
- };
-
- u64::from_str_radix(&pair.as_str()[2..], base).map_err(|_| CalcError::NumberFormat)? as f64
- },
- float => pair.as_str().parse::<f64>().map_err(|_| CalcError::NumberFormat)?,
- expr | num => eval_expr(pair.into_inner())?,
- unary_expr => {
- let mut p = pair.into_inner();
-
- let op = p.next().ok_or(CalcError::ArgCount)?;
- let arg = eval_expr(p)?;
-
- match op.as_rule() {
- log => arg.ln(),
- sqrt => arg.sqrt(),
- sgn => arg.signum(),
-
- sin => arg.sin(),
- cos => arg.cos(),
- tan => arg.tan(),
- asin => arg.asin(),
- acos => arg.acos(),
- atan => arg.atan(),
-
- sinh => arg.sinh(),
- cosh => arg.cosh(),
- tanh => arg.tanh(),
- asinh => arg.asinh(),
- acosh => arg.acosh(),
- atanh => arg.atanh(),
-
- exp => arg.exp(),
- abs => arg.abs(),
- ceil => arg.ceil(),
- floor => arg.floor(),
- round => arg.round(),
- _ => unreachable!(),
- }
- },
- binary_expr => {
- let mut p = pair.into_inner();
-
- let op = p.next().ok_or(CalcError::ArgCount)?;
-
- let arg1 = eval_single_pair(p.next().ok_or(CalcError::ArgCount)?)?;
- let arg2 = eval_single_pair(p.next().ok_or(CalcError::ArgCount)?)?;
-
- assert!(p.next().is_none());
-
- match op.as_rule() {
- min => arg1.min(arg2),
- max => arg1.max(arg2),
- atan2 => arg1.atan2(arg2),
- _ => unreachable!(),
- }
- },
- suffix_expr => {
- let mut p = pair.into_inner();
-
- let arg = eval_expr(p.next().ok_or(CalcError::ArgCount)?.into_inner())?;
- let op = p.next().ok_or(CalcError::ArgCount)?;
-
- assert!(p.next().is_none());
-
- match op.as_rule() {
- factorial => statrs::function::gamma::gamma(arg + 1.),
- _ => unreachable!(),
- }
- },
- _ => unreachable!(),
- };
-
- Ok(result)
- }
-
- fn eval_expr(p: Pairs<self::Rule>) -> Result<f64, CalcError> {
- CLIMBER.climb(
- p,
- eval_single_pair,
- |lhs, op, rhs| {
- let lhs = lhs?;
- let rhs = rhs?;
-
- let result = match op.as_rule() {
- add => lhs + rhs,
- sub => lhs - rhs,
- mul => lhs * rhs,
- div => lhs / rhs,
- pow => lhs.powf(rhs),
- dice => {
- let dice_count = lhs as usize;
- let dice_faces = rhs as usize;
-
- let mut rng = thread_rng();
- (0..dice_count).map(|_| rng.gen_range(1..=dice_faces)).sum::<usize>() as f64
- },
- _ => unreachable!(),
- };
-
- Ok(result)
- }
- )
- }
-
- eval_expr(result)
- }
-}
-
-#[cfg(test)]
-mod test {
- use super::*;
-
- #[test]
- fn test_calc_basics() {
- assert_eq!(3., Calc::eval("1 + 2").unwrap());
- assert_eq!(3.0f64.ln(), Calc::eval("log 3").unwrap());
- assert!(6. - Calc::eval("3!").unwrap() < 0.0001);
- assert_eq!(3., Calc::eval("max 3 2").unwrap());
- }
-
- #[test]
- fn test_binary_unary() {
- assert_eq!(3.0f64.ln(), Calc::eval("max log 3 log 2").unwrap());
- }
-
- #[test]
- fn test_prefix_suffix() {
- assert!(6. - Calc::eval("abs 3!").unwrap() < 0.0001);
- }
-}
-
+rustler::init!("Elixir.Thulani.Calc");