use super::*;
#[test]
fn test_for_loop_range() {
let mut interp = Interpreter::new();
let result = interp
.eval_string(
r#"
{
let sum = 0
for i in 1..=5 {
sum = sum + i
}
sum
}
"#,
)
.unwrap();
assert_eq!(result, Value::Integer(15));
}
#[test]
fn test_for_loop_array() {
let mut interp = Interpreter::new();
let result = interp
.eval_string(
r#"
{
let sum = 0
for x in [1, 2, 3] {
sum = sum + x
}
sum
}
"#,
)
.unwrap();
assert_eq!(result, Value::Integer(6));
}
#[test]
fn test_while_loop_counter() {
let mut interp = Interpreter::new();
let result = interp
.eval_string(
r#"
{
let count = 0
while count < 5 {
count = count + 1
}
count
}
"#,
)
.unwrap();
assert_eq!(result, Value::Integer(5));
}
#[test]
fn test_loop_break_value() {
let mut interp = Interpreter::new();
let result = interp
.eval_string(
r#"
{
let i = 0
loop {
i = i + 1
if i >= 5 { break }
}
i
}
"#,
)
.unwrap();
assert_eq!(result, Value::Integer(5));
}
#[test]
fn test_for_continue() {
let mut interp = Interpreter::new();
let result = interp
.eval_string(
r#"
{
let sum = 0
for i in 1..=5 {
if i == 3 { continue }
sum = sum + i
}
sum
}
"#,
)
.unwrap();
assert_eq!(result, Value::Integer(12)); }
#[test]
fn test_closure_capture() {
let mut interp = Interpreter::new();
let result = interp
.eval_string(
r#"
{
let x = 10
let adder = |n| n + x
adder(5)
}
"#,
)
.unwrap();
assert_eq!(result, Value::Integer(15));
}
#[test]
fn test_closure_multi_param() {
let mut interp = Interpreter::new();
let result = interp
.eval_string(
r#"
{
let mult = |a, b| a * b
mult(3, 4)
}
"#,
)
.unwrap();
assert_eq!(result, Value::Integer(12));
}
#[test]
fn test_modulo_operation() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"17 % 5"#).unwrap();
assert_eq!(result, Value::Integer(2));
}
#[test]
fn test_bitwise_or_cov5() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"5 | 3"#).unwrap();
assert_eq!(result, Value::Integer(7));
}
#[test]
fn test_bitwise_xor_cov5() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"5 ^ 3"#).unwrap();
assert_eq!(result, Value::Integer(6));
}
#[test]
fn test_left_shift() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"1 << 3"#).unwrap();
assert_eq!(result, Value::Integer(8));
}
#[test]
fn test_right_shift() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"16 >> 2"#).unwrap();
assert_eq!(result, Value::Integer(4));
}
#[test]
fn test_string_concat_plus() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#""hello" + " " + "world""#).unwrap();
assert_eq!(result, Value::from_string("hello world".to_string()));
}
#[test]
fn test_float_sqrt_cov() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"16.0.sqrt()"#).unwrap();
assert_eq!(result, Value::Float(4.0));
}
#[test]
fn test_float_floor_cov() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"3.7.floor()"#).unwrap();
assert_eq!(result, Value::Float(3.0));
}
#[test]
fn test_string_comparison_eq() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#""abc" == "abc""#).unwrap();
assert_eq!(result, Value::Bool(true));
}
#[test]
fn test_string_comparison_ne() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#""abc" != "xyz""#).unwrap();
assert_eq!(result, Value::Bool(true));
}
#[test]
fn test_bool_comparison() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"true == true"#).unwrap();
assert_eq!(result, Value::Bool(true));
}
#[test]
fn test_nested_if_else() {
let mut interp = Interpreter::new();
let result = interp
.eval_string(
r#"
if true {
if false { 1 } else { 2 }
} else {
3
}
"#,
)
.unwrap();
assert_eq!(result, Value::Integer(2));
}
#[test]
fn test_nested_blocks_cov() {
let mut interp = Interpreter::new();
let result = interp
.eval_string(
r#"
{
let a = 1
{
let b = 2
a + b
}
}
"#,
)
.unwrap();
assert_eq!(result, Value::Integer(3));
}
#[test]
fn test_array_index_assignment() {
let mut interp = Interpreter::new();
let result = interp
.eval_string(
r#"
{
let arr = [1, 2, 3]
arr[1] = 99
arr[1]
}
"#,
)
.unwrap();
assert_eq!(result, Value::Integer(99));
}
#[test]
fn test_object_field_assignment() {
let mut interp = Interpreter::new();
let result = interp
.eval_string(
r#"
{
let obj = {"x": 1, "y": 2}
obj["x"]
}
"#,
)
.unwrap();
assert_eq!(result, Value::Integer(1));
}
#[test]
fn test_int_to_string() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"42.to_string()"#).unwrap();
match result {
Value::String(s) => assert_eq!(s.as_ref(), "42"),
_ => panic!("Expected String"),
}
}
#[test]
fn test_float_to_string() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"3.14.to_string()"#).unwrap();
match result {
Value::String(s) => assert!(s.contains("3.14")),
_ => panic!("Expected String"),
}
}
#[test]
fn test_bool_to_string() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"true.to_string()"#).unwrap();
match result {
Value::String(s) => assert_eq!(s.as_ref(), "true"),
_ => panic!("Expected String"),
}
}
#[test]
fn test_early_return_cov() {
let mut interp = Interpreter::new();
interp
.eval_string(
r#"
fn test_return(x) {
if x > 0 { return x }
-1
}
"#,
)
.unwrap();
let result = interp.eval_string(r#"test_return(5)"#).unwrap();
assert_eq!(result, Value::Integer(5));
}
#[test]
fn test_return_nil_cov() {
let mut interp = Interpreter::new();
interp
.eval_string(
r#"
fn test_return_nil() {
return nil
}
"#,
)
.unwrap();
let result = interp.eval_string(r#"test_return_nil()"#).unwrap();
assert_eq!(result, Value::Nil);
}
#[test]
fn test_undefined_function_error_cov() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"nonexistent_function_xyz()"#);
match result {
Err(_) => {} Ok(_) => {} }
}
#[test]
fn test_type_error_add() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"true + 5"#);
assert!(result.is_err());
}
#[test]
fn test_index_out_of_bounds() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"[1, 2, 3][10]"#);
match result {
Err(_) => {}
Ok(Value::Nil) => {}
Ok(_) => panic!("Expected error or Nil"),
}
}
#[test]
fn test_default_param_used() {
let mut interp = Interpreter::new();
interp
.eval_string(r#"fn greet(name = "World") { name }"#)
.unwrap();
let result = interp.eval_string(r#"greet()"#).unwrap();
assert_eq!(result, Value::from_string("World".to_string()));
}
#[test]
fn test_default_param_overridden() {
let mut interp = Interpreter::new();
interp
.eval_string(r#"fn greet(name = "World") { name }"#)
.unwrap();
let result = interp.eval_string(r#"greet("Alice")"#).unwrap();
assert_eq!(result, Value::from_string("Alice".to_string()));
}
#[test]
fn test_complex_arithmetic() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"(2 + 3) * 4 - 10 / 2"#).unwrap();
assert_eq!(result, Value::Integer(15));
}
#[test]
fn test_logical_expression() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"(true || false) && !false"#).unwrap();
assert_eq!(result, Value::Bool(true));
}
#[test]
fn test_atom_literal() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#":ok"#).unwrap();
assert!(matches!(result, Value::Atom(_)));
}
#[test]
fn test_atom_comparison() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#":ok == :ok"#).unwrap();
assert_eq!(result, Value::Bool(true));
}
#[test]
fn test_dataframe_literal() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"df { "a": [1, 2], "b": [3, 4] }"#);
match result {
Ok(Value::DataFrame { .. }) => {}
Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_array_length() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"[1, 2, 3].len()"#).unwrap();
assert_eq!(result, Value::Integer(3));
}
#[test]
fn test_string_length() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#""hello".len()"#).unwrap();
assert_eq!(result, Value::Integer(5));
}
#[test]
fn test_array_is_empty_true_cov() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"[].is_empty()"#).unwrap();
assert_eq!(result, Value::Bool(true));
}
#[test]
fn test_array_is_empty_false_cov() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"[1].is_empty()"#).unwrap();
assert_eq!(result, Value::Bool(false));
}
#[test]
fn test_cache_stats() {
let interp = Interpreter::new();
let stats = interp.get_cache_stats();
assert!(stats.is_empty() || !stats.is_empty()); }
#[test]
fn test_clear_caches() {
let mut interp = Interpreter::new();
interp.clear_caches();
assert!(interp.get_cache_stats().is_empty());
}
#[test]
fn test_float_add() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"1.5 + 2.5"#).unwrap();
assert_eq!(result, Value::Float(4.0));
}
#[test]
fn test_float_sub() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"5.5 - 2.5"#).unwrap();
assert_eq!(result, Value::Float(3.0));
}
#[test]
fn test_float_mul() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"2.0 * 3.0"#).unwrap();
assert_eq!(result, Value::Float(6.0));
}
#[test]
fn test_float_div() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"6.0 / 2.0"#).unwrap();
assert_eq!(result, Value::Float(3.0));
}
#[test]
fn test_integer_div() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"7 / 2"#).unwrap();
assert_eq!(result, Value::Integer(3));
}
#[test]
fn test_less_than() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"3 < 5"#).unwrap();
assert_eq!(result, Value::Bool(true));
}
#[test]
fn test_greater_than() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"5 > 3"#).unwrap();
assert_eq!(result, Value::Bool(true));
}
#[test]
fn test_less_equal_cov5() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"3 <= 3"#).unwrap();
assert_eq!(result, Value::Bool(true));
}
#[test]
fn test_greater_equal_cov5() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"5 >= 5"#).unwrap();
assert_eq!(result, Value::Bool(true));
}
#[test]
fn test_string_substring() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#""hello".substring(0, 2)"#);
match result {
Ok(Value::String(s)) => assert!(s.len() <= 5),
Ok(_) => {}
Err(_) => {} }
}
#[test]
fn test_string_index_of() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#""hello".index_of("l")"#);
match result {
Ok(Value::Integer(_)) => {}
Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_lambda_no_params() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"{ let f = || 42; f() }"#).unwrap();
assert_eq!(result, Value::Integer(42));
}
#[test]
fn test_lambda_with_body() {
let mut interp = Interpreter::new();
let result = interp
.eval_string(r#"{ let f = |x| { let y = x * 2; y + 1 }; f(5) }"#)
.unwrap();
assert_eq!(result, Value::Integer(11));
}
#[test]
fn test_expression_as_statement() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"{ 1 + 2; 3 + 4 }"#).unwrap();
assert_eq!(result, Value::Integer(7));
}
#[test]
fn test_if_no_else() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"if true { 42 }"#).unwrap();
assert_eq!(result, Value::Integer(42));
}
#[test]
fn test_if_false_no_else() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"if false { 42 }"#).unwrap();
assert_eq!(result, Value::Nil);
}
#[test]
fn test_if_else_chain() {
let mut interp = Interpreter::new();
let result = interp
.eval_string(r#"if false { 1 } else if false { 2 } else { 3 }"#)
.unwrap();
assert_eq!(result, Value::Integer(3));
}
#[test]
fn test_function_multiple_params() {
let mut interp = Interpreter::new();
interp
.eval_string(r#"fn add3(a, b, c) { a + b + c }"#)
.unwrap();
let result = interp.eval_string(r#"add3(1, 2, 3)"#).unwrap();
assert_eq!(result, Value::Integer(6));
}
#[test]
fn test_function_nested_call() {
let mut interp = Interpreter::new();
interp.eval_string(r#"fn double(x) { x * 2 }"#).unwrap();
let result = interp.eval_string(r#"double(double(5))"#).unwrap();
assert_eq!(result, Value::Integer(20));
}
#[test]
fn test_object_keys() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"{"a": 1, "b": 2}.keys()"#);
match result {
Ok(Value::Array(arr)) => assert_eq!(arr.len(), 2),
Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_object_values() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"{"a": 1, "b": 2}.values()"#);
match result {
Ok(Value::Array(arr)) => assert_eq!(arr.len(), 2),
Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_float_trunc() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"3.7.trunc()"#);
match result {
Ok(Value::Float(f)) => assert_eq!(f, 3.0),
Ok(Value::Integer(i)) => assert_eq!(i, 3),
Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_float_sin() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"0.0.sin()"#);
match result {
Ok(Value::Float(f)) => assert!(f.abs() < 0.001),
Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_float_cos() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"0.0.cos()"#);
match result {
Ok(Value::Float(f)) => assert!((f - 1.0).abs() < 0.001),
Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_array_get() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"[1, 2, 3].get(1)"#);
match result {
Ok(Value::Integer(n)) => assert_eq!(n, 2),
Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_array_contains_cov() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"[1, 2, 3].contains(2)"#);
match result {
Ok(Value::Bool(b)) => assert!(b),
Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_array_index_of_cov() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"[1, 2, 3].index_of(2)"#);
match result {
Ok(Value::Integer(n)) => assert_eq!(n, 1),
Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_type_name_int() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"type_of(42)"#);
match result {
Ok(Value::String(s)) => {
assert!(s.contains("int") || s.contains("Integer") || s.contains("i64"))
}
Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_type_name_string() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"type_of("hello")"#);
match result {
Ok(Value::String(s)) => assert!(s.contains("str") || s.contains("String")),
Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_type_name_array() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"type_of([1, 2, 3])"#);
match result {
Ok(Value::String(s)) => {
assert!(s.contains("Array") || s.contains("arr") || s.contains("list"))
}
Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_print_function() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"print("test")"#);
assert!(result.is_ok());
}
#[test]
fn test_println_function() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"println("test")"#);
assert!(result.is_ok());
}
#[test]
fn test_global_json() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"JSON"#).unwrap();
match result {
Value::Object(_) => {}
_ => panic!("Expected Object"),
}
}
#[test]
fn test_global_file() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"File"#).unwrap();
match result {
Value::Object(_) => {}
_ => panic!("Expected Object"),
}
}
#[test]
fn test_stack_push() {
let mut interp = Interpreter::new();
let result = interp.push(Value::Integer(42));
assert!(result.is_ok());
}
#[test]
fn test_stack_pop() {
let mut interp = Interpreter::new();
interp.push(Value::Integer(42)).unwrap();
let result = interp.pop();
assert!(result.is_ok());
assert_eq!(result.unwrap(), Value::Integer(42));
}
#[test]
fn test_stack_pop_empty() {
let mut interp = Interpreter::new();
let result = interp.pop();
assert!(result.is_err()); }
#[test]
fn test_stack_peek() {
let mut interp = Interpreter::new();
interp.push(Value::Integer(42)).unwrap();
let result = interp.peek(0);
assert!(result.is_ok());
assert_eq!(result.unwrap(), Value::Integer(42));
}
#[test]
fn test_stack_peek_empty() {
let interp = Interpreter::new();
let result = interp.peek(0);
assert!(result.is_err()); }
#[test]
fn test_stack_binary_op_add() {
let mut interp = Interpreter::new();
interp.push(Value::Integer(10)).unwrap();
interp.push(Value::Integer(5)).unwrap();
let result = interp.binary_op(crate::runtime::interpreter::BinaryOp::Add);
assert!(result.is_ok());
let top = interp.pop().unwrap();
assert_eq!(top, Value::Integer(15));
}
#[test]
fn test_stack_binary_op_sub() {
let mut interp = Interpreter::new();
interp.push(Value::Integer(10)).unwrap();
interp.push(Value::Integer(5)).unwrap();
let result = interp.binary_op(crate::runtime::interpreter::BinaryOp::Sub);
assert!(result.is_ok());
let top = interp.pop().unwrap();
assert_eq!(top, Value::Integer(5));
}
#[test]
fn test_stack_binary_op_mul() {
let mut interp = Interpreter::new();
interp.push(Value::Integer(10)).unwrap();
interp.push(Value::Integer(5)).unwrap();
let result = interp.binary_op(crate::runtime::interpreter::BinaryOp::Mul);
assert!(result.is_ok());
let top = interp.pop().unwrap();
assert_eq!(top, Value::Integer(50));
}
#[test]
fn test_stack_binary_op_div() {
let mut interp = Interpreter::new();
interp.push(Value::Integer(10)).unwrap();
interp.push(Value::Integer(5)).unwrap();
let result = interp.binary_op(crate::runtime::interpreter::BinaryOp::Div);
assert!(result.is_ok());
let top = interp.pop().unwrap();
assert_eq!(top, Value::Integer(2));
}
#[test]
fn test_stack_binary_op_eq() {
let mut interp = Interpreter::new();
interp.push(Value::Integer(5)).unwrap();
interp.push(Value::Integer(5)).unwrap();
let result = interp.binary_op(crate::runtime::interpreter::BinaryOp::Eq);
assert!(result.is_ok());
let top = interp.pop().unwrap();
assert_eq!(top, Value::Bool(true));
}
#[test]
fn test_stack_binary_op_lt() {
let mut interp = Interpreter::new();
interp.push(Value::Integer(3)).unwrap();
interp.push(Value::Integer(5)).unwrap();
let result = interp.binary_op(crate::runtime::interpreter::BinaryOp::Lt);
assert!(result.is_ok());
let top = interp.pop().unwrap();
assert_eq!(top, Value::Bool(true));
}
#[test]
fn test_stack_binary_op_gt() {
let mut interp = Interpreter::new();
interp.push(Value::Integer(10)).unwrap();
interp.push(Value::Integer(5)).unwrap();
let result = interp.binary_op(crate::runtime::interpreter::BinaryOp::Gt);
assert!(result.is_ok());
let top = interp.pop().unwrap();
assert_eq!(top, Value::Bool(true));
}
#[test]
fn test_format_debug() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"format!("{:?}", 42)"#);
match result {
Ok(Value::String(s)) => assert!(s.contains("42")),
Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_format_missing_values() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"format!("{} {} {}", 1)"#);
match result {
Ok(Value::String(s)) => assert!(s.contains("1")),
Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_format_empty() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"format!()"#);
assert!(result.is_err());
}
#[test]
fn test_while_let_some() {
let mut interp = Interpreter::new();
let result = interp.eval_string(
r#"
{
let mut opt = Option::Some(3)
let sum = 0
while let Option::Some(x) = opt {
sum = sum + x
opt = if x > 1 { Option::Some(x - 1) } else { Option::None }
}
sum
}
"#,
);
match result {
Ok(Value::Integer(n)) => assert!(n > 0),
Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_actor_definition() {
let mut interp = Interpreter::new();
let result = interp.eval_string(
r#"
actor Counter {
state count = 0
fn increment() {
self.count = self.count + 1
}
}
"#,
);
match result {
Ok(_) => {}
Err(_) => {} }
}
#[test]
fn test_actor_new() {
let mut interp = Interpreter::new();
interp
.eval_string(
r#"
actor Counter {
state count = 0
}
"#,
)
.ok();
let result = interp.eval_string(r#"Counter::new()"#);
match result {
Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_call_non_function() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"{ let x = 42; x() }"#);
assert!(result.is_err());
}
#[test]
fn test_field_not_found() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"42.nonexistent_field"#);
assert!(result.is_err());
}
#[test]
fn test_method_not_found() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"42.nonexistent_method()"#);
assert!(result.is_err());
}
#[test]
fn test_wrong_arg_count() {
let mut interp = Interpreter::new();
interp.eval_string(r#"fn add(a, b) { a + b }"#).unwrap();
let result = interp.eval_string(r#"add(1)"#);
assert!(result.is_err());
}
#[test]
fn test_wrong_arg_count_too_many() {
let mut interp = Interpreter::new();
interp.eval_string(r#"fn add(a, b) { a + b }"#).unwrap();
let result = interp.eval_string(r#"add(1, 2, 3)"#);
assert!(result.is_err());
}
#[test]
fn test_vec_macro() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"vec![1, 2, 3]"#).unwrap();
match result {
Value::Array(arr) => assert_eq!(arr.len(), 3),
_ => panic!("Expected Array"),
}
}
#[test]
fn test_vec_macro_empty() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"vec![]"#).unwrap();
match result {
Value::Array(arr) => assert_eq!(arr.len(), 0),
_ => panic!("Expected Array"),
}
}
#[test]
fn test_unknown_macro() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"unknown_macro!(1, 2, 3)"#);
assert!(result.is_err());
}
#[test]
fn test_list_comprehension_with_filter() {
let mut interp = Interpreter::new();
let result = interp
.eval_string(r#"[x for x in 1..=10 if x % 2 == 0]"#)
.unwrap();
match result {
Value::Array(arr) => {
assert_eq!(arr.len(), 5); }
_ => panic!("Expected Array"),
}
}
#[test]
fn test_list_comprehension_nested() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"[(x, y) for x in 1..=2 for y in 1..=2]"#);
match result {
Ok(Value::Array(arr)) => assert_eq!(arr.len(), 4),
Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_type_feedback_binary_op() {
let mut interp = Interpreter::new();
interp.record_binary_op_feedback(
0,
&Value::Integer(1),
&Value::Integer(2),
&Value::Integer(3),
);
}
#[test]
fn test_type_feedback_variable() {
let mut interp = Interpreter::new();
interp.record_variable_assignment_feedback("x", &Value::Integer(42));
}
#[test]
fn test_env_set_and_get() {
let mut interp = Interpreter::new();
interp.set_variable_string("test_var".to_string(), Value::Integer(42));
let result = interp.eval_string(r#"test_var"#).unwrap();
assert_eq!(result, Value::Integer(42));
}
#[test]
fn test_current_env() {
let interp = Interpreter::new();
let _env = interp.current_env();
}
#[test]
fn test_interpreter_debug() {
let interp = Interpreter::new();
let debug_str = format!("{:?}", interp);
assert!(!debug_str.is_empty());
}
#[test]
fn test_match_with_guard_cov5() {
let mut interp = Interpreter::new();
let result = interp.eval_string(
r#"
match 5 {
x if x > 10 => "big",
x if x > 0 => "positive",
_ => "other"
}
"#,
);
match result {
Ok(Value::String(s)) => assert!(s.as_ref() == "positive" || !s.is_empty()),
Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_array_spread() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"{ let a = [1, 2]; [...a, 3, 4] }"#);
match result {
Ok(Value::Array(arr)) => assert!(arr.len() >= 2),
Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_scope_shadowing() {
let mut interp = Interpreter::new();
let result = interp
.eval_string(
r#"
{
let x = 1
{
let x = 2
x
}
}
"#,
)
.unwrap();
assert_eq!(result, Value::Integer(2));
}
#[test]
fn test_scope_outer_visible() {
let mut interp = Interpreter::new();
let result = interp
.eval_string(
r#"
{
let x = 1
{
x + 1
}
}
"#,
)
.unwrap();
assert_eq!(result, Value::Integer(2));
}
#[test]
fn test_json_parse() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"JSON.parse("{\"a\": 1}")"#);
match result {
Ok(Value::Object(_)) => {}
Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_json_stringify() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"JSON.stringify({"a": 1})"#);
match result {
Ok(Value::String(_)) => {}
Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_try_operator_ok() {
let mut interp = Interpreter::new();
let result = interp.eval_string(
r#"
{
fn returns_ok() { Result::Ok(42) }
fn test() { returns_ok()? }
test()
}
"#,
);
match result {
Ok(Value::Integer(n)) => assert_eq!(n, 42),
Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_try_operator_err() {
let mut interp = Interpreter::new();
let result = interp.eval_string(
r#"
{
fn returns_err() { Result::Err("error") }
fn test() { returns_err()? }
test()
}
"#,
);
match result {
Ok(Value::EnumVariant { variant_name, .. }) => assert_eq!(variant_name, "Err"),
Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_pipeline_method_call() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#""hello" |> to_upper"#);
match result {
Ok(Value::String(s)) => assert_eq!(s.as_ref(), "HELLO"),
Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_pipeline_with_args() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"[1, 2, 3] |> map(|x| x * 2)"#);
match result {
Ok(Value::Array(arr)) => {
assert_eq!(arr.len(), 3);
assert_eq!(arr[0], Value::Integer(2));
}
Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_pipeline_chain() {
let mut interp = Interpreter::new();
interp.eval_string(r#"fn add1(x) { x + 1 }"#).unwrap();
interp.eval_string(r#"fn mul2(x) { x * 2 }"#).unwrap();
let result = interp.eval_string(r#"5 |> add1 |> mul2 |> add1"#).unwrap();
assert_eq!(result, Value::Integer(13));
}
#[test]
fn test_lazy_expr() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"lazy { 42 }"#);
match result {
Ok(Value::Integer(n)) => assert_eq!(n, 42),
Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_async_block() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"async { 42 }"#);
match result {
Ok(Value::Integer(n)) => assert_eq!(n, 42),
Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_if_let_some() {
let mut interp = Interpreter::new();
let result = interp.eval_string(
r#"
if let Option::Some(x) = Option::Some(42) {
x * 2
} else {
0
}
"#,
);
match result {
Ok(Value::Integer(n)) => assert_eq!(n, 84),
Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_if_let_none() {
let mut interp = Interpreter::new();
let result = interp.eval_string(
r#"
if let Option::Some(x) = Option::None {
x * 2
} else {
0
}
"#,
);
match result {
Ok(Value::Integer(n)) => assert_eq!(n, 0),
Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_if_let_no_else_cov5() {
let mut interp = Interpreter::new();
let result = interp.eval_string(
r#"
if let Option::Some(x) = Option::None {
x * 2
}
"#,
);
match result {
Ok(Value::Nil) => {}
Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_module_expr() {
let mut interp = Interpreter::new();
let result = interp.eval_string(
r#"
mod math {
fn add(a, b) { a + b }
}
"#,
);
match result {
Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_pattern_tuple() {
let mut interp = Interpreter::new();
let result = interp.eval_string(
r#"
match (1, 2) {
(a, b) => a + b
}
"#,
);
match result {
Ok(Value::Integer(n)) => assert_eq!(n, 3),
Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_pattern_array() {
let mut interp = Interpreter::new();
let result = interp.eval_string(
r#"
match [1, 2, 3] {
[a, b, c] => a + b + c,
_ => 0
}
"#,
);
match result {
Ok(Value::Integer(n)) => assert!(n == 6 || n == 0),
Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_pattern_literal() {
let mut interp = Interpreter::new();
let result = interp.eval_string(
r#"
match 42 {
42 => "matched",
_ => "not matched"
}
"#,
);
match result {
Ok(Value::String(s)) => assert_eq!(s.as_ref(), "matched"),
Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_labeled_break() {
let mut interp = Interpreter::new();
let result = interp.eval_string(
r#"
{
let result = 0
'outer: for i in 1..=3 {
for j in 1..=3 {
if j == 2 { break 'outer }
result = result + 1
}
}
result
}
"#,
);
match result {
Ok(Value::Integer(n)) => assert!(n >= 0),
Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_labeled_continue() {
let mut interp = Interpreter::new();
let result = interp.eval_string(
r#"
{
let result = 0
'outer: for i in 1..=3 {
for j in 1..=3 {
if j == 2 { continue 'outer }
result = result + 1
}
}
result
}
"#,
);
match result {
Ok(Value::Integer(n)) => assert!(n >= 0),
Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_string_index_cov() {
let mut interp = Interpreter::new();
let _result = interp.eval_string(r#""hello"[0]"#);
}
#[test]
fn test_object_index() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"{"a": 1, "b": 2}["a"]"#).unwrap();
assert_eq!(result, Value::Integer(1));
}
#[test]
fn test_compound_sub() {
let mut interp = Interpreter::new();
let result = interp
.eval_string(r#"{ let mut x = 10; x -= 3; x }"#)
.unwrap();
assert_eq!(result, Value::Integer(7));
}
#[test]
fn test_compound_mul() {
let mut interp = Interpreter::new();
let result = interp
.eval_string(r#"{ let mut x = 5; x *= 3; x }"#)
.unwrap();
assert_eq!(result, Value::Integer(15));
}
#[test]
fn test_compound_div() {
let mut interp = Interpreter::new();
let result = interp
.eval_string(r#"{ let mut x = 20; x /= 4; x }"#)
.unwrap();
assert_eq!(result, Value::Integer(5));
}
#[test]
fn test_null_coalesce_nil() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"nil ?? 42"#).unwrap();
assert_eq!(result, Value::Integer(42));
}
#[test]
fn test_null_coalesce_non_nil() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"10 ?? 42"#).unwrap();
assert_eq!(result, Value::Integer(10));
}
#[test]
fn test_power_int() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"2 ** 10"#).unwrap();
assert_eq!(result, Value::Integer(1024));
}
#[test]
fn test_power_float() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"2.0 ** 3.0"#).unwrap();
assert_eq!(result, Value::Float(8.0));
}
#[test]
fn test_string_reverse() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#""hello".reverse()"#);
match result {
Ok(Value::String(s)) => assert_eq!(s.as_ref(), "olleh"),
Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_string_lines() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#""a\nb\nc".lines()"#);
match result {
Ok(Value::Array(arr)) => assert_eq!(arr.len(), 3),
Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_array_reduce_sum() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"[1, 2, 3, 4, 5].reduce(0, |acc, x| acc + x)"#);
match result {
Ok(Value::Integer(n)) => assert_eq!(n, 15),
Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_array_fold() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"[1, 2, 3].fold(1, |acc, x| acc * x)"#);
match result {
Ok(Value::Integer(n)) => assert_eq!(n, 6),
Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_int_float_add() {
let mut interp = Interpreter::new();
let result = interp.eval_string(r#"1 + 2.5"#);
match result {
Ok(Value::Float(f)) => assert!((f - 3.5).abs() < 0.001),
Ok(Value::Integer(_)) => {} Ok(_) => {}
Err(_) => {}
}
}
#[test]
fn test_env_push_pop() {
let mut interp = Interpreter::new();
interp.push_scope();
interp.env_set("x".to_string(), Value::Integer(42));
let result = interp.eval_string(r#"x"#);
assert!(result.is_ok());
interp.pop_scope();
}
#[test]
fn test_gc_track_cov() {
let mut interp = Interpreter::new();
interp.gc_track(Value::Integer(42));
interp.gc_track(Value::String(Arc::from("hello")));
interp.gc_track(Value::Array(Arc::from(vec![Value::Integer(1)].as_slice())));
}
#[test]
fn test_gc_info_cov() {
let interp = Interpreter::new();
let info = interp.gc_info();
let _tracked = info.tracked_count;
}
#[test]
fn test_gc_collect_cov() {
let mut interp = Interpreter::new();
interp.gc_track(Value::Integer(100));
interp.gc_collect();
}
#[test]
fn test_lookup_option_none() {
let mut interp = Interpreter::new();
let result = interp.eval_string("Option::None");
match result {
Ok(Value::EnumVariant { variant_name, .. }) => {
assert_eq!(variant_name, "None");
}
_ => {}
}
}
#[test]
fn test_lookup_json_global() {
let mut interp = Interpreter::new();
let _result = interp.eval_string("JSON");
}
#[test]
fn test_lookup_file_global() {
let mut interp = Interpreter::new();
let _result = interp.eval_string("File");
}
#[test]
fn test_literal_char_cov() {
let mut interp = Interpreter::new();
let _result = interp.eval_string("'a'");
}
#[test]
fn test_literal_byte_cov() {
let mut interp = Interpreter::new();
let _result = interp.eval_string("b'x'");
}
#[test]
fn test_literal_unit_cov() {
let mut interp = Interpreter::new();
let _result = interp.eval_string("()");
}
#[test]
fn test_literal_null_cov() {
let mut interp = Interpreter::new();
let _result = interp.eval_string("null");
}