Crates.io | arithmetic-eval |
lib.rs | arithmetic-eval |
version | 0.4.0-beta.1 |
source | src |
created_at | 2020-06-01 20:19:20.149258 |
updated_at | 2024-09-22 19:19:38.574524 |
description | Simple interpreter for arithmetic expressions. |
homepage | |
repository | https://github.com/slowli/arithmetic-parser |
max_upload_size | |
id | 248802 |
size | 440,772 |
This library provides a simple interpreter, which can be used for some grammars
recognized by arithmetic-parser
, e.g., integer-, real-, complex-valued and modular arithmetic.
(Both built-in integer types and big integers from num-bigint
are supported.)
The interpreter provides support for native functions,
which allows to overcome some syntax limitations (e.g., the lack of control flow
can be solved with native if
/ while
functions). Native functions and opaque reference types
allow effectively embedding the interpreter into larger Rust applications.
The interpreter is somewhat opinionated on how to interpret language features
(e.g., in terms of arithmetic ops for tuple / object arguments).
On the other hand, handling primitive types is fully customizable, just like their parsing
in arithmetic-parser
.
The primary goal is to be intuitive for simple grammars (such as the aforementioned
real-valued arithmetic).
The interpreter is quite slow – 1–2 orders of magnitude slower than native arithmetic.
Add this to your Crate.toml
:
[dependencies]
arithmetic-eval = "0.4.0-beta.1"
A simple script relying entirely on standard functions.
minmax = |...xs| xs.fold(#{ min: INF, max: -INF }, |acc, x| #{
min: if(x < acc.min, x, acc.min),
max: if(x > acc.max, x, acc.max),
});
assert_eq(minmax(3, 7, 2, 4).min, 2);
assert_eq(minmax(5, -4, 6, 9, 1), #{ min: -4, max: 9 });
Recursive quick sort implementation:
sort = defer(|sort| {
// `defer` allows to define a function recursively
|xs| {
if(xs == (), || (), || {
(pivot, ...rest) = xs;
lesser_part = sort(rest.filter(|x| x < pivot));
greater_part = sort(rest.filter(|x| x >= pivot));
lesser_part.push(pivot).merge(greater_part)
})()
}
});
assert_eq(sort((1, 7, -3, 2, -1, 4, 2)), (-3, -1, 1, 2, 2, 4, 7));
// Generate a larger array to sort. `rand_num` is a custom native function
// that generates random numbers in the specified range.
xs = sort(array(1000, |_| rand_num(0, 100)));
// Check that elements in `xs` are monotonically non-decreasing.
{ sorted } = xs.fold(
#{ prev: -1, sorted: true },
|{ prev, sorted }, x| #{
prev: x,
sorted: sorted && prev <= x
},
);
assert(sorted);
Defining a type:
Vector = {
len = |{ x, y }| sqrt(x * x + y * y);
scale = |self| if(self.x == 0 && self.y == 0,
|| self,
|| self / self.len(),
)();
#{ len, scale }
};
assert_close(#{ x: 3, y: 4 }.{Vector.len}(), 5);
// ...is same as
assert_close({Vector.len}(#{ x: 3, y: 4 }), 5);
scaled = #{ x: 3, y: -4 }.{Vector.scale}();
assert_close(scaled.x, 0.6);
assert_close(scaled.y, -0.8);
Please see the crate docs and examples for more examples.
arithmetic-typing
is a type checker / inference tool for ASTs evaluated
by this crate.Licensed under either of Apache License, Version 2.0 or MIT license at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in arithmetic-eval
by you, as defined in the Apache-2.0 license,
shall be dual licensed as above, without any additional terms or conditions.