use super::value_sort::{sort_by_key, sort_values};
use crate::prelude::*;
pub fn make_module() -> KMap {
let result = KMap::with_type("core.tuple");
result.add_fn("contains", |ctx| {
let expected_error = "|Tuple, Any|";
match ctx.instance_and_args(is_tuple, expected_error)? {
(KValue::Tuple(t), [value]) => {
let t = t.clone();
let value = value.clone();
for candidate in t.iter() {
match ctx
.vm
.run_binary_op(BinaryOp::Equal, value.clone(), candidate.clone())
{
Ok(KValue::Bool(false)) => {}
Ok(KValue::Bool(true)) => return Ok(true.into()),
Ok(unexpected) => {
return unexpected_type(
"a Bool from the equality comparison",
&unexpected,
);
}
Err(e) => return Err(e),
}
}
Ok(false.into())
}
(instance, args) => unexpected_args_after_instance(expected_error, instance, args),
}
});
result.add_fn("first", |ctx| {
let expected_error = "|Tuple|";
match ctx.instance_and_args(is_tuple, expected_error)? {
(KValue::Tuple(t), []) => match t.first() {
Some(value) => Ok(value.clone()),
None => Ok(KValue::Null),
},
(instance, args) => unexpected_args_after_instance(expected_error, instance, args),
}
});
result.add_fn("get", |ctx| {
use KValue::{Null, Number, Tuple};
let expected_error = "|Tuple, Number|, or |Tuple, Number, Any|";
let (tuple, index, default) = match ctx.instance_and_args(is_tuple, expected_error)? {
(Tuple(tuple), [Number(n)]) => (tuple, n, Null),
(Tuple(tuple), [Number(n), default]) => (tuple, n, default.clone()),
(instance, args) => {
return unexpected_args_after_instance(expected_error, instance, args);
}
};
if *index >= 0 {
match tuple.get(usize::from(index)) {
Some(value) => Ok(value.clone()),
None => Ok(default),
}
} else {
Ok(default)
}
});
result.add_fn("last", |ctx| {
let expected_error = "|Tuple|";
match ctx.instance_and_args(is_tuple, expected_error)? {
(KValue::Tuple(t), []) => match t.last() {
Some(value) => Ok(value.clone()),
None => Ok(KValue::Null),
},
(instance, args) => unexpected_args_after_instance(expected_error, instance, args),
}
});
result.add_fn("is_empty", |ctx| {
let expected_error = "|Tuple|";
match ctx.instance_and_args(is_tuple, expected_error)? {
(KValue::Tuple(t), []) => Ok(t.is_empty().into()),
(instance, args) => unexpected_args_after_instance(expected_error, instance, args),
}
});
result.add_fn("sort_copy", |ctx| {
let expected_error = "|Tuple|, or |Tuple, |Any| -> Any|";
match ctx.instance_and_args(is_tuple, expected_error)? {
(KValue::Tuple(t), []) => {
let mut result = t.to_vec();
sort_values(ctx.vm, &mut result)?;
Ok(KValue::Tuple(result.into()))
}
(KValue::Tuple(t), [f]) if f.is_callable() => {
let t = t.clone();
let sorted = sort_by_key(ctx.vm, &t, f.clone())?;
let result: Vec<_> = sorted.into_iter().map(|(_key, value)| value).collect();
Ok(KValue::Tuple(result.into()))
}
(instance, args) => unexpected_args_after_instance(expected_error, instance, args),
}
});
result.add_fn("to_list", |ctx| {
let expected_error = "|Tuple|";
match ctx.instance_and_args(is_tuple, expected_error)? {
(KValue::Tuple(t), []) => Ok(KValue::List(KList::from_slice(t))),
(instance, args) => unexpected_args_after_instance(expected_error, instance, args),
}
});
result
}
fn is_tuple(value: &KValue) -> bool {
matches!(value, KValue::Tuple(_))
}