//! Result operations: map, map_err, unwrap_or, unwrap_or_else, and_then, ok. use el_types::{Type, TypeEnv}; use super::fn_type; pub fn register(env: &mut TypeEnv) { // result_unwrap_or(Result, T) -> T let result_unk = Type::Result { ok: Box::new(Type::Unknown), err: Box::new(Type::Unknown), }; env.register_fn("result_unwrap_or", fn_type(vec![result_unk.clone(), Type::Unknown], Type::Unknown)); env.register_fn("result_unwrap_or_else", fn_type( vec![result_unk.clone(), Type::Fn { params: vec![Type::Unknown], return_type: Box::new(Type::Unknown) }], Type::Unknown, )); // result_ok(Result) -> T? env.register_fn("result_ok", fn_type(vec![result_unk.clone()], Type::Optional(Box::new(Type::Unknown)))); // result_err(Result) -> E? env.register_fn("result_err", fn_type(vec![result_unk.clone()], Type::Optional(Box::new(Type::Unknown)))); // result_is_ok(Result) -> Bool env.register_fn("result_is_ok", fn_type(vec![result_unk.clone()], Type::Bool)); // result_is_err(Result) -> Bool env.register_fn("result_is_err", fn_type(vec![result_unk.clone()], Type::Bool)); // result_map(Result, fn(T) -> U) -> Result let mapper = Type::Fn { params: vec![Type::Unknown], return_type: Box::new(Type::Unknown) }; env.register_fn("result_map", fn_type(vec![result_unk.clone(), mapper.clone()], result_unk.clone())); // result_and_then(Result, fn(T) -> Result) -> Result let chain_fn = Type::Fn { params: vec![Type::Unknown], return_type: Box::new(result_unk.clone()) }; env.register_fn("result_and_then", fn_type(vec![result_unk.clone(), chain_fn], result_unk.clone())); // result_ok_val(T) -> Result — wrap a value in Ok env.register_fn("ok", fn_type(vec![Type::Unknown], result_unk.clone())); // result_err_val(E) -> Result — wrap an error in Err env.register_fn("err", fn_type(vec![Type::Unknown], result_unk)); } #[cfg(test)] mod tests { use super::*; fn env() -> TypeEnv { let mut e = TypeEnv::with_builtins(); register(&mut e); e } #[test] fn test_result_unwrap_or_registered() { assert!(env().lookup_fn("result_unwrap_or").is_some()); } #[test] fn test_result_ok_returns_optional() { let e = env(); let ty = e.lookup_fn("result_ok").unwrap(); assert!(matches!(ty, Type::Fn { return_type, .. } if matches!(return_type.as_ref(), Type::Optional(_)))); } #[test] fn test_ok_and_err_registered() { let e = env(); assert!(e.lookup_fn("ok").is_some()); assert!(e.lookup_fn("err").is_some()); } }