66 lines
2.8 KiB
Rust
66 lines
2.8 KiB
Rust
//! Result<T, E> 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, E>, 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, E>) -> T?
|
|
env.register_fn("result_ok", fn_type(vec![result_unk.clone()], Type::Optional(Box::new(Type::Unknown))));
|
|
// result_err(Result<T, E>) -> E?
|
|
env.register_fn("result_err", fn_type(vec![result_unk.clone()], Type::Optional(Box::new(Type::Unknown))));
|
|
// result_is_ok(Result<T, E>) -> Bool
|
|
env.register_fn("result_is_ok", fn_type(vec![result_unk.clone()], Type::Bool));
|
|
// result_is_err(Result<T, E>) -> Bool
|
|
env.register_fn("result_is_err", fn_type(vec![result_unk.clone()], Type::Bool));
|
|
// result_map(Result<T, E>, fn(T) -> U) -> Result<U, E>
|
|
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<T, E>, fn(T) -> Result<U, E>) -> Result<U, E>
|
|
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<T, E> — wrap a value in Ok
|
|
env.register_fn("ok", fn_type(vec![Type::Unknown], result_unk.clone()));
|
|
// result_err_val(E) -> Result<T, E> — 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());
|
|
}
|
|
}
|