use aethershell::{env::Env, eval, parser, value::Value};
fn eval_code(code: &str) -> Value {
let mut env = Env::default();
let stmts = parser::parse_program(code).unwrap();
eval::eval_program(&stmts, &mut env).unwrap()
}
#[test]
fn map_reduce_pipeline_double() {
let code = r#"[1,2,3] | map(fn(x)=> x*2) | reduce(fn(a,b)=> a+b, 0)"#;
let out = eval_code(code);
assert!(
matches!(out, Value::Int(12)) || matches!(out, Value::Float(f) if (f - 12.0).abs() < 1e-9)
);
}
#[test]
fn map_reduce_pipeline() {
let code = r#"[1,2,3] | map(fn(x)=> x*2) | reduce(fn(a,b)=> a+b, 0)"#;
let out = eval_code(code);
match out {
Value::Int(12) => {}
Value::Float(f) if (f - 12.0).abs() < 1e-9 => {}
other => panic!("expected 12, got {other}"),
}
}
#[test]
fn pipe_sugar_ident() {
let code = r#"[1,2] | print"#;
let out = eval_code(code);
assert!(matches!(out, Value::Str(_)));
}
#[test]
fn string_concat_and_compare() {
let code = r#""au" + "rora" == "aurora""#;
let out = eval_code(code);
assert!(matches!(out, Value::Bool(true)));
}
#[test]
fn logical_ops() {
let code = r#"true && false || true"#;
let out = eval_code(code);
assert!(matches!(out, Value::Bool(true)));
}
#[test]
fn user_lambda_shadowing_builtin_is_ok() {
let code = r#"let map = 42; [1,2] | map(fn(x)=>x+1) | reduce(fn(a,b)=>a+b, 0)"#;
let out = eval_code(code);
assert!(matches!(out, Value::Int(5)));
}
#[test]
fn lambda_three_args() {
let code = r#"let lerp = fn(a, b, t) => a + (b - a) * t; lerp(0, 10, 0.5)"#;
let out = eval_code(code);
match out {
Value::Int(5) => {}
Value::Float(f) if (f - 5.0).abs() < 1e-9 => {}
other => panic!("expected 5, got {other:?}"),
}
}
#[test]
fn lambda_four_args() {
let code = r#"let f = fn(a, b, c, d) => a * b + c * d; f(2, 3, 4, 5)"#;
let out = eval_code(code);
assert!(matches!(out, Value::Int(26)));
}
#[test]
fn lambda_five_args() {
let code = r#"let f = fn(a, b, c, d, e) => a + b + c + d + e; f(1, 2, 3, 4, 5)"#;
let out = eval_code(code);
assert!(matches!(out, Value::Int(15)));
}