Skip to main content

ion_core/
module.rs

1use indexmap::IndexMap;
2
3use crate::value::{BuiltinFn, Value};
4
5/// A named collection of functions and values that can be registered
6/// with an Engine and accessed via `module::name` syntax in Ion scripts.
7pub struct Module {
8    pub name: String,
9    functions: IndexMap<String, (String, BuiltinFn)>,
10    values: IndexMap<String, Value>,
11    submodules: IndexMap<String, Module>,
12}
13
14impl Module {
15    pub fn new(name: impl Into<String>) -> Self {
16        Self {
17            name: name.into(),
18            functions: IndexMap::new(),
19            values: IndexMap::new(),
20            submodules: IndexMap::new(),
21        }
22    }
23
24    /// Register a builtin function in this module.
25    pub fn register_fn(&mut self, name: &str, func: BuiltinFn) {
26        let qualified = format!("{}::{}", self.name, name);
27        self.functions.insert(name.to_string(), (qualified, func));
28    }
29
30    /// Register a constant value in this module.
31    pub fn set(&mut self, name: &str, value: Value) {
32        self.values.insert(name.to_string(), value);
33    }
34
35    /// Register a submodule (e.g., `net::http`).
36    pub fn register_submodule(&mut self, sub: Module) {
37        self.submodules.insert(sub.name.clone(), sub);
38    }
39
40    /// Convert this module into a `Value::Dict` for use in the interpreter env.
41    /// Functions become `Value::BuiltinFn`, submodules become nested dicts.
42    pub fn to_value(&self) -> Value {
43        let mut map = IndexMap::new();
44
45        for (name, (qualified, func)) in &self.functions {
46            map.insert(name.clone(), Value::BuiltinFn(qualified.clone(), *func));
47        }
48
49        for (name, value) in &self.values {
50            map.insert(name.clone(), value.clone());
51        }
52
53        for (name, sub) in &self.submodules {
54            map.insert(name.clone(), sub.to_value());
55        }
56
57        Value::Dict(map)
58    }
59
60    /// Get all exported names (for `use mod::*`).
61    pub fn names(&self) -> Vec<String> {
62        let mut names: Vec<String> = self.functions.keys().cloned().collect();
63        names.extend(self.values.keys().cloned());
64        names.extend(self.submodules.keys().cloned());
65        names
66    }
67}