use crate::evaluator::RuntimeError;
use crate::value::Value;
pub fn range(args: &[Value]) -> Result<Value, RuntimeError> {
let (start, end, step) = match args.len() {
1 => {
match &args[0] {
Value::Number(n) => (0.0, *n, 1.0),
_ => {
return Err(RuntimeError::TypeErrorDetailed {
expected: "Number".to_string(),
got: format!("{:?}", args[0]),
});
}
}
}
2 => {
match (&args[0], &args[1]) {
(Value::Number(s), Value::Number(e)) => (*s, *e, 1.0),
_ => {
return Err(RuntimeError::TypeErrorDetailed {
expected: "Number, Number".to_string(),
got: format!("{:?}, {:?}", args[0], args[1]),
});
}
}
}
3 => {
match (&args[0], &args[1], &args[2]) {
(Value::Number(s), Value::Number(e), Value::Number(st)) => (*s, *e, *st),
_ => {
return Err(RuntimeError::TypeErrorDetailed {
expected: "Number, Number, Number".to_string(),
got: format!("{:?}, {:?}, {:?}", args[0], args[1], args[2]),
});
}
}
}
n => {
return Err(RuntimeError::WrongArity {
expected: 1,
got: n,
});
}
};
if step == 0.0 {
return Err(RuntimeError::InvalidOperation(
"Range step cannot be zero".to_string(),
));
}
let mut result = Vec::new();
let mut current = start;
if step > 0.0 {
while current < end {
result.push(Value::Number(current));
current += step;
}
} else {
while current > end {
result.push(Value::Number(current));
current += step;
}
}
Ok(Value::Array(result))
}
pub fn push(args: &[Value]) -> Result<Value, RuntimeError> {
if args.len() != 2 {
return Err(RuntimeError::WrongArity {
expected: 2,
got: args.len(),
});
}
match &args[0] {
Value::Array(arr) => {
let mut new_arr = arr.clone();
new_arr.push(args[1].clone());
Ok(Value::Array(new_arr))
}
_ => Err(RuntimeError::TypeErrorDetailed {
expected: "Array".to_string(),
got: format!("{:?}", args[0]),
}),
}
}
pub fn pop(args: &[Value]) -> Result<Value, RuntimeError> {
if args.len() != 1 {
return Err(RuntimeError::WrongArity {
expected: 1,
got: args.len(),
});
}
match &args[0] {
Value::Array(arr) => {
if arr.is_empty() {
return Err(RuntimeError::InvalidOperation(
"Cannot pop from empty array".to_string(),
));
}
let mut new_arr = arr.clone();
let popped = new_arr.pop().unwrap();
Ok(Value::Array(vec![Value::Array(new_arr), popped]))
}
_ => Err(RuntimeError::TypeErrorDetailed {
expected: "Array".to_string(),
got: format!("{:?}", args[0]),
}),
}
}
pub fn join(args: &[Value]) -> Result<Value, RuntimeError> {
if args.len() != 2 {
return Err(RuntimeError::WrongArity {
expected: 2,
got: args.len(),
});
}
match (&args[0], &args[1]) {
(Value::Array(arr), Value::String(sep)) => {
let strings: Vec<String> = arr.iter().map(|v| v.to_string()).collect();
Ok(Value::String(strings.join(sep)))
}
_ => Err(RuntimeError::TypeErrorDetailed {
expected: "Array, String".to_string(),
got: format!("{:?}, {:?}", args[0], args[1]),
}),
}
}
pub fn reverse(args: &[Value]) -> Result<Value, RuntimeError> {
if args.len() != 1 {
return Err(RuntimeError::WrongArity {
expected: 1,
got: args.len(),
});
}
match &args[0] {
Value::Array(arr) => {
let mut new_arr = arr.clone();
new_arr.reverse();
Ok(Value::Array(new_arr))
}
_ => Err(RuntimeError::TypeErrorDetailed {
expected: "Array".to_string(),
got: format!("{:?}", args[0]),
}),
}
}
pub fn sort(args: &[Value]) -> Result<Value, RuntimeError> {
if args.len() != 1 {
return Err(RuntimeError::WrongArity {
expected: 1,
got: args.len(),
});
}
match &args[0] {
Value::Array(arr) => {
let mut numbers: Vec<f64> = Vec::new();
for val in arr {
match val {
Value::Number(n) => numbers.push(*n),
_ => {
return Err(RuntimeError::TypeErrorDetailed {
expected: "Array of Numbers".to_string(),
got: format!("Array containing {:?}", val),
});
}
}
}
numbers.sort_by(|a, b| a.partial_cmp(b).unwrap());
Ok(Value::Array(
numbers.into_iter().map(Value::Number).collect(),
))
}
_ => Err(RuntimeError::TypeErrorDetailed {
expected: "Array".to_string(),
got: format!("{:?}", args[0]),
}),
}
}
pub fn sum(args: &[Value]) -> Result<Value, RuntimeError> {
if args.len() != 1 {
return Err(RuntimeError::WrongArity {
expected: 1,
got: args.len(),
});
}
match &args[0] {
Value::Array(arr) => {
let mut total = 0.0;
for val in arr {
match val {
Value::Number(n) => total += n,
_ => {
return Err(RuntimeError::TypeErrorDetailed {
expected: "Array of Numbers".to_string(),
got: format!("Array containing {:?}", val),
});
}
}
}
Ok(Value::Number(total))
}
_ => Err(RuntimeError::TypeErrorDetailed {
expected: "Array".to_string(),
got: format!("{:?}", args[0]),
}),
}
}
pub fn max(args: &[Value]) -> Result<Value, RuntimeError> {
if args.len() != 1 {
return Err(RuntimeError::WrongArity {
expected: 1,
got: args.len(),
});
}
match &args[0] {
Value::Array(arr) => {
if arr.is_empty() {
return Err(RuntimeError::InvalidOperation(
"Cannot get max of empty array".to_string(),
));
}
let mut max_val = f64::NEG_INFINITY;
for val in arr {
match val {
Value::Number(n) => {
if *n > max_val {
max_val = *n;
}
}
_ => {
return Err(RuntimeError::TypeErrorDetailed {
expected: "Array of Numbers".to_string(),
got: format!("Array containing {:?}", val),
});
}
}
}
Ok(Value::Number(max_val))
}
_ => Err(RuntimeError::TypeErrorDetailed {
expected: "Array".to_string(),
got: format!("{:?}", args[0]),
}),
}
}
pub fn min(args: &[Value]) -> Result<Value, RuntimeError> {
if args.len() != 1 {
return Err(RuntimeError::WrongArity {
expected: 1,
got: args.len(),
});
}
match &args[0] {
Value::Array(arr) => {
if arr.is_empty() {
return Err(RuntimeError::InvalidOperation(
"Cannot get min of empty array".to_string(),
));
}
let mut min_val = f64::INFINITY;
for val in arr {
match val {
Value::Number(n) => {
if *n < min_val {
min_val = *n;
}
}
_ => {
return Err(RuntimeError::TypeErrorDetailed {
expected: "Array of Numbers".to_string(),
got: format!("Array containing {:?}", val),
});
}
}
}
Ok(Value::Number(min_val))
}
_ => Err(RuntimeError::TypeErrorDetailed {
expected: "Array".to_string(),
got: format!("{:?}", args[0]),
}),
}
}
pub fn map(_args: &[Value]) -> Result<Value, RuntimeError> {
Err(RuntimeError::InvalidOperation(
"MAP requires function evaluation context. Use stdlib implementation or manual loops instead.".to_string(),
))
}
pub fn filter(_args: &[Value]) -> Result<Value, RuntimeError> {
Err(RuntimeError::InvalidOperation(
"FILTER requires function evaluation context. Use stdlib implementation or manual loops instead.".to_string(),
))
}
pub fn reduce(_args: &[Value]) -> Result<Value, RuntimeError> {
Err(RuntimeError::InvalidOperation(
"Reduce requires function evaluation context - use evaluator's reduce implementation"
.to_string(),
))
}