5 releases (3 breaking)
0.4.0-beta.1 | Sep 22, 2024 |
---|---|
0.3.0 | May 24, 2021 |
0.2.0 | Dec 5, 2020 |
0.2.0-beta.1 | Oct 4, 2020 |
0.1.0 | Jun 1, 2020 |
#251 in Programming languages
505KB
11K
SLoC
Simple Arithmetic Interpreter
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.
Usage
Add this to your Crate.toml
:
[dependencies]
arithmetic-eval = "0.4.0-beta.1"
Script samples
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.
See also
arithmetic-typing
is a type checker / inference tool for ASTs evaluated by this crate.
License
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.
Dependencies
~1.2–2MB
~38K SLoC