#![cfg(test)]
#![allow(warnings)]
#![allow(clippy::assertions_on_constants)]
#![allow(clippy::unreadable_literal)]
#![allow(clippy::unwrap_used)]
use anyhow::Result;
use ruchy::runtime::Repl;
use std::env;
#[test]
fn test_interpreter_basic_arithmetic() -> Result<()> {
let mut interpreter = Repl::new(std::env::temp_dir())?;
let result = interpreter.eval("2 + 3")?;
assert_eq!(result, "5");
let result = interpreter.eval("10 * 4")?;
assert_eq!(result, "40");
let result = interpreter.eval("15 / 3")?;
assert_eq!(result, "5");
Ok(())
}
#[test]
fn test_interpreter_string_operations() -> Result<()> {
let mut interpreter = Repl::new(std::env::temp_dir())?;
let result = interpreter.eval(r#""hello" + " world""#)?;
assert!(result.contains("hello") && result.contains("world"));
let result = interpreter.eval(r#""test".len()"#)?;
let _output = result;
Ok(())
}
#[test]
fn test_interpreter_variable_bindings() -> Result<()> {
let mut interpreter = Repl::new(std::env::temp_dir())?;
let _result = interpreter.eval("let x = 42")?;
let result = interpreter.eval("x")?;
assert_eq!(result, "42");
let _result = interpreter.eval("let x = 99")?;
let result = interpreter.eval("x")?;
assert_eq!(result, "99");
Ok(())
}
#[test]
fn test_interpreter_conditionals() -> Result<()> {
let mut interpreter = Repl::new(std::env::temp_dir())?;
let result = interpreter.eval("if true { 10 } else { 20 }")?;
assert_eq!(result, "10");
let result = interpreter.eval("if false { 10 } else { 20 }")?;
assert_eq!(result, "20");
let result = interpreter.eval("if 5 > 3 { \"yes\" } else { \"no\" }")?;
assert!(result.contains("yes"));
Ok(())
}
#[test]
fn test_interpreter_functions() -> Result<()> {
let mut interpreter = Repl::new(std::env::temp_dir())?;
let _result = interpreter.eval("fn double(x) { x * 2 }")?;
let result = interpreter.eval("double(21)")?;
assert_eq!(result, "42");
Ok(())
}
#[test]
fn test_interpreter_boolean_logic() -> Result<()> {
let mut interpreter = Repl::new(std::env::temp_dir())?;
let result = interpreter.eval("true && false")?;
assert_eq!(result, "false");
let result = interpreter.eval("true || false")?;
assert_eq!(result, "true");
let result = interpreter.eval("!true")?;
assert_eq!(result, "false");
Ok(())
}
#[test]
fn test_interpreter_comparisons() -> Result<()> {
let mut interpreter = Repl::new(std::env::temp_dir())?;
let result = interpreter.eval("5 > 3")?;
assert_eq!(result, "true");
let result = interpreter.eval("2 < 1")?;
assert_eq!(result, "false");
let result = interpreter.eval("4 == 4")?;
assert_eq!(result, "true");
let result = interpreter.eval("3 != 3")?;
assert_eq!(result, "false");
Ok(())
}
#[test]
fn test_interpreter_lists() -> Result<()> {
let mut interpreter = Repl::new(std::env::temp_dir())?;
let result = interpreter.eval("[1, 2, 3]")?;
assert!(result.contains('1') && result.contains('3'));
let _result = interpreter.eval("let numbers = [10, 20, 30]")?;
let result = interpreter.eval("numbers")?;
assert!(result.contains("10"));
Ok(())
}
#[test]
fn test_interpreter_nested_expressions() -> Result<()> {
let mut interpreter = Repl::new(std::env::temp_dir())?;
let result = interpreter.eval("(2 + 3) * (4 - 1)")?;
assert_eq!(result, "15");
let result = interpreter.eval("if (10 > 5) && (3 < 7) { 100 } else { 0 }")?;
assert_eq!(result, "100");
Ok(())
}
#[test]
fn test_interpreter_error_handling() -> Result<()> {
let mut interpreter = Repl::new(std::env::temp_dir())?;
let result = interpreter.eval("10 / 0");
assert!(result.is_ok() || result.is_err());
let result = interpreter.eval("undefined_variable");
assert!(result.is_err());
Ok(())
}
#[test]
fn test_interpreter_pattern_matching() -> Result<()> {
let mut interpreter = Repl::new(std::env::temp_dir())?;
let result = interpreter.eval(
r#"
match 42 {
42 => "found",
_ => "not found"
}
"#,
)?;
assert!(result.contains("found"));
Ok(())
}
#[test]
fn test_interpreter_loops() -> Result<()> {
let mut interpreter = Repl::new(std::env::temp_dir())?;
let result = interpreter.eval(
r"
let sum = 0
for i in [1, 2, 3] {
sum = sum + i
}
sum
",
);
let _output = result.is_ok() || result.is_err();
Ok(())
}
#[test]
fn test_interpreter_state_persistence() -> Result<()> {
let mut interpreter = Repl::new(std::env::temp_dir())?;
let _result = interpreter.eval("let counter = 0")?;
let _result = interpreter.eval("counter = counter + 1")?;
let _result = interpreter.eval("counter = counter + 1")?;
let result = interpreter.eval("counter")?;
let _output = result;
Ok(())
}
#[test]
fn test_repl_commands() -> Result<()> {
let mut interpreter = Repl::new(std::env::temp_dir())?;
let result = interpreter.eval(":help");
let _is_valid = result.is_ok() || result.is_err();
let _result = interpreter.eval("let x = 42");
let result = interpreter.eval(":type x");
let _is_valid = result.is_ok() || result.is_err();
Ok(())
}
#[test]
fn test_interpreter_recursion() -> Result<()> {
let mut interpreter = Repl::new(std::env::temp_dir())?;
let _result = interpreter.eval(
r"
fn factorial(n) {
if n <= 1 {
1
} else {
n * factorial(n - 1)
}
}
",
)?;
let result = interpreter.eval("factorial(5)")?;
assert_eq!(result, "120");
Ok(())
}