use aethershell::env::Env;
use aethershell::eval::eval_program;
use aethershell::parser::parse_program;
fn run(src: &str) -> anyhow::Result<aethershell::value::Value> {
let stmts = parse_program(src)?;
let mut env = Env::new();
eval_program(&stmts, &mut env)
}
#[test]
fn async_lambda_parses() {
let result = parse_program("let f = async fn(x) => x * 2");
assert!(result.is_ok(), "Failed to parse async lambda: {:?}", result);
}
#[test]
fn await_expression_parses() {
let result = parse_program("let x = await future_val");
assert!(result.is_ok(), "Failed to parse await: {:?}", result);
}
#[test]
fn async_lambda_returns_async_lambda_value() {
let result = run("async fn(x) => x * 2");
assert!(result.is_ok());
let val = result.unwrap();
assert_eq!(val.type_name(), "AsyncLambda");
}
#[test]
fn calling_async_lambda_returns_future() {
let result = run(r#"
let f = async fn(x) => x * 2
f(5)
"#);
assert!(result.is_ok(), "Failed to call async lambda: {:?}", result);
let val = result.unwrap();
assert_eq!(val.type_name(), "Future");
}
#[test]
fn await_executes_future() {
let result = run(r#"
let f = async fn(x) => x * 2
await f(5)
"#);
assert!(result.is_ok(), "Failed to await: {:?}", result);
let val = result.unwrap();
assert_eq!(val, aethershell::value::Value::Int(10));
}
#[test]
fn await_on_non_future_returns_value() {
let result = run("await 42");
assert!(result.is_ok());
let val = result.unwrap();
assert_eq!(val, aethershell::value::Value::Int(42));
}
#[test]
fn async_lambda_multi_arg() {
let result = run(r#"
let add = async fn(a, b) => a + b
await add(3, 4)
"#);
assert!(result.is_ok(), "Failed: {:?}", result);
let val = result.unwrap();
assert_eq!(val, aethershell::value::Value::Int(7));
}
#[test]
fn nested_await() {
let result = run(r#"
let double = async fn(x) => x * 2
let triple = async fn(x) => x * 3
await double(await triple(2))
"#);
assert!(result.is_ok(), "Failed: {:?}", result);
let val = result.unwrap();
assert_eq!(val, aethershell::value::Value::Int(12));
}
#[test]
fn async_in_pipeline_context() {
let result = parse_program("map async fn(x) => x * 2");
assert!(
result.is_ok(),
"Failed to parse async in pipeline: {:?}",
result
);
}
#[test]
fn await_unary_precedence() {
let result = run("await 1 + 2"); assert!(result.is_ok());
let val = result.unwrap();
assert_eq!(val, aethershell::value::Value::Int(3));
}
#[test]
fn async_lambda_with_string() {
let result = run(r#"
let greet = async fn(name) => "Hello, " + name
await greet("World")
"#);
assert!(result.is_ok(), "Failed: {:?}", result);
let val = result.unwrap();
assert_eq!(
val,
aethershell::value::Value::Str("Hello, World".to_string())
);
}
#[test]
fn type_of_async_lambda() {
let result = run(r#"
let f = async fn(x) => x
type_of(f)
"#);
assert!(result.is_ok(), "Failed: {:?}", result);
let val = result.unwrap();
assert_eq!(
val,
aethershell::value::Value::Str("AsyncLambda".to_string())
);
}
#[test]
fn type_of_future() {
let result = run(r#"
let f = async fn(x) => x
let future = f(42)
type_of(future)
"#);
assert!(result.is_ok(), "Failed: {:?}", result);
let val = result.unwrap();
assert_eq!(val, aethershell::value::Value::Str("Future".to_string()));
}