Skip to main content

aver/types/
option.rs

1/// Option namespace — combinators for Option<T>.
2///
3/// Methods:
4///   Option.withDefault(option, default) → T              — unwrap Some or return default
5///   Option.toResult(option, err)        → Result<T, E>   — convert Option to Result
6///
7/// Constructors (Some, None) are registered separately in interpreter/core.rs.
8/// No effects required.
9use std::collections::HashMap;
10
11use crate::value::{RuntimeError, Value};
12
13pub fn register(global: &mut HashMap<String, Value>) {
14    // Option namespace already exists (created in interpreter/core.rs for Some/None).
15    // We merge our members into it via a separate step in core.rs.
16    let _ = global;
17}
18
19/// Members to merge into the existing Option namespace.
20pub fn extra_members() -> Vec<(&'static str, String)> {
21    vec![
22        ("withDefault", "Option.withDefault".to_string()),
23        ("toResult", "Option.toResult".to_string()),
24    ]
25}
26
27pub fn effects(_name: &str) -> &'static [&'static str] {
28    &[]
29}
30
31pub fn call(name: &str, args: &[Value]) -> Option<Result<Value, RuntimeError>> {
32    match name {
33        "Option.withDefault" => Some(with_default(args)),
34        "Option.toResult" => Some(to_result(args)),
35        _ => None,
36    }
37}
38
39// ─── Implementations ────────────────────────────────────────────────────────
40
41fn with_default(args: &[Value]) -> Result<Value, RuntimeError> {
42    if args.len() != 2 {
43        return Err(RuntimeError::Error(format!(
44            "Option.withDefault() takes 2 arguments (option, default), got {}",
45            args.len()
46        )));
47    }
48    match &args[0] {
49        Value::Some(v) => Ok(*v.clone()),
50        Value::None => Ok(args[1].clone()),
51        _ => Err(RuntimeError::Error(
52            "Option.withDefault: first argument must be an Option".to_string(),
53        )),
54    }
55}
56
57fn to_result(args: &[Value]) -> Result<Value, RuntimeError> {
58    if args.len() != 2 {
59        return Err(RuntimeError::Error(format!(
60            "Option.toResult() takes 2 arguments (option, err), got {}",
61            args.len()
62        )));
63    }
64    match &args[0] {
65        Value::Some(v) => Ok(Value::Ok(v.clone())),
66        Value::None => Ok(Value::Err(Box::new(args[1].clone()))),
67        _ => Err(RuntimeError::Error(
68            "Option.toResult: first argument must be an Option".to_string(),
69        )),
70    }
71}