bean_script/modules/
registry.rs1use std::{any::Any, cell::RefCell, collections::HashMap, path::PathBuf, rc::Rc};
2
3use crate::{
4 logger::Logger,
5 util::{make_ref, MutRc},
6};
7
8use super::{bean_std, BuiltinModule, CustomModule, Module, ModuleBuilder};
9
10pub(super) enum RegistryEntry {
11 Uninitialized(Box<dyn FnOnce() -> MutRc<dyn Module>>),
12 Available(MutRc<dyn Module>),
13}
14
15impl RegistryEntry {
16 pub fn get_or_init(self) -> MutRc<dyn Module> {
17 match self {
18 Self::Uninitialized(init) => init(),
19 Self::Available(v) => v,
20 }
21 }
22}
23
24#[derive(Clone, Copy)]
25pub struct RegistryFeatures {
26 pub custom_modules: bool,
27 pub import: bool,
28 pub lang_debug: bool,
29}
30
31impl Default for RegistryFeatures {
32 fn default() -> Self {
33 Self {
34 custom_modules: true,
35 import: true,
36 lang_debug: false,
37 }
38 }
39}
40
41pub struct ModuleRegistry {
42 pub(super) registered: HashMap<String, RegistryEntry>,
43 pub(super) local: HashMap<PathBuf, MutRc<CustomModule>>,
44 pub(super) loading: Vec<PathBuf>,
45 runtime: MutRc<BuiltinModule>,
46 pub features: RegistryFeatures,
47 pub logger: Logger,
48 pub metadata: HashMap<String, Box<dyn Any>>,
49}
50
51impl std::fmt::Debug for ModuleRegistry {
52 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
53 f.debug_struct("ModuleRegistry").finish()
54 }
55}
56
57impl ModuleRegistry {
58 pub fn new(features: RegistryFeatures) -> Self {
59 let standard_lib = BuiltinModule::new(bean_std::construct, features);
60 let mut s = Self {
61 registered: HashMap::new(),
62 local: HashMap::new(),
63 loading: Vec::new(),
64 runtime: match RefCell::borrow(
65 &standard_lib.get_submodule("runtime").unwrap(),
66 )
67 .as_any()
68 .downcast_ref::<BuiltinModule>()
69 {
70 Some(r) => Rc::new(RefCell::new(r.clone())),
71 None => panic!("Runtime module is custom?"),
72 },
73 features: RegistryFeatures::default(),
74 logger: Logger::Stdout,
75 metadata: HashMap::new(),
76 };
77 s.registered.insert(
78 String::from("std"),
79 RegistryEntry::Available(make_ref(standard_lib)),
80 );
81 s
82 }
83
84 pub fn register_builtin(
85 &mut self,
86 name: String,
87 constructor: fn(&mut ModuleBuilder),
88 ) {
89 if !self.registered.contains_key(&name) {
90 let features = self.features.clone();
91 self.registered.insert(
92 name,
93 RegistryEntry::Uninitialized(Box::new(move || {
94 make_ref(BuiltinModule::new(constructor, features))
95 })),
96 );
97 } else {
98 panic!("Trying to register a builtin module under a used name.")
99 }
100 }
101
102 pub fn register_initialized_builtin(&mut self, name: String, module: BuiltinModule) {
103 if !self.registered.contains_key(&name) {
104 self.registered
105 .insert(name, RegistryEntry::Available(make_ref(module)));
106 } else {
107 panic!("Trying to register a builtin module under a used name.")
108 }
109 }
110
111 pub fn set_logger(&mut self, logger: Logger) {
112 self.logger = logger;
113 }
114
115 pub fn runtime(&self) -> MutRc<BuiltinModule> {
116 Rc::clone(&self.runtime)
117 }
118}