Skip to main content

mailang_stdlib/stdlib/
mod.rs

1//! MaìLang standard library
2//!
3//! This module provides built-in functions for MaìLang.
4
5mod convert;
6mod io;
7mod math;
8mod string;
9mod time;
10
11pub use convert::*;
12pub use io::*;
13pub use math::*;
14pub use string::*;
15pub use time::*;
16
17use mailang_bytecode::Value;
18
19// Output capture for WASM builds
20#[cfg(feature = "capture-output")]
21mod capture {
22    use std::sync::Mutex;
23
24    lazy_static::lazy_static! {
25        static ref CAPTURED_OUTPUT: Mutex<Vec<String>> = Mutex::new(Vec::new());
26        static ref IS_CAPTURED: Mutex<bool> = Mutex::new(false);
27    }
28
29    pub fn set_captured(captured: bool) -> bool {
30        let mut is_captured = IS_CAPTURED.lock().unwrap();
31        let prev = *is_captured;
32        *is_captured = captured;
33        if captured {
34            CAPTURED_OUTPUT.lock().unwrap().clear();
35        }
36        prev
37    }
38
39    pub fn get_output() -> Vec<String> {
40        CAPTURED_OUTPUT.lock().unwrap().clone()
41    }
42
43    pub fn is_captured() -> bool {
44        *IS_CAPTURED.lock().unwrap()
45    }
46
47    pub fn push_line(line: String) {
48        CAPTURED_OUTPUT.lock().unwrap().push(line);
49    }
50
51    pub fn push_text(text: String) {
52        let mut output = CAPTURED_OUTPUT.lock().unwrap();
53        if let Some(last) = output.last_mut() {
54            last.push_str(&text);
55        } else {
56            output.push(text);
57        }
58    }
59}
60
61/// Enable or disable output capture mode (only available with capture-output feature).
62#[cfg(feature = "capture-output")]
63pub fn set_println_captured(captured: bool) -> bool {
64    capture::set_captured(captured)
65}
66
67/// Get the captured output lines (only available with capture-output feature).
68#[cfg(feature = "capture-output")]
69pub fn get_captured_output() -> Vec<String> {
70    capture::get_output()
71}
72
73pub fn value_to_string(v: &Value) -> String {
74    match v {
75        Value::Null => "null".to_string(),
76        Value::Bool(b) => b.to_string(),
77        Value::Int(n) => n.to_string(),
78        Value::Float(n) => n.to_string(),
79        Value::Str(s) => s.to_string(),
80        Value::Char(c) => c.to_string(),
81        Value::Array(arr) => {
82            let items: Vec<String> = arr.borrow().iter().map(value_to_string).collect();
83            format!("[{}]", items.join(", "))
84        }
85        Value::Map(m) => {
86            let items: Vec<String> = m
87                .borrow()
88                .iter()
89                .map(|(k, v)| format!("{}: {}", value_to_string(k), value_to_string(v)))
90                .collect();
91            format!("{{{}}}", items.join(", "))
92        }
93        Value::Tuple(t) => {
94            let items: Vec<String> = t.borrow().iter().map(value_to_string).collect();
95            format!("({})", items.join(", "))
96        }
97        Value::Function(f) => format!("<fn {}>", f.name),
98        Value::Closure(c) => format!("<closure {}>", c.function_index),
99        Value::Class(cls) => format!("<class {}>", cls.name),
100        Value::Instance { class_index, .. } => format!("<instance {}>", class_index),
101        Value::Ok(v) => format!("Ok({})", value_to_string(v)),
102        Value::Err(v) => format!("Err({})", value_to_string(v)),
103        Value::Some(v) => format!("Some({})", value_to_string(v)),
104        Value::Builtin { name, .. } => format!("<builtin {}>", name),
105    }
106}