1use indexmap::IndexMap;
2
3use crate::value::{BuiltinClosureFn, BuiltinFn, Value};
4
5enum ModuleFn {
6 Function(BuiltinFn),
7 Closure(BuiltinClosureFn),
8}
9
10pub struct Module {
13 pub name: String,
14 functions: IndexMap<String, (String, ModuleFn)>,
15 values: IndexMap<String, Value>,
16 submodules: IndexMap<String, Module>,
17}
18
19impl Module {
20 pub fn new(name: impl Into<String>) -> Self {
21 Self {
22 name: name.into(),
23 functions: IndexMap::new(),
24 values: IndexMap::new(),
25 submodules: IndexMap::new(),
26 }
27 }
28
29 pub fn register_fn(&mut self, name: &str, func: BuiltinFn) {
31 let qualified = format!("{}::{}", self.name, name);
32 self.functions
33 .insert(name.to_string(), (qualified, ModuleFn::Function(func)));
34 }
35
36 pub fn register_closure<F>(&mut self, name: &str, func: F)
38 where
39 F: Fn(&[Value]) -> Result<Value, String> + Send + Sync + 'static,
40 {
41 let qualified = format!("{}::{}", self.name, name);
42 self.functions.insert(
43 name.to_string(),
44 (qualified, ModuleFn::Closure(BuiltinClosureFn::new(func))),
45 );
46 }
47
48 pub fn set(&mut self, name: &str, value: Value) {
50 self.values.insert(name.to_string(), value);
51 }
52
53 pub fn register_submodule(&mut self, sub: Module) {
55 self.submodules.insert(sub.name.clone(), sub);
56 }
57
58 pub fn to_value(&self) -> Value {
61 let mut map = IndexMap::new();
62
63 for (name, (qualified, func)) in &self.functions {
64 let value = match func {
65 ModuleFn::Function(func) => Value::BuiltinFn(qualified.clone(), *func),
66 ModuleFn::Closure(func) => Value::BuiltinClosure(qualified.clone(), func.clone()),
67 };
68 map.insert(name.clone(), value);
69 }
70
71 for (name, value) in &self.values {
72 map.insert(name.clone(), value.clone());
73 }
74
75 for (name, sub) in &self.submodules {
76 map.insert(name.clone(), sub.to_value());
77 }
78
79 Value::Dict(map)
80 }
81
82 pub fn names(&self) -> Vec<String> {
84 let mut names: Vec<String> = self.functions.keys().cloned().collect();
85 names.extend(self.values.keys().cloned());
86 names.extend(self.submodules.keys().cloned());
87 names
88 }
89}