summaryrefslogtreecommitdiff
path: root/src/eval
diff options
context:
space:
mode:
authorSekoiaTree <51149447+SekoiaTree@users.noreply.github.com>2023-04-25 11:18:27 +0200
committerGitHub <noreply@github.com>2023-04-25 11:18:27 +0200
commitefad1e71fa699e0d2413d3a6a3ce5a4163e38112 (patch)
tree64dd37c540989e71408ee005abdccdb523d76618 /src/eval
parent12129f01707a3389ef90a4c78a872e1c7897a752 (diff)
Add sum and product to arrays (#966)
Diffstat (limited to 'src/eval')
-rw-r--r--src/eval/array.rs35
-rw-r--r--src/eval/methods.rs2
2 files changed, 37 insertions, 0 deletions
diff --git a/src/eval/array.rs b/src/eval/array.rs
index b04fdab8..1166ce94 100644
--- a/src/eval/array.rs
+++ b/src/eval/array.rs
@@ -24,6 +24,7 @@ macro_rules! __array {
#[doc(inline)]
pub use crate::__array as array;
+use crate::eval::ops::{add, mul};
#[doc(hidden)]
pub use ecow::eco_vec;
@@ -199,6 +200,40 @@ impl Array {
Ok(acc)
}
+ /// Calculates the sum of the array's items
+ pub fn sum(&self, default: Option<Value>, span: Span) -> SourceResult<Value> {
+ let mut acc = self
+ .first()
+ .map(|x| x.clone())
+ .or_else(|_| {
+ default.ok_or_else(|| {
+ eco_format!("cannot calculate sum of empty array with no default")
+ })
+ })
+ .at(span)?;
+ for i in self.iter().skip(1) {
+ acc = add(acc, i.clone()).at(span)?;
+ }
+ Ok(acc)
+ }
+
+ /// Calculates the product of the array's items
+ pub fn product(&self, default: Option<Value>, span: Span) -> SourceResult<Value> {
+ let mut acc = self
+ .first()
+ .map(|x| x.clone())
+ .or_else(|_| {
+ default.ok_or_else(|| {
+ eco_format!("cannot calculate product of empty array with no default")
+ })
+ })
+ .at(span)?;
+ for i in self.iter().skip(1) {
+ acc = mul(acc, i.clone()).at(span)?;
+ }
+ Ok(acc)
+ }
+
/// Whether any item matches.
pub fn any(&self, vm: &mut Vm, func: Func) -> SourceResult<bool> {
for item in self.iter() {
diff --git a/src/eval/methods.rs b/src/eval/methods.rs
index 56d1c7b7..29b729cb 100644
--- a/src/eval/methods.rs
+++ b/src/eval/methods.rs
@@ -105,6 +105,8 @@ pub fn call(
"fold" => {
array.fold(vm, args.expect("initial value")?, args.expect("function")?)?
}
+ "sum" => array.sum(args.named("default")?, span)?,
+ "product" => array.product(args.named("default")?, span)?,
"any" => Value::Bool(array.any(vm, args.expect("function")?)?),
"all" => Value::Bool(array.all(vm, args.expect("function")?)?),
"flatten" => Value::Array(array.flatten()),