Skip to main content

mailang_stdlib/stdlib/
sys.rs

1//! Process / environment builtins.
2
3use mailang_bytecode::Value;
4
5/// `env(name)` → str | null
6pub fn builtin_env(args: &[Value]) -> Result<Value, String> {
7    let name = match args.first() {
8        Some(Value::Str(s)) => s.to_string(),
9        _ => return Err("env(name): name must be string".into()),
10    };
11    match std::env::var(&name) {
12        Ok(v) => Ok(Value::Str(v.into())),
13        Err(_) => Ok(Value::Null),
14    }
15}
16
17/// `process_exit(code)` — terminate the process with `code` (never returns).
18pub fn builtin_process_exit(args: &[Value]) -> Result<Value, String> {
19    let code = match args.first() {
20        Some(Value::Int(n)) => *n as i32,
21        _ => return Err("process_exit(code): code must be int".into()),
22    };
23    std::process::exit(code);
24}
25
26#[cfg(test)]
27mod tests {
28    use super::*;
29
30    #[test]
31    fn env_missing_is_null() {
32        let v = builtin_env(&[Value::Str("MAILANG_DEFINITELY_UNSET_VAR_XYZ".into())]).unwrap();
33        assert_eq!(v, Value::Null);
34    }
35
36    #[test]
37    fn env_reads_present_var() {
38        std::env::set_var("MAILANG_TEST_ENV", "hello");
39        let v = builtin_env(&[Value::Str("MAILANG_TEST_ENV".into())]).unwrap();
40        assert_eq!(v, Value::Str("hello".into()));
41    }
42
43    #[test]
44    fn env_rejects_non_string() {
45        assert!(builtin_env(&[Value::Int(1)]).is_err());
46    }
47}