use crate::runtime::pattern_matching::values_equal;
use crate::runtime::validation::validate_arg_count;
use crate::runtime::{InterpreterError, Value};
use std::sync::Arc;
pub fn eval_array_method<F>(
arr: &Arc<[Value]>,
method: &str,
args: &[Value],
mut eval_function_call_value: F,
) -> Result<Value, InterpreterError>
where
F: FnMut(&Value, &[Value]) -> Result<Value, InterpreterError>,
{
match method {
"len" | "length" if args.is_empty() => eval_array_len(arr),
"first" if args.is_empty() => eval_array_first(arr),
"last" if args.is_empty() => eval_array_last(arr),
"is_empty" if args.is_empty() => eval_array_is_empty(arr),
"push" if args.len() == 1 => eval_array_push(arr, &args[0]),
"pop" if args.is_empty() => eval_array_pop(arr),
"get" if args.len() == 1 => eval_array_get(arr, &args[0]),
"nth" if args.len() == 1 => eval_array_nth(arr, &args[0]),
"contains" if args.len() == 1 => eval_array_contains(arr, &args[0]),
"slice" if args.len() == 2 => eval_array_slice(arr, &args[0], &args[1]),
"join" if args.len() == 1 => eval_array_join(arr, &args[0]),
"unique" if args.is_empty() => eval_array_unique(arr),
"enumerate" if args.is_empty() => eval_array_enumerate(arr),
"concat" if args.len() == 1 => eval_array_concat(arr, &args[0]),
"append" if args.len() == 1 => eval_array_concat(arr, &args[0]), "flatten" if args.is_empty() => eval_array_flatten(arr),
"union" if args.len() == 1 => eval_array_union(arr, &args[0]),
"intersection" if args.len() == 1 => eval_array_intersection(arr, &args[0]),
"difference" if args.len() == 1 => eval_array_difference(arr, &args[0]),
"sort" if args.is_empty() => eval_array_sort(arr),
"reverse" if args.is_empty() => eval_array_reverse(arr),
"sum" if args.is_empty() => eval_array_sum(arr),
"product" if args.is_empty() => eval_array_product(arr),
"min" if args.is_empty() => eval_array_min(arr),
"max" if args.is_empty() => eval_array_max(arr),
"take" if args.len() == 1 => eval_array_take(arr, &args[0]),
"skip" if args.len() == 1 => eval_array_skip(arr, &args[0]),
"zip" if args.len() == 1 => eval_array_zip(arr, &args[0]),
"map" => eval_array_map(arr, args, &mut eval_function_call_value),
"filter" => eval_array_filter(arr, args, &mut eval_function_call_value),
"reduce" => eval_array_reduce(arr, args, &mut eval_function_call_value),
"any" => eval_array_any(arr, args, &mut eval_function_call_value),
"all" => eval_array_all(arr, args, &mut eval_function_call_value),
"find" => eval_array_find(arr, args, &mut eval_function_call_value),
"each" => eval_array_each(arr, args, &mut eval_function_call_value),
_ => Err(InterpreterError::RuntimeError(format!(
"Unknown array method: {method}"
))),
}
}
fn eval_array_len(arr: &Arc<[Value]>) -> Result<Value, InterpreterError> {
Ok(Value::Integer(arr.len() as i64))
}
fn eval_array_first(arr: &Arc<[Value]>) -> Result<Value, InterpreterError> {
Ok(arr.first().cloned().unwrap_or(Value::Nil))
}
fn eval_array_last(arr: &Arc<[Value]>) -> Result<Value, InterpreterError> {
Ok(arr.last().cloned().unwrap_or(Value::Nil))
}
fn eval_array_is_empty(arr: &Arc<[Value]>) -> Result<Value, InterpreterError> {
Ok(Value::Bool(arr.is_empty()))
}
fn eval_array_push(arr: &Arc<[Value]>, item: &Value) -> Result<Value, InterpreterError> {
let mut new_arr = arr.to_vec();
new_arr.push(item.clone());
Ok(Value::Array(Arc::from(new_arr)))
}
fn eval_array_pop(arr: &Arc<[Value]>) -> Result<Value, InterpreterError> {
let mut new_arr = arr.to_vec();
new_arr.pop().unwrap_or(Value::nil());
Ok(Value::Array(Arc::from(new_arr)))
}
fn eval_array_get(arr: &Arc<[Value]>, index: &Value) -> Result<Value, InterpreterError> {
if let Value::Integer(idx) = index {
if *idx < 0 {
return Ok(Value::Nil);
}
#[allow(clippy::cast_sign_loss)]
let index = *idx as usize;
if index < arr.len() {
Ok(arr[index].clone())
} else {
Ok(Value::Nil)
}
} else {
Err(InterpreterError::RuntimeError(
"get expects integer index".to_string(),
))
}
}
fn eval_array_nth(arr: &Arc<[Value]>, index: &Value) -> Result<Value, InterpreterError> {
if let Value::Integer(idx) = index {
if *idx < 0 {
return Ok(Value::EnumVariant {
enum_name: "Option".to_string(),
variant_name: "None".to_string(),
data: None,
});
}
#[allow(clippy::cast_sign_loss)]
let index = *idx as usize;
if index < arr.len() {
Ok(Value::EnumVariant {
enum_name: "Option".to_string(),
variant_name: "Some".to_string(),
data: Some(vec![arr[index].clone()]),
})
} else {
Ok(Value::EnumVariant {
enum_name: "Option".to_string(),
variant_name: "None".to_string(),
data: None,
})
}
} else {
Err(InterpreterError::RuntimeError(
"nth expects integer index".to_string(),
))
}
}
fn eval_array_contains(arr: &Arc<[Value]>, item: &Value) -> Result<Value, InterpreterError> {
for element in arr.iter() {
if values_equal(element, item) {
return Ok(Value::Bool(true));
}
}
Ok(Value::Bool(false))
}
fn eval_array_enumerate(arr: &Arc<[Value]>) -> Result<Value, InterpreterError> {
let enumerated: Vec<Value> = arr
.iter()
.enumerate()
.map(|(i, val)| Value::Tuple(Arc::from(vec![Value::Integer(i as i64), val.clone()])))
.collect();
Ok(Value::Array(Arc::from(enumerated)))
}
fn eval_array_slice(
arr: &Arc<[Value]>,
start: &Value,
end: &Value,
) -> Result<Value, InterpreterError> {
match (start, end) {
(Value::Integer(s), Value::Integer(e)) => {
let start_idx = (*s).max(0) as usize;
let end_idx = (*e).max(0) as usize;
let slice: Vec<Value> = arr
.iter()
.skip(start_idx)
.take(end_idx.saturating_sub(start_idx))
.cloned()
.collect();
Ok(Value::Array(Arc::from(slice)))
}
_ => Err(InterpreterError::RuntimeError(
"Array.slice() expects two integer arguments".to_string(),
)),
}
}
fn eval_array_join(arr: &Arc<[Value]>, separator: &Value) -> Result<Value, InterpreterError> {
match separator {
Value::String(sep) => {
let strings: Vec<String> = arr
.iter()
.map(|v| match v {
Value::String(s) => s.to_string(),
_ => format!("{v}"),
})
.collect();
Ok(Value::from_string(strings.join(sep.as_ref())))
}
_ => Err(InterpreterError::RuntimeError(
"Array.join() expects a string argument".to_string(),
)),
}
}
fn eval_array_unique(arr: &Arc<[Value]>) -> Result<Value, InterpreterError> {
let mut seen = std::collections::HashSet::new();
let unique: Vec<Value> = arr
.iter()
.filter(|v| {
let key = format!("{v:?}");
seen.insert(key)
})
.cloned()
.collect();
Ok(Value::Array(Arc::from(unique)))
}
fn eval_array_map<F>(
arr: &Arc<[Value]>,
args: &[Value],
eval_function_call_value: &mut F,
) -> Result<Value, InterpreterError>
where
F: FnMut(&Value, &[Value]) -> Result<Value, InterpreterError>,
{
validate_single_closure_argument(args, "map")?;
let mut result = Vec::new();
for item in arr.iter() {
let func_result = eval_function_call_value(&args[0], std::slice::from_ref(item))?;
result.push(func_result);
}
Ok(Value::Array(Arc::from(result)))
}
fn eval_array_filter<F>(
arr: &Arc<[Value]>,
args: &[Value],
eval_function_call_value: &mut F,
) -> Result<Value, InterpreterError>
where
F: FnMut(&Value, &[Value]) -> Result<Value, InterpreterError>,
{
validate_single_closure_argument(args, "filter")?;
let mut result = Vec::new();
for item in arr.iter() {
let func_result = eval_function_call_value(&args[0], std::slice::from_ref(item))?;
if func_result.is_truthy() {
result.push(item.clone());
}
}
Ok(Value::Array(Arc::from(result)))
}
fn eval_array_reduce<F>(
arr: &Arc<[Value]>,
args: &[Value],
eval_function_call_value: &mut F,
) -> Result<Value, InterpreterError>
where
F: FnMut(&Value, &[Value]) -> Result<Value, InterpreterError>,
{
validate_arg_count("reduce", args, 2)?;
let (initial, func) = if matches!(&args[1], Value::Closure { .. }) {
(&args[0], &args[1])
} else if matches!(&args[0], Value::Closure { .. }) {
(&args[1], &args[0])
} else {
return Err(InterpreterError::RuntimeError(
"reduce expects an initial value and a function".to_string(),
));
};
let mut accumulator = initial.clone();
for item in arr.iter() {
accumulator = eval_function_call_value(func, &[accumulator, item.clone()])?;
}
Ok(accumulator)
}
fn eval_array_any<F>(
arr: &Arc<[Value]>,
args: &[Value],
eval_function_call_value: &mut F,
) -> Result<Value, InterpreterError>
where
F: FnMut(&Value, &[Value]) -> Result<Value, InterpreterError>,
{
validate_single_closure_argument(args, "any")?;
for item in arr.iter() {
let func_result = eval_function_call_value(&args[0], std::slice::from_ref(item))?;
if func_result.is_truthy() {
return Ok(Value::Bool(true));
}
}
Ok(Value::Bool(false))
}
fn eval_array_all<F>(
arr: &Arc<[Value]>,
args: &[Value],
eval_function_call_value: &mut F,
) -> Result<Value, InterpreterError>
where
F: FnMut(&Value, &[Value]) -> Result<Value, InterpreterError>,
{
validate_single_closure_argument(args, "all")?;
for item in arr.iter() {
let func_result = eval_function_call_value(&args[0], std::slice::from_ref(item))?;
if !func_result.is_truthy() {
return Ok(Value::Bool(false));
}
}
Ok(Value::Bool(true))
}
fn eval_array_find<F>(
arr: &Arc<[Value]>,
args: &[Value],
eval_function_call_value: &mut F,
) -> Result<Value, InterpreterError>
where
F: FnMut(&Value, &[Value]) -> Result<Value, InterpreterError>,
{
validate_single_closure_argument(args, "find")?;
for item in arr.iter() {
let func_result = eval_function_call_value(&args[0], std::slice::from_ref(item))?;
if func_result.is_truthy() {
return Ok(item.clone());
}
}
Ok(Value::Nil)
}
fn eval_array_each<F>(
arr: &Arc<[Value]>,
args: &[Value],
eval_function_call_value: &mut F,
) -> Result<Value, InterpreterError>
where
F: FnMut(&Value, &[Value]) -> Result<Value, InterpreterError>,
{
validate_single_closure_argument(args, "each")?;
for item in arr.iter() {
eval_function_call_value(&args[0], std::slice::from_ref(item))?;
}
Ok(Value::Nil)
}
fn validate_single_closure_argument(
args: &[Value],
method_name: &str,
) -> Result<(), InterpreterError> {
validate_arg_count(method_name, args, 1)?;
if !matches!(&args[0], Value::Closure { .. }) {
return Err(InterpreterError::RuntimeError(format!(
"{method_name} expects a function argument"
)));
}
Ok(())
}
fn eval_array_concat(arr: &Arc<[Value]>, other: &Value) -> Result<Value, InterpreterError> {
match other {
Value::Array(other_arr) => {
let mut result = arr.to_vec();
result.extend_from_slice(other_arr);
Ok(Value::Array(Arc::from(result)))
}
_ => Err(InterpreterError::TypeError(format!(
"concat() requires array argument, got {other:?}"
))),
}
}
fn eval_array_flatten(arr: &Arc<[Value]>) -> Result<Value, InterpreterError> {
let mut result = Vec::new();
for item in arr.iter() {
match item {
Value::Array(nested) => {
result.extend_from_slice(nested);
}
_ => {
result.push(item.clone());
}
}
}
Ok(Value::Array(Arc::from(result)))
}
fn eval_array_union(arr: &Arc<[Value]>, other: &Value) -> Result<Value, InterpreterError> {
match other {
Value::Array(other_arr) => {
let mut seen = std::collections::HashSet::new();
let mut result = Vec::new();
for item in arr.iter() {
let key = format!("{item:?}");
if seen.insert(key) {
result.push(item.clone());
}
}
for item in other_arr.iter() {
let key = format!("{item:?}");
if seen.insert(key) {
result.push(item.clone());
}
}
Ok(Value::Array(Arc::from(result)))
}
_ => Err(InterpreterError::TypeError(format!(
"union() requires array argument, got {other:?}"
))),
}
}
fn eval_array_intersection(arr: &Arc<[Value]>, other: &Value) -> Result<Value, InterpreterError> {
match other {
Value::Array(other_arr) => {
let other_set: std::collections::HashSet<_> =
other_arr.iter().map(|v| format!("{v:?}")).collect();
let mut seen = std::collections::HashSet::new();
let mut result = Vec::new();
for item in arr.iter() {
let key = format!("{item:?}");
if other_set.contains(&key) && seen.insert(key) {
result.push(item.clone());
}
}
Ok(Value::Array(Arc::from(result)))
}
_ => Err(InterpreterError::TypeError(format!(
"intersection() requires array argument, got {other:?}"
))),
}
}
fn eval_array_difference(arr: &Arc<[Value]>, other: &Value) -> Result<Value, InterpreterError> {
match other {
Value::Array(other_arr) => {
let other_set: std::collections::HashSet<_> =
other_arr.iter().map(|v| format!("{v:?}")).collect();
let mut seen = std::collections::HashSet::new();
let mut result = Vec::new();
for item in arr.iter() {
let key = format!("{item:?}");
if !other_set.contains(&key) && seen.insert(key) {
result.push(item.clone());
}
}
Ok(Value::Array(Arc::from(result)))
}
_ => Err(InterpreterError::TypeError(format!(
"difference() requires array argument, got {other:?}"
))),
}
}
fn eval_array_sort(arr: &Arc<[Value]>) -> Result<Value, InterpreterError> {
let mut sorted = arr.to_vec();
sorted.sort_by(|a, b| {
let a_str = format!("{a:?}");
let b_str = format!("{b:?}");
a_str.cmp(&b_str)
});
Ok(Value::Array(Arc::from(sorted)))
}
fn eval_array_reverse(arr: &Arc<[Value]>) -> Result<Value, InterpreterError> {
let mut reversed = arr.to_vec();
reversed.reverse();
Ok(Value::Array(Arc::from(reversed)))
}
fn eval_array_sum(arr: &Arc<[Value]>) -> Result<Value, InterpreterError> {
let mut int_sum: i64 = 0;
let mut float_sum: f64 = 0.0;
let mut has_float = false;
for item in arr.iter() {
match item {
Value::Integer(i) => int_sum += i,
Value::Float(f) => {
has_float = true;
float_sum += f;
}
_ => {
return Err(InterpreterError::RuntimeError(
"sum() requires numeric array elements".to_string(),
))
}
}
}
if has_float {
Ok(Value::Float(int_sum as f64 + float_sum))
} else {
Ok(Value::Integer(int_sum))
}
}
fn eval_array_product(arr: &Arc<[Value]>) -> Result<Value, InterpreterError> {
if arr.is_empty() {
return Ok(Value::Integer(1)); }
let mut int_product: i64 = 1;
let mut float_product: f64 = 1.0;
let mut has_float = false;
for item in arr.iter() {
match item {
Value::Integer(i) => int_product *= i,
Value::Float(f) => {
has_float = true;
float_product *= f;
}
_ => {
return Err(InterpreterError::RuntimeError(
"product() requires numeric array elements".to_string(),
))
}
}
}
if has_float {
Ok(Value::Float(int_product as f64 * float_product))
} else {
Ok(Value::Integer(int_product))
}
}
fn eval_array_min(arr: &Arc<[Value]>) -> Result<Value, InterpreterError> {
if arr.is_empty() {
return Ok(Value::Nil);
}
let mut min_val: Option<f64> = None;
let mut has_float = false;
for item in arr.iter() {
let val = match item {
Value::Integer(i) => *i as f64,
Value::Float(f) => {
has_float = true;
*f
}
_ => {
return Err(InterpreterError::RuntimeError(
"min() requires numeric array elements".to_string(),
))
}
};
min_val = Some(min_val.map_or(val, |m| m.min(val)));
}
match min_val {
Some(v) if has_float => Ok(Value::Float(v)),
Some(v) => Ok(Value::Integer(v as i64)),
None => Ok(Value::Nil),
}
}
fn eval_array_max(arr: &Arc<[Value]>) -> Result<Value, InterpreterError> {
if arr.is_empty() {
return Ok(Value::Nil);
}
let mut max_val: Option<f64> = None;
let mut has_float = false;
for item in arr.iter() {
let val = match item {
Value::Integer(i) => *i as f64,
Value::Float(f) => {
has_float = true;
*f
}
_ => {
return Err(InterpreterError::RuntimeError(
"max() requires numeric array elements".to_string(),
))
}
};
max_val = Some(max_val.map_or(val, |m| m.max(val)));
}
match max_val {
Some(v) if has_float => Ok(Value::Float(v)),
Some(v) => Ok(Value::Integer(v as i64)),
None => Ok(Value::Nil),
}
}
fn eval_array_take(arr: &Arc<[Value]>, count: &Value) -> Result<Value, InterpreterError> {
match count {
Value::Integer(n) => {
let n = (*n).max(0) as usize;
let taken: Vec<Value> = arr.iter().take(n).cloned().collect();
Ok(Value::Array(Arc::from(taken)))
}
_ => Err(InterpreterError::RuntimeError(
"take() expects integer argument".to_string(),
)),
}
}
fn eval_array_skip(arr: &Arc<[Value]>, count: &Value) -> Result<Value, InterpreterError> {
match count {
Value::Integer(n) => {
let n = (*n).max(0) as usize;
let skipped: Vec<Value> = arr.iter().skip(n).cloned().collect();
Ok(Value::Array(Arc::from(skipped)))
}
_ => Err(InterpreterError::RuntimeError(
"skip() expects integer argument".to_string(),
)),
}
}
fn eval_array_zip(arr: &Arc<[Value]>, other: &Value) -> Result<Value, InterpreterError> {
match other {
Value::Array(other_arr) => {
let zipped: Vec<Value> = arr
.iter()
.zip(other_arr.iter())
.map(|(a, b)| Value::Tuple(Arc::from(vec![a.clone(), b.clone()])))
.collect();
Ok(Value::Array(Arc::from(zipped)))
}
_ => Err(InterpreterError::RuntimeError(
"zip() expects array argument".to_string(),
)),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_array_len() {
let arr = Arc::from(vec![
Value::Integer(1),
Value::Integer(2),
Value::Integer(3),
]);
let result = eval_array_len(&arr).expect("operation should succeed in test");
assert_eq!(result, Value::Integer(3));
}
#[test]
fn test_array_first() {
let arr = Arc::from(vec![
Value::Integer(1),
Value::Integer(2),
Value::Integer(3),
]);
let result = eval_array_first(&arr).expect("operation should succeed in test");
assert_eq!(result, Value::Integer(1));
}
#[test]
fn test_array_last() {
let arr = Arc::from(vec![
Value::Integer(1),
Value::Integer(2),
Value::Integer(3),
]);
let result = eval_array_last(&arr).expect("operation should succeed in test");
assert_eq!(result, Value::Integer(3));
}
#[test]
fn test_array_push() {
let arr = Arc::from(vec![Value::Integer(1), Value::Integer(2)]);
let result =
eval_array_push(&arr, &Value::Integer(3)).expect("operation should succeed in test");
if let Value::Array(new_arr) = result {
assert_eq!(new_arr.len(), 3);
assert_eq!(new_arr[2], Value::Integer(3));
} else {
panic!("Expected array result");
}
}
#[test]
fn test_array_get() {
let arr = Arc::from(vec![
Value::Integer(1),
Value::Integer(2),
Value::Integer(3),
]);
let result =
eval_array_get(&arr, &Value::Integer(1)).expect("operation should succeed in test");
assert_eq!(result, Value::Integer(2));
}
#[test]
fn test_array_append_basic() {
let arr = Arc::from(vec![Value::Integer(1), Value::Integer(2)]);
let other = Value::Array(Arc::from(vec![Value::Integer(3), Value::Integer(4)]));
let dummy_eval = |_: &Value, _: &[Value]| Ok(Value::Nil);
let result = eval_array_method(&arr, "append", &[other], dummy_eval)
.expect("operation should succeed in test");
if let Value::Array(result_arr) = result {
assert_eq!(result_arr.len(), 4);
assert_eq!(result_arr[0], Value::Integer(1));
assert_eq!(result_arr[1], Value::Integer(2));
assert_eq!(result_arr[2], Value::Integer(3));
assert_eq!(result_arr[3], Value::Integer(4));
} else {
panic!("Expected array result from append");
}
}
#[test]
fn test_array_append_empty_arrays() {
let arr = Arc::from(vec![Value::Integer(1)]);
let other = Value::Array(Arc::from(vec![]));
let dummy_eval = |_: &Value, _: &[Value]| Ok(Value::Nil);
let result = eval_array_method(&arr, "append", &[other], dummy_eval)
.expect("operation should succeed in test");
if let Value::Array(result_arr) = result {
assert_eq!(result_arr.len(), 1);
assert_eq!(result_arr[0], Value::Integer(1));
} else {
panic!("Expected array result from append");
}
}
#[test]
fn test_array_append_wrong_arg_type() {
let arr = Arc::from(vec![Value::Integer(1)]);
let dummy_eval = |_: &Value, _: &[Value]| Ok(Value::Nil);
let result = eval_array_method(&arr, "append", &[Value::Integer(42)], dummy_eval);
assert!(
result.is_err(),
"append() should reject non-array arguments"
);
}
#[test]
fn test_eval_array_method_match_guards() {
let arr = Arc::from(vec![
Value::Integer(1),
Value::Integer(2),
Value::Integer(3),
]);
let dummy_eval = |_: &Value, _: &[Value]| Ok(Value::Nil);
let result = eval_array_method(&arr, "first", &[], dummy_eval);
assert!(result.is_ok(), "first with 0 args should work");
assert_eq!(
result.expect("operation should succeed in test"),
Value::Integer(1)
);
let result = eval_array_method(&arr, "first", &[Value::Integer(0)], dummy_eval);
assert!(
result.is_err(),
"first with args should fail (match guard: args.is_empty())"
);
let result = eval_array_method(&arr, "push", &[Value::Integer(4)], dummy_eval);
assert!(result.is_ok(), "push with 1 arg should work");
let result = eval_array_method(&arr, "push", &[], dummy_eval);
assert!(
result.is_err(),
"push with 0 args should fail (match guard: args.len() == 1)"
);
}
#[test]
fn test_eval_array_method_match_arms_any_all() {
let arr = Arc::from(vec![
Value::Integer(1),
Value::Integer(2),
Value::Integer(3),
]);
use std::sync::Arc as RcAlias;
let closure = Value::Closure {
params: vec![("x".to_string(), None)],
body: RcAlias::new(crate::frontend::ast::Expr {
kind: crate::frontend::ast::ExprKind::Identifier("x".to_string()),
span: crate::frontend::ast::Span::new(0, 0),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
env: Default::default(),
};
let eval_func = |_: &Value, _: &[Value]| Ok(Value::Bool(true));
let result = eval_array_any(&arr, std::slice::from_ref(&closure), &mut |f, a| {
eval_func(f, a)
});
assert!(result.is_ok(), "any method should work (match arm test)");
let result = eval_array_all(&arr, std::slice::from_ref(&closure), &mut |f, a| {
eval_func(f, a)
});
assert!(result.is_ok(), "all method should work (match arm test)");
}
#[test]
fn test_eval_array_reduce_comparison_operator() {
let arr = Arc::from(vec![Value::Integer(1), Value::Integer(2)]);
use std::sync::Arc as RcAlias;
let closure = Value::Closure {
params: vec![("acc".to_string(), None), ("x".to_string(), None)],
body: RcAlias::new(crate::frontend::ast::Expr {
kind: crate::frontend::ast::ExprKind::Identifier("acc".to_string()),
span: crate::frontend::ast::Span::new(0, 0),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
env: Default::default(),
};
let eval_func = |_: &Value, args: &[Value]| Ok(args[0].clone());
let result = eval_array_reduce(&arr, &[closure.clone(), Value::Integer(0)], &mut |f, a| {
eval_func(f, a)
});
assert!(
result.is_ok(),
"reduce with 2 args should work (args.len() != 2 check)"
);
let result = eval_array_reduce(&arr, std::slice::from_ref(&closure), &mut |f, a| {
eval_func(f, a)
});
assert!(
result.is_err(),
"reduce with 1 arg should fail (proves != operator, not ==)"
);
let result = eval_array_reduce(
&arr,
&[closure, Value::Integer(0), Value::Integer(1)],
&mut |f, a| eval_func(f, a),
);
assert!(
result.is_err(),
"reduce with 3 args should fail (proves != operator)"
);
}
#[test]
fn test_eval_array_reduce_negation_operator() {
let arr = Arc::from(vec![Value::Integer(1)]);
let eval_func = |_: &Value, _: &[Value]| Ok(Value::Nil);
let result = eval_array_reduce(
&arr,
&[Value::Integer(0), Value::Integer(0)],
&mut |f, a| eval_func(f, a),
);
assert!(
result.is_err(),
"reduce should reject non-closure (tests !matches negation)"
);
use std::sync::Arc as RcAlias;
let closure = Value::Closure {
params: vec![],
body: RcAlias::new(crate::frontend::ast::Expr {
kind: crate::frontend::ast::ExprKind::Literal(crate::frontend::ast::Literal::Null),
span: crate::frontend::ast::Span::new(0, 0),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
env: Default::default(),
};
let result = eval_array_reduce(&arr, &[closure, Value::Integer(0)], &mut |f, a| {
eval_func(f, a)
});
assert!(
result.is_ok(),
"reduce should accept closure (proves negation works)"
);
}
#[test]
fn test_eval_array_all_negation_operator() {
let arr = Arc::from(vec![
Value::Bool(true),
Value::Bool(false),
Value::Bool(true),
]);
let eval_identity = |_: &Value, args: &[Value]| Ok(args[0].clone());
use std::sync::Arc as RcAlias;
let closure = Value::Closure {
params: vec![("x".to_string(), None)],
body: RcAlias::new(crate::frontend::ast::Expr {
kind: crate::frontend::ast::ExprKind::Identifier("x".to_string()),
span: crate::frontend::ast::Span::new(0, 0),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
env: Default::default(),
};
let result = eval_array_all(&arr, &[closure], &mut |f, a| eval_identity(f, a))
.expect("operation should succeed in test");
assert_eq!(
result,
Value::Bool(false),
"all() should return false when any element is falsy (tests ! operator)"
);
let all_true_arr = Arc::from(vec![Value::Bool(true), Value::Bool(true)]);
let closure2 = Value::Closure {
params: vec![("x".to_string(), None)],
body: RcAlias::new(crate::frontend::ast::Expr {
kind: crate::frontend::ast::ExprKind::Identifier("x".to_string()),
span: crate::frontend::ast::Span::new(0, 0),
attributes: vec![],
leading_comments: vec![],
trailing_comment: None,
}),
env: Default::default(),
};
let result = eval_array_all(&all_true_arr, &[closure2], &mut |f, a| eval_identity(f, a))
.expect("operation should succeed in test");
assert_eq!(
result,
Value::Bool(true),
"all() should return true when all elements are truthy"
);
}
#[test]
fn test_array_nth_in_bounds() {
let arr = Arc::from(vec![
Value::Integer(10),
Value::Integer(20),
Value::Integer(30),
]);
let result =
eval_array_nth(&arr, &Value::Integer(1)).expect("operation should succeed in test");
match result {
Value::EnumVariant {
variant_name, data, ..
} if variant_name == "Some" => {
assert_eq!(
data.expect("operation should succeed in test")[0],
Value::Integer(20)
);
}
_ => panic!("Expected Some variant"),
}
}
#[test]
fn test_array_nth_out_of_bounds() {
let arr = Arc::from(vec![Value::Integer(1), Value::Integer(2)]);
let result =
eval_array_nth(&arr, &Value::Integer(10)).expect("operation should succeed in test");
match result {
Value::EnumVariant {
variant_name, data, ..
} if variant_name == "None" => {
assert!(data.is_none());
}
_ => panic!("Expected None variant"),
}
}
#[test]
fn test_array_nth_negative_index() {
let arr = Arc::from(vec![Value::Integer(1), Value::Integer(2)]);
let result =
eval_array_nth(&arr, &Value::Integer(-1)).expect("operation should succeed in test");
match result {
Value::EnumVariant {
variant_name, data, ..
} if variant_name == "None" => {
assert!(data.is_none());
}
_ => panic!("Expected None variant for negative index"),
}
}
#[cfg(test)]
mod property_tests {
use super::*;
use proptest::prelude::*;
proptest! {
#[test]
fn prop_nth_valid_index_returns_some(values in prop::collection::vec(any::<i64>(), 1..10), idx in 0usize..10) {
if idx >= values.len() {
return Ok(()); }
let arr = Arc::from(
values.iter().map(|&v| Value::Integer(v)).collect::<Vec<_>>()
);
let result = eval_array_nth(&arr, &Value::Integer(idx as i64)).expect("operation should succeed in test");
match result {
Value::EnumVariant { variant_name, data, .. } if variant_name == "Some" => {
prop_assert!(data.is_some());
prop_assert_eq!(&data.expect("operation should succeed in test")[0], &Value::Integer(values[idx]));
}
_ => prop_assert!(false, "Expected Some variant"),
}
}
#[test]
fn prop_nth_out_of_bounds_returns_none(values in prop::collection::vec(any::<i64>(), 0..10), idx in 10i64..100) {
let arr = Arc::from(
values.iter().map(|&v| Value::Integer(v)).collect::<Vec<_>>()
);
let result = eval_array_nth(&arr, &Value::Integer(idx)).expect("operation should succeed in test");
match result {
Value::EnumVariant { variant_name, data, .. } if variant_name == "None" => {
prop_assert!(data.is_none());
}
_ => prop_assert!(false, "Expected None variant"),
}
}
#[test]
fn prop_nth_negative_returns_none(values in prop::collection::vec(any::<i64>(), 1..10), idx in -100i64..-1) {
let arr = Arc::from(
values.iter().map(|&v| Value::Integer(v)).collect::<Vec<_>>()
);
let result = eval_array_nth(&arr, &Value::Integer(idx)).expect("operation should succeed in test");
match result {
Value::EnumVariant { variant_name, data, .. } if variant_name == "None" => {
prop_assert!(data.is_none());
}
_ => prop_assert!(false, "Expected None variant for negative index"),
}
}
#[test]
fn prop_nth_never_panics(values in prop::collection::vec(any::<i64>(), 0..20), idx in any::<i64>()) {
let arr = Arc::from(
values.iter().map(|&v| Value::Integer(v)).collect::<Vec<_>>()
);
let _ = eval_array_nth(&arr, &Value::Integer(idx)); }
}
}
#[test]
fn test_array_first_empty() {
let arr = Arc::from(Vec::<Value>::new());
let result = eval_array_first(&arr).unwrap();
assert_eq!(result, Value::Nil);
}
#[test]
fn test_array_last_empty() {
let arr = Arc::from(Vec::<Value>::new());
let result = eval_array_last(&arr).unwrap();
assert_eq!(result, Value::Nil);
}
#[test]
fn test_array_is_empty_true() {
let arr = Arc::from(Vec::<Value>::new());
let result = eval_array_is_empty(&arr).unwrap();
assert_eq!(result, Value::Bool(true));
}
#[test]
fn test_array_is_empty_false() {
let arr = Arc::from(vec![Value::Integer(1)]);
let result = eval_array_is_empty(&arr).unwrap();
assert_eq!(result, Value::Bool(false));
}
#[test]
fn test_array_pop_returns_shorter_array() {
let arr = Arc::from(vec![
Value::Integer(1),
Value::Integer(2),
Value::Integer(3),
]);
let result = eval_array_pop(&arr).unwrap();
if let Value::Array(new_arr) = result {
assert_eq!(new_arr.len(), 2);
assert_eq!(new_arr[0], Value::Integer(1));
assert_eq!(new_arr[1], Value::Integer(2));
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_pop_empty() {
let arr = Arc::from(Vec::<Value>::new());
let result = eval_array_pop(&arr).unwrap();
if let Value::Array(new_arr) = result {
assert_eq!(new_arr.len(), 0);
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_get_negative_index() {
let arr = Arc::from(vec![Value::Integer(1), Value::Integer(2)]);
let result = eval_array_get(&arr, &Value::Integer(-1)).unwrap();
assert_eq!(result, Value::Nil);
}
#[test]
fn test_array_get_out_of_bounds() {
let arr = Arc::from(vec![Value::Integer(1), Value::Integer(2)]);
let result = eval_array_get(&arr, &Value::Integer(100)).unwrap();
assert_eq!(result, Value::Nil);
}
#[test]
fn test_array_get_wrong_type() {
let arr = Arc::from(vec![Value::Integer(1)]);
let result = eval_array_get(&arr, &Value::from_string("test".to_string()));
assert!(result.is_err());
}
#[test]
fn test_array_nth_wrong_type() {
let arr = Arc::from(vec![Value::Integer(1)]);
let result = eval_array_nth(&arr, &Value::from_string("test".to_string()));
assert!(result.is_err());
}
#[test]
fn test_array_contains_found() {
let arr = Arc::from(vec![
Value::Integer(1),
Value::Integer(2),
Value::Integer(3),
]);
let result = eval_array_contains(&arr, &Value::Integer(2)).unwrap();
assert_eq!(result, Value::Bool(true));
}
#[test]
fn test_array_contains_not_found() {
let arr = Arc::from(vec![Value::Integer(1), Value::Integer(2)]);
let result = eval_array_contains(&arr, &Value::Integer(100)).unwrap();
assert_eq!(result, Value::Bool(false));
}
#[test]
fn test_array_contains_empty() {
let arr = Arc::from(Vec::<Value>::new());
let result = eval_array_contains(&arr, &Value::Integer(1)).unwrap();
assert_eq!(result, Value::Bool(false));
}
#[test]
fn test_array_enumerate_basic() {
let arr = Arc::from(vec![
Value::from_string("a".to_string()),
Value::from_string("b".to_string()),
]);
let result = eval_array_enumerate(&arr).unwrap();
if let Value::Array(enumerated) = result {
assert_eq!(enumerated.len(), 2);
if let Value::Tuple(first) = &enumerated[0] {
assert_eq!(first[0], Value::Integer(0));
}
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_enumerate_empty() {
let arr = Arc::from(Vec::<Value>::new());
let result = eval_array_enumerate(&arr).unwrap();
if let Value::Array(enumerated) = result {
assert_eq!(enumerated.len(), 0);
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_slice_basic() {
let arr = Arc::from(vec![
Value::Integer(1),
Value::Integer(2),
Value::Integer(3),
Value::Integer(4),
]);
let result = eval_array_slice(&arr, &Value::Integer(1), &Value::Integer(3)).unwrap();
if let Value::Array(sliced) = result {
assert_eq!(sliced.len(), 2);
assert_eq!(sliced[0], Value::Integer(2));
assert_eq!(sliced[1], Value::Integer(3));
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_slice_negative_start() {
let arr = Arc::from(vec![Value::Integer(1), Value::Integer(2)]);
let result = eval_array_slice(&arr, &Value::Integer(-5), &Value::Integer(1)).unwrap();
if let Value::Array(sliced) = result {
assert_eq!(sliced.len(), 1);
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_slice_wrong_types() {
let arr = Arc::from(vec![Value::Integer(1)]);
let result = eval_array_slice(
&arr,
&Value::from_string("a".to_string()),
&Value::Integer(1),
);
assert!(result.is_err());
}
#[test]
fn test_array_join_basic() {
let arr = Arc::from(vec![
Value::from_string("a".to_string()),
Value::from_string("b".to_string()),
Value::from_string("c".to_string()),
]);
let sep = Value::from_string(",".to_string());
let result = eval_array_join(&arr, &sep).unwrap();
if let Value::String(s) = result {
assert_eq!(s.as_ref(), "a,b,c");
} else {
panic!("Expected string");
}
}
#[test]
fn test_array_join_non_strings() {
let arr = Arc::from(vec![Value::Integer(1), Value::Integer(2)]);
let sep = Value::from_string("-".to_string());
let result = eval_array_join(&arr, &sep).unwrap();
assert!(matches!(result, Value::String(_)));
}
#[test]
fn test_array_join_wrong_separator_type() {
let arr = Arc::from(vec![Value::Integer(1)]);
let result = eval_array_join(&arr, &Value::Integer(42));
assert!(result.is_err());
}
#[test]
fn test_array_unique_basic() {
let arr = Arc::from(vec![
Value::Integer(1),
Value::Integer(2),
Value::Integer(1),
Value::Integer(3),
Value::Integer(2),
]);
let result = eval_array_unique(&arr).unwrap();
if let Value::Array(unique) = result {
assert_eq!(unique.len(), 3);
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_unique_empty() {
let arr = Arc::from(Vec::<Value>::new());
let result = eval_array_unique(&arr).unwrap();
if let Value::Array(unique) = result {
assert_eq!(unique.len(), 0);
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_concat_basic() {
let arr = Arc::from(vec![Value::Integer(1), Value::Integer(2)]);
let other = Value::Array(Arc::from(vec![Value::Integer(3), Value::Integer(4)]));
let result = eval_array_concat(&arr, &other).unwrap();
if let Value::Array(concat) = result {
assert_eq!(concat.len(), 4);
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_concat_wrong_type() {
let arr = Arc::from(vec![Value::Integer(1)]);
let result = eval_array_concat(&arr, &Value::Integer(42));
assert!(result.is_err());
}
#[test]
fn test_array_flatten_nested() {
let inner1 = Value::Array(Arc::from(vec![Value::Integer(1), Value::Integer(2)]));
let inner2 = Value::Array(Arc::from(vec![Value::Integer(3)]));
let arr = Arc::from(vec![inner1, inner2]);
let result = eval_array_flatten(&arr).unwrap();
if let Value::Array(flat) = result {
assert_eq!(flat.len(), 3);
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_flatten_mixed() {
let inner = Value::Array(Arc::from(vec![Value::Integer(2)]));
let arr = Arc::from(vec![Value::Integer(1), inner, Value::Integer(3)]);
let result = eval_array_flatten(&arr).unwrap();
if let Value::Array(flat) = result {
assert_eq!(flat.len(), 3);
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_union_basic() {
let arr = Arc::from(vec![Value::Integer(1), Value::Integer(2)]);
let other = Value::Array(Arc::from(vec![Value::Integer(2), Value::Integer(3)]));
let result = eval_array_union(&arr, &other).unwrap();
if let Value::Array(union_arr) = result {
assert_eq!(union_arr.len(), 3);
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_union_wrong_type() {
let arr = Arc::from(vec![Value::Integer(1)]);
let result = eval_array_union(&arr, &Value::Integer(42));
assert!(result.is_err());
}
#[test]
fn test_array_intersection_basic() {
let arr = Arc::from(vec![
Value::Integer(1),
Value::Integer(2),
Value::Integer(3),
]);
let other = Value::Array(Arc::from(vec![
Value::Integer(2),
Value::Integer(3),
Value::Integer(4),
]));
let result = eval_array_intersection(&arr, &other).unwrap();
if let Value::Array(inter) = result {
assert_eq!(inter.len(), 2);
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_intersection_no_common() {
let arr = Arc::from(vec![Value::Integer(1), Value::Integer(2)]);
let other = Value::Array(Arc::from(vec![Value::Integer(3), Value::Integer(4)]));
let result = eval_array_intersection(&arr, &other).unwrap();
if let Value::Array(inter) = result {
assert_eq!(inter.len(), 0);
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_intersection_wrong_type() {
let arr = Arc::from(vec![Value::Integer(1)]);
let result = eval_array_intersection(&arr, &Value::Integer(42));
assert!(result.is_err());
}
#[test]
fn test_array_difference_basic() {
let arr = Arc::from(vec![
Value::Integer(1),
Value::Integer(2),
Value::Integer(3),
]);
let other = Value::Array(Arc::from(vec![Value::Integer(2)]));
let result = eval_array_difference(&arr, &other).unwrap();
if let Value::Array(diff) = result {
assert_eq!(diff.len(), 2);
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_difference_wrong_type() {
let arr = Arc::from(vec![Value::Integer(1)]);
let result = eval_array_difference(&arr, &Value::Integer(42));
assert!(result.is_err());
}
#[test]
fn test_array_sort_integers() {
let arr = Arc::from(vec![
Value::Integer(3),
Value::Integer(1),
Value::Integer(4),
Value::Integer(1),
Value::Integer(5),
]);
let result = eval_array_sort(&arr).unwrap();
if let Value::Array(sorted) = result {
assert_eq!(sorted.len(), 5);
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_sort_empty() {
let arr = Arc::from(Vec::<Value>::new());
let result = eval_array_sort(&arr).unwrap();
if let Value::Array(sorted) = result {
assert_eq!(sorted.len(), 0);
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_method_unknown() {
let arr = Arc::from(vec![Value::Integer(1)]);
let dummy_eval = |_: &Value, _: &[Value]| Ok(Value::Nil);
let result = eval_array_method(&arr, "unknown_method", &[], dummy_eval);
assert!(result.is_err());
}
#[test]
fn test_array_len_empty() {
let arr = Arc::from(Vec::<Value>::new());
let result = eval_array_len(&arr).unwrap();
assert_eq!(result, Value::Integer(0));
}
#[test]
fn test_array_length_alias() {
let arr = Arc::from(vec![Value::Integer(1), Value::Integer(2)]);
let dummy_eval = |_: &Value, _: &[Value]| Ok(Value::Nil);
let result = eval_array_method(&arr, "length", &[], dummy_eval).unwrap();
assert_eq!(result, Value::Integer(2));
}
#[test]
fn test_array_first_single_element() {
let arr = Arc::from(vec![Value::Integer(42)]);
let result = eval_array_first(&arr).unwrap();
assert_eq!(result, Value::Integer(42));
}
#[test]
fn test_array_last_single_element() {
let arr = Arc::from(vec![Value::Integer(42)]);
let result = eval_array_last(&arr).unwrap();
assert_eq!(result, Value::Integer(42));
}
#[test]
fn test_array_push_multiple_types() {
let arr = Arc::from(vec![Value::Integer(1)]);
let result = eval_array_push(&arr, &Value::from_string("hello".to_string())).unwrap();
if let Value::Array(new_arr) = result {
assert_eq!(new_arr.len(), 2);
assert_eq!(new_arr[0], Value::Integer(1));
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_get_first_element() {
let arr = Arc::from(vec![Value::Integer(100), Value::Integer(200)]);
let result = eval_array_get(&arr, &Value::Integer(0)).unwrap();
assert_eq!(result, Value::Integer(100));
}
#[test]
fn test_array_get_last_element() {
let arr = Arc::from(vec![Value::Integer(100), Value::Integer(200)]);
let result = eval_array_get(&arr, &Value::Integer(1)).unwrap();
assert_eq!(result, Value::Integer(200));
}
#[test]
fn test_array_nth_first_element() {
let arr = Arc::from(vec![Value::Integer(100)]);
let result = eval_array_nth(&arr, &Value::Integer(0)).unwrap();
match result {
Value::EnumVariant {
variant_name, data, ..
} if variant_name == "Some" => {
assert_eq!(data.unwrap()[0], Value::Integer(100));
}
_ => panic!("Expected Some variant"),
}
}
#[test]
fn test_array_slice_full() {
let arr = Arc::from(vec![
Value::Integer(1),
Value::Integer(2),
Value::Integer(3),
]);
let result = eval_array_slice(&arr, &Value::Integer(0), &Value::Integer(3)).unwrap();
if let Value::Array(sliced) = result {
assert_eq!(sliced.len(), 3);
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_slice_empty() {
let arr = Arc::from(vec![Value::Integer(1), Value::Integer(2)]);
let result = eval_array_slice(&arr, &Value::Integer(1), &Value::Integer(1)).unwrap();
if let Value::Array(sliced) = result {
assert_eq!(sliced.len(), 0);
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_join_empty() {
let arr = Arc::from(Vec::<Value>::new());
let sep = Value::from_string(",".to_string());
let result = eval_array_join(&arr, &sep).unwrap();
if let Value::String(s) = result {
assert!(s.is_empty());
} else {
panic!("Expected string");
}
}
#[test]
fn test_array_join_single_element() {
let arr = Arc::from(vec![Value::from_string("hello".to_string())]);
let sep = Value::from_string(",".to_string());
let result = eval_array_join(&arr, &sep).unwrap();
if let Value::String(s) = result {
assert_eq!(s.as_ref(), "hello");
} else {
panic!("Expected string");
}
}
#[test]
fn test_array_unique_all_same() {
let arr = Arc::from(vec![
Value::Integer(1),
Value::Integer(1),
Value::Integer(1),
]);
let result = eval_array_unique(&arr).unwrap();
if let Value::Array(unique) = result {
assert_eq!(unique.len(), 1);
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_flatten_empty() {
let arr = Arc::from(Vec::<Value>::new());
let result = eval_array_flatten(&arr).unwrap();
if let Value::Array(flat) = result {
assert_eq!(flat.len(), 0);
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_flatten_already_flat() {
let arr = Arc::from(vec![Value::Integer(1), Value::Integer(2)]);
let result = eval_array_flatten(&arr).unwrap();
if let Value::Array(flat) = result {
assert_eq!(flat.len(), 2);
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_union_empty_first() {
let arr = Arc::from(Vec::<Value>::new());
let other = Value::Array(Arc::from(vec![Value::Integer(1)]));
let result = eval_array_union(&arr, &other).unwrap();
if let Value::Array(union_arr) = result {
assert_eq!(union_arr.len(), 1);
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_union_empty_second() {
let arr = Arc::from(vec![Value::Integer(1)]);
let other = Value::Array(Arc::from(Vec::<Value>::new()));
let result = eval_array_union(&arr, &other).unwrap();
if let Value::Array(union_arr) = result {
assert_eq!(union_arr.len(), 1);
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_difference_all_removed() {
let arr = Arc::from(vec![Value::Integer(1), Value::Integer(2)]);
let other = Value::Array(Arc::from(vec![
Value::Integer(1),
Value::Integer(2),
Value::Integer(3),
]));
let result = eval_array_difference(&arr, &other).unwrap();
if let Value::Array(diff) = result {
assert_eq!(diff.len(), 0);
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_difference_none_removed() {
let arr = Arc::from(vec![Value::Integer(1), Value::Integer(2)]);
let other = Value::Array(Arc::from(vec![Value::Integer(3), Value::Integer(4)]));
let result = eval_array_difference(&arr, &other).unwrap();
if let Value::Array(diff) = result {
assert_eq!(diff.len(), 2);
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_sort_strings() {
let arr = Arc::from(vec![
Value::from_string("banana".to_string()),
Value::from_string("apple".to_string()),
Value::from_string("cherry".to_string()),
]);
let result = eval_array_sort(&arr).unwrap();
if let Value::Array(sorted) = result {
assert_eq!(sorted.len(), 3);
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_sort_single() {
let arr = Arc::from(vec![Value::Integer(42)]);
let result = eval_array_sort(&arr).unwrap();
if let Value::Array(sorted) = result {
assert_eq!(sorted.len(), 1);
assert_eq!(sorted[0], Value::Integer(42));
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_first_empty_r159() {
let arr = Arc::from(vec![] as Vec<Value>);
let result = eval_array_first(&arr).unwrap();
assert_eq!(result, Value::Nil);
}
#[test]
fn test_array_first_single_r159() {
let arr = Arc::from(vec![Value::Integer(42)]);
let result = eval_array_first(&arr).unwrap();
assert_eq!(result, Value::Integer(42));
}
#[test]
fn test_array_last_empty_r159() {
let arr = Arc::from(vec![] as Vec<Value>);
let result = eval_array_last(&arr).unwrap();
assert_eq!(result, Value::Nil);
}
#[test]
fn test_array_last_single_r159() {
let arr = Arc::from(vec![Value::Integer(42)]);
let result = eval_array_last(&arr).unwrap();
assert_eq!(result, Value::Integer(42));
}
#[test]
fn test_array_is_empty_true_r159() {
let arr = Arc::from(vec![] as Vec<Value>);
let result = eval_array_is_empty(&arr).unwrap();
assert_eq!(result, Value::Bool(true));
}
#[test]
fn test_array_is_empty_false_r159() {
let arr = Arc::from(vec![Value::Integer(1)]);
let result = eval_array_is_empty(&arr).unwrap();
assert_eq!(result, Value::Bool(false));
}
#[test]
fn test_array_push_r159() {
let arr = Arc::from(vec![Value::Integer(1), Value::Integer(2)]);
let result = eval_array_push(&arr, &Value::Integer(3)).unwrap();
if let Value::Array(new_arr) = result {
assert_eq!(new_arr.len(), 3);
assert_eq!(new_arr[2], Value::Integer(3));
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_pop_r159() {
let arr = Arc::from(vec![
Value::Integer(1),
Value::Integer(2),
Value::Integer(3),
]);
let result = eval_array_pop(&arr).unwrap();
if let Value::Array(new_arr) = result {
assert_eq!(new_arr.len(), 2);
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_pop_empty_r159() {
let arr = Arc::from(vec![] as Vec<Value>);
let result = eval_array_pop(&arr).unwrap();
if let Value::Array(new_arr) = result {
assert_eq!(new_arr.len(), 0);
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_get_valid_r159() {
let arr = Arc::from(vec![Value::Integer(10), Value::Integer(20)]);
let result = eval_array_get(&arr, &Value::Integer(1)).unwrap();
assert_eq!(result, Value::Integer(20));
}
#[test]
fn test_array_get_out_of_bounds_r159() {
let arr = Arc::from(vec![Value::Integer(10)]);
let result = eval_array_get(&arr, &Value::Integer(5)).unwrap();
assert_eq!(result, Value::Nil);
}
#[test]
fn test_array_get_negative_r159() {
let arr = Arc::from(vec![Value::Integer(10)]);
let result = eval_array_get(&arr, &Value::Integer(-1)).unwrap();
assert_eq!(result, Value::Nil);
}
#[test]
fn test_array_get_wrong_type_r159() {
let arr = Arc::from(vec![Value::Integer(10)]);
let result = eval_array_get(&arr, &Value::Bool(true));
assert!(result.is_err());
}
#[test]
fn test_array_nth_valid_r159() {
let arr = Arc::from(vec![Value::Integer(10), Value::Integer(20)]);
let result = eval_array_nth(&arr, &Value::Integer(0)).unwrap();
if let Value::EnumVariant {
variant_name, data, ..
} = result
{
assert_eq!(variant_name, "Some");
assert_eq!(data, Some(vec![Value::Integer(10)]));
} else {
panic!("Expected EnumVariant");
}
}
#[test]
fn test_array_nth_out_of_bounds_r159() {
let arr = Arc::from(vec![Value::Integer(10)]);
let result = eval_array_nth(&arr, &Value::Integer(5)).unwrap();
if let Value::EnumVariant {
variant_name, data, ..
} = result
{
assert_eq!(variant_name, "None");
assert!(data.is_none());
} else {
panic!("Expected EnumVariant");
}
}
#[test]
fn test_array_nth_negative_r159() {
let arr = Arc::from(vec![Value::Integer(10)]);
let result = eval_array_nth(&arr, &Value::Integer(-1)).unwrap();
if let Value::EnumVariant { variant_name, .. } = result {
assert_eq!(variant_name, "None");
} else {
panic!("Expected EnumVariant");
}
}
#[test]
fn test_array_nth_wrong_type_r159() {
let arr = Arc::from(vec![Value::Integer(10)]);
let result = eval_array_nth(&arr, &Value::Bool(true));
assert!(result.is_err());
}
#[test]
fn test_array_contains_true_r159() {
let arr = Arc::from(vec![
Value::Integer(1),
Value::Integer(2),
Value::Integer(3),
]);
let result = eval_array_contains(&arr, &Value::Integer(2)).unwrap();
assert_eq!(result, Value::Bool(true));
}
#[test]
fn test_array_contains_false_r159() {
let arr = Arc::from(vec![Value::Integer(1), Value::Integer(2)]);
let result = eval_array_contains(&arr, &Value::Integer(5)).unwrap();
assert_eq!(result, Value::Bool(false));
}
#[test]
fn test_array_enumerate_r159() {
let arr = Arc::from(vec![
Value::from_string("a".to_string()),
Value::from_string("b".to_string()),
]);
let result = eval_array_enumerate(&arr).unwrap();
if let Value::Array(enumerated) = result {
assert_eq!(enumerated.len(), 2);
if let Value::Tuple(first) = &enumerated[0] {
assert_eq!(first[0], Value::Integer(0));
} else {
panic!("Expected tuple");
}
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_slice_r159() {
let arr = Arc::from(vec![
Value::Integer(1),
Value::Integer(2),
Value::Integer(3),
Value::Integer(4),
]);
let result = eval_array_slice(&arr, &Value::Integer(1), &Value::Integer(3)).unwrap();
if let Value::Array(sliced) = result {
assert_eq!(sliced.len(), 2);
assert_eq!(sliced[0], Value::Integer(2));
assert_eq!(sliced[1], Value::Integer(3));
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_slice_wrong_type_r159() {
let arr = Arc::from(vec![Value::Integer(1)]);
let result = eval_array_slice(&arr, &Value::Bool(true), &Value::Integer(1));
assert!(result.is_err());
}
#[test]
fn test_array_join_r159() {
let arr = Arc::from(vec![
Value::from_string("a".to_string()),
Value::from_string("b".to_string()),
Value::from_string("c".to_string()),
]);
let result = eval_array_join(&arr, &Value::from_string(",".to_string())).unwrap();
assert_eq!(result, Value::from_string("a,b,c".to_string()));
}
#[test]
fn test_array_join_integers_r159() {
let arr = Arc::from(vec![Value::Integer(1), Value::Integer(2)]);
let result = eval_array_join(&arr, &Value::from_string("-".to_string())).unwrap();
assert_eq!(result, Value::from_string("1-2".to_string()));
}
#[test]
fn test_array_join_wrong_type_r159() {
let arr = Arc::from(vec![Value::Integer(1)]);
let result = eval_array_join(&arr, &Value::Integer(1));
assert!(result.is_err());
}
#[test]
fn test_array_unique_r159() {
let arr = Arc::from(vec![
Value::Integer(1),
Value::Integer(2),
Value::Integer(1),
Value::Integer(3),
Value::Integer(2),
]);
let result = eval_array_unique(&arr).unwrap();
if let Value::Array(unique) = result {
assert_eq!(unique.len(), 3);
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_concat_r159() {
let arr1 = Arc::from(vec![Value::Integer(1), Value::Integer(2)]);
let arr2 = Value::Array(Arc::from(vec![Value::Integer(3), Value::Integer(4)]));
let result = eval_array_concat(&arr1, &arr2).unwrap();
if let Value::Array(concatenated) = result {
assert_eq!(concatenated.len(), 4);
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_concat_wrong_type_r159() {
let arr = Arc::from(vec![Value::Integer(1)]);
let result = eval_array_concat(&arr, &Value::Integer(2));
assert!(result.is_err());
}
#[test]
fn test_array_flatten_nested_r159() {
let inner1 = Value::Array(Arc::from(vec![Value::Integer(1), Value::Integer(2)]));
let inner2 = Value::Array(Arc::from(vec![Value::Integer(3), Value::Integer(4)]));
let arr = Arc::from(vec![inner1, inner2]);
let result = eval_array_flatten(&arr).unwrap();
if let Value::Array(flat) = result {
assert_eq!(flat.len(), 4);
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_flatten_mixed_r159() {
let inner = Value::Array(Arc::from(vec![Value::Integer(2), Value::Integer(3)]));
let arr = Arc::from(vec![Value::Integer(1), inner, Value::Integer(4)]);
let result = eval_array_flatten(&arr).unwrap();
if let Value::Array(flat) = result {
assert_eq!(flat.len(), 4);
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_union_r159() {
let arr1 = Arc::from(vec![Value::Integer(1), Value::Integer(2)]);
let arr2 = Value::Array(Arc::from(vec![Value::Integer(2), Value::Integer(3)]));
let result = eval_array_union(&arr1, &arr2).unwrap();
if let Value::Array(union) = result {
assert_eq!(union.len(), 3);
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_union_wrong_type_r159() {
let arr = Arc::from(vec![Value::Integer(1)]);
let result = eval_array_union(&arr, &Value::Integer(2));
assert!(result.is_err());
}
#[test]
fn test_array_intersection_r159() {
let arr1 = Arc::from(vec![
Value::Integer(1),
Value::Integer(2),
Value::Integer(3),
]);
let arr2 = Value::Array(Arc::from(vec![
Value::Integer(2),
Value::Integer(3),
Value::Integer(4),
]));
let result = eval_array_intersection(&arr1, &arr2).unwrap();
if let Value::Array(intersection) = result {
assert_eq!(intersection.len(), 2);
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_intersection_empty_r159() {
let arr1 = Arc::from(vec![Value::Integer(1), Value::Integer(2)]);
let arr2 = Value::Array(Arc::from(vec![Value::Integer(3), Value::Integer(4)]));
let result = eval_array_intersection(&arr1, &arr2).unwrap();
if let Value::Array(intersection) = result {
assert_eq!(intersection.len(), 0);
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_intersection_wrong_type_r159() {
let arr = Arc::from(vec![Value::Integer(1)]);
let result = eval_array_intersection(&arr, &Value::Integer(2));
assert!(result.is_err());
}
#[test]
fn test_array_difference_r159() {
let arr1 = Arc::from(vec![
Value::Integer(1),
Value::Integer(2),
Value::Integer(3),
]);
let arr2 = Value::Array(Arc::from(vec![Value::Integer(2), Value::Integer(4)]));
let result = eval_array_difference(&arr1, &arr2).unwrap();
if let Value::Array(diff) = result {
assert_eq!(diff.len(), 2); } else {
panic!("Expected array");
}
}
#[test]
fn test_array_difference_all_removed_r159() {
let arr1 = Arc::from(vec![Value::Integer(1), Value::Integer(2)]);
let arr2 = Value::Array(Arc::from(vec![
Value::Integer(1),
Value::Integer(2),
Value::Integer(3),
]));
let result = eval_array_difference(&arr1, &arr2).unwrap();
if let Value::Array(diff) = result {
assert_eq!(diff.len(), 0);
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_difference_wrong_type_r159() {
let arr = Arc::from(vec![Value::Integer(1)]);
let result = eval_array_difference(&arr, &Value::Integer(2));
assert!(result.is_err());
}
#[test]
fn test_array_sort_empty_r159() {
let arr = Arc::from(vec![] as Vec<Value>);
let result = eval_array_sort(&arr).unwrap();
if let Value::Array(sorted) = result {
assert_eq!(sorted.len(), 0);
} else {
panic!("Expected array");
}
}
#[test]
fn test_array_sort_integers_r159() {
let arr = Arc::from(vec![
Value::Integer(3),
Value::Integer(1),
Value::Integer(4),
Value::Integer(1),
Value::Integer(5),
]);
let result = eval_array_sort(&arr).unwrap();
if let Value::Array(sorted) = result {
assert_eq!(sorted.len(), 5);
} else {
panic!("Expected array");
}
}
}