///|
/// Evaluate Reduce
fn eval_reduce(
expr : Expr,
var_name : String,
init_expr : Expr,
update_expr : Expr,
input : Json,
env : Env,
) -> Iter[Json] raise InterpreterError {
let init_results = eval_with_env(init_expr, input, env).collect()
match init_results {
[] => Iter::singleton(null)
[first, ..] => {
let accumulator = eval_with_env(expr, input, env).fold(init=first, fn(
acc,
item,
) raise InterpreterError {
let new_env = env.set(var_name, item)
let update_results = eval_with_env(update_expr, acc, new_env).collect()
match update_results {
[] => acc
[next, ..] => next
}
})
Iter::singleton(accumulator)
}
}
}
///|
/// Evaluate SortBy
fn eval_sort_by(
expr : Expr,
input : Json,
env : Env,
) -> Iter[Json] raise InterpreterError {
guard input is Array(arr) else {
raise TypeMismatch("array", @ast_internal.json_type_name(input))
}
let pairs = arr.map(elem => {
let keys = eval_with_env(expr, elem, env).collect()
let sort_key = match keys {
[] => null
[first, ..] => first
}
(elem, sort_key)
})
pairs.sort_by(fn(a, b) { compare_json(a.1, b.1) })
let sorted = pairs.map(fn(p) { p.0 })
Iter::singleton(Json::array(sorted))
}
///|
/// Evaluate GroupBy
fn eval_group_by(
expr : Expr,
input : Json,
env : Env,
) -> Iter[Json] raise InterpreterError {
guard input is Array(arr) else {
raise TypeMismatch("array", @ast_internal.json_type_name(input))
}
let groups : Map[String, Array[Json]] = Map([])
for elem in arr {
let keys = eval_with_env(expr, elem, env).collect()
let key_json = match keys {
[] => null
[first, ..] => first
}
let key_str = @debug.to_string(key_json)
groups.update(key_str, fn(existing) {
match existing {
Some(group) => {
group.push(elem)
Some(group)
}
None => Some([elem])
}
})
}
let result = groups.values().map(Json::array).collect()
Iter::singleton(Json::array(result))
}
///|
/// Evaluate Any
fn eval_any(input : Json) -> Iter[Json] raise InterpreterError {
guard input is Array(arr) else {
raise TypeMismatch("array", @ast_internal.json_type_name(input))
}
Iter::singleton(Json::boolean(arr.any(@ast_internal.is_truthy)))
}
///|
/// Evaluate All
fn eval_all(input : Json) -> Iter[Json] raise InterpreterError {
guard input is Array(arr) else {
raise TypeMismatch("array", @ast_internal.json_type_name(input))
}
Iter::singleton(Json::boolean(arr.all(@ast_internal.is_truthy)))
}