Skip to main content

rl_lang/interpreter/stdlib/array/
arr_sort_by.rs

1use crate::{
2    interpreter::{evaluator::Evaluator, values::Value},
3    utils::{errors::Error, span::Span},
4};
5
6pub fn std_arr_sort_by(
7    eval: &mut Evaluator,
8    array: Value,
9    function: Value,
10    span: Span,
11) -> Result<Value, Error> {
12    let (items_type, mut items) = match array {
13        Value::Values { items_type, items } => (items_type, items),
14        other => {
15            return Err(eval.err(
16                format!(
17                    "arr_sort_by() accepts only arrays, found {}",
18                    other.type_name()
19                ),
20                span,
21            ));
22        }
23    };
24
25    if !matches!(function, Value::Function { .. }) {
26        return Err(eval.err(
27            format!(
28                "arr_sort_by() expected function or lambda, found {}",
29                function.type_name()
30            ),
31            span,
32        ));
33    }
34
35    for i in 1..items.len() {
36        let mut j = i;
37        while j > 0 {
38            let result = eval.call_value(
39                function.clone(),
40                vec![items[j - 1].clone(), items[j].clone()],
41                span,
42            )?;
43
44            match result {
45                Value::Integer(n) if n > 0 => {
46                    items.swap(j - 1, j);
47                    j -= 1;
48                }
49                Value::Integer(_) => break,
50                other => {
51                    return Err(eval.err(
52                        format!(
53                            "arr_sort_by() comparator must return int (-1, 0, 1), found {}",
54                            other.type_name()
55                        ),
56                        span,
57                    ));
58                }
59            }
60        }
61    }
62
63    Ok(Value::Values { items_type, items })
64}