@@ -38,6 +38,23 @@ impl ModuleId {
3838 pub const ROOT : Self = Self :: MAX ;
3939}
4040
41+ /// A builder for constructing a [`ModuleRegistry`].
42+ ///
43+ /// Collects module definitions during construction (e.g. stdlib registration) and produces
44+ /// an immutable [`ModuleRegistry`] via [`finish`].
45+ ///
46+ /// The typical construction sequence is:
47+ /// 1. Create with [`new_in`]
48+ /// 2. Provision module IDs with [`provision_module`]
49+ /// 3. Insert fully built modules with [`insert_module`]
50+ /// 4. Register root-level modules with [`register`]
51+ /// 5. Finalize into a [`ModuleRegistry`] with [`finish`]
52+ ///
53+ /// [`new_in`]: Self::new_in
54+ /// [`provision_module`]: Self::provision_module
55+ /// [`insert_module`]: Self::insert_module
56+ /// [`register`]: Self::register
57+ /// [`finish`]: Self::finish
4158pub struct PartialModuleRegistry < ' heap , S : Allocator > {
4259 heap : & ' heap Heap ,
4360 modules : IdVec < ModuleId , Option < Module < ' heap > > , S > ,
@@ -54,16 +71,22 @@ impl<'heap, S: Allocator> PartialModuleRegistry<'heap, S> {
5471 }
5572 }
5673
74+ /// Reserves a fresh [`ModuleId`] that can be referenced by child items before the
75+ /// module itself is inserted.
5776 pub fn provision_module ( & mut self ) -> ModuleId {
5877 self . modules . push ( None )
5978 }
6079
61- /// Interns a new module into the registry.
80+ /// Inserts a fully constructed module into the registry.
81+ ///
82+ /// The module's `id` must have been previously obtained from [`provision_module`].
6283 ///
6384 /// # Panics
6485 ///
65- /// In debug builds, this function will panic if any item in the module has a parent
66- /// that doesn't match the module ID.
86+ /// In debug builds, panics if any item in the module references a different module ID
87+ /// than the one being inserted, or if child module metadata is inconsistent.
88+ ///
89+ /// [`provision_module`]: Self::provision_module
6790 pub fn insert_module ( & mut self , module : Module < ' heap > ) {
6891 #[ cfg( debug_assertions) ]
6992 {
@@ -88,11 +111,13 @@ impl<'heap, S: Allocator> PartialModuleRegistry<'heap, S> {
88111 debug_assert ! ( value. is_none( ) ) ;
89112 }
90113
91- /// Register a new module in the root namespace.
114+ /// Registers a module in the root namespace, making it accessible by name .
92115 ///
93116 /// # Panics
94117 ///
95- /// This function will panic if the internal `RwLock` is poisoned.
118+ /// Panics if the module has not been inserted via [`insert_module`].
119+ ///
120+ /// [`insert_module`]: Self::insert_module
96121 pub fn register ( & mut self , module : ModuleId ) {
97122 let module = self
98123 . modules
@@ -104,6 +129,13 @@ impl<'heap, S: Allocator> PartialModuleRegistry<'heap, S> {
104129 self . root . insert ( module. name , module. id ) ;
105130 }
106131
132+ /// Finalizes the builder into an immutable [`ModuleRegistry`].
133+ ///
134+ /// # Panics
135+ ///
136+ /// Panics if any provisioned module ID was never populated via [`insert_module`].
137+ ///
138+ /// [`insert_module`]: Self::insert_module
107139 #[ expect( unsafe_code) ]
108140 pub fn finish ( self , heap : & ' heap Heap ) -> ModuleRegistry < ' heap > {
109141 assert ! (
@@ -146,6 +178,16 @@ pub struct ModuleRegistry<'heap> {
146178}
147179
148180impl < ' heap > ModuleRegistry < ' heap > {
181+ /// Creates a new module registry with the standard library pre-loaded.
182+ ///
183+ /// This initializes the registry with all the standard modules and items
184+ /// defined in the standard library, using the global allocator for scratch space.
185+ pub fn new ( env : & Environment < ' heap > ) -> Self {
186+ Self :: new_in ( env, alloc:: alloc:: Global )
187+ }
188+
189+ /// Creates a new module registry with the standard library pre-loaded, using `scratch`
190+ /// for temporary allocations during construction.
149191 pub fn new_in < S : Allocator + Clone > ( env : & Environment < ' heap > , scratch : S ) -> Self {
150192 let mut partial = PartialModuleRegistry :: new_in ( env. heap , scratch. clone ( ) ) ;
151193
@@ -155,11 +197,7 @@ impl<'heap> ModuleRegistry<'heap> {
155197 partial. finish ( env. heap )
156198 }
157199
158- /// Find an item by name in the root namespace.
159- ///
160- /// # Panics
161- ///
162- /// This function will panic if the internal `RwLock` is poisoned.
200+ /// Looks up a root-level module by name.
163201 #[ must_use]
164202 pub fn find_by_name ( & self , name : Symbol < ' heap > ) -> Option < Module < ' heap > > {
165203 let id = self . root . get ( & name) . copied ( ) ?;
@@ -389,3 +427,49 @@ impl HasId for Module<'_> {
389427 self . id
390428 }
391429}
430+
431+ #[ cfg( test) ]
432+ impl < ' heap > ModuleRegistry < ' heap > {
433+ /// Creates a partially built registry with the stdlib loaded.
434+ ///
435+ /// Returns a `PartialModuleRegistry` that can be further customized (e.g. by inserting
436+ /// test modules) before calling [`PartialModuleRegistry::finish`].
437+ pub ( crate ) fn builder (
438+ env : & Environment < ' heap > ,
439+ ) -> PartialModuleRegistry < ' heap , alloc:: alloc:: Global > {
440+ use alloc:: alloc:: Global ;
441+
442+ let mut partial = PartialModuleRegistry :: new_in ( env. heap , Global ) ;
443+
444+ let mut std = StandardLibrary :: new ( env, & mut partial, Global ) ;
445+ std. register ( ) ;
446+
447+ partial
448+ }
449+ }
450+
451+ #[ cfg( test) ]
452+ impl < ' heap , S : Allocator > PartialModuleRegistry < ' heap , S > {
453+ /// Inserts a root-level module with the given name and items.
454+ ///
455+ /// This is a test helper that provisions a module ID, passes it to the `items` closure
456+ /// so items can reference their owning module, then inserts and registers the module.
457+ pub ( crate ) fn insert_root_module (
458+ & mut self ,
459+ name : Symbol < ' heap > ,
460+ items : impl FnOnce ( ModuleId ) -> & ' heap [ Item < ' heap > ] ,
461+ ) -> ModuleId {
462+ let id = self . provision_module ( ) ;
463+
464+ self . insert_module ( Module {
465+ id,
466+ name,
467+ parent : ModuleId :: ROOT ,
468+ depth : const { NonZero :: new ( 1 ) . unwrap ( ) } ,
469+ items : items ( id) ,
470+ } ) ;
471+ self . register ( id) ;
472+
473+ id
474+ }
475+ }
0 commit comments